This adds typed asset APIs to the geo client, covers the 3D/image upload-share flow in integration tests, and introduces a simple Leaflet web demo that places objects on map features and manages sharing visibility via backend links. Made-with: Cursor
This commit is contained in:
@@ -130,9 +130,65 @@
|
||||
</v-row>
|
||||
<div v-for="f in featuresFor(selectedCollection().id)" :key="f.id" class="d-flex align-center py-2 mb-1 rounded px-2" style="background: rgba(255,255,255,0.05)">
|
||||
<span class="flex-grow-1">{{ formatFeature(f).name }} ({{ formatFeature(f).lon }}, {{ formatFeature(f).lat }})</span>
|
||||
<v-btn
|
||||
variant="tonal"
|
||||
size="small"
|
||||
class="mr-2"
|
||||
:color="state.selectedFeatureId === f.id ? 'primary' : undefined"
|
||||
@click="selectFeature(f.id)"
|
||||
>
|
||||
{{ state.selectedFeatureId === f.id ? 'Selected' : 'Select' }}
|
||||
</v-btn>
|
||||
<v-btn variant="outlined" color="error" size="small" @click="removeFeature(selectedCollection().id, f.id)">Remove</v-btn>
|
||||
</div>
|
||||
<div v-if="featuresFor(selectedCollection().id).length === 0" class="text-medium-emphasis text-caption py-2">No features. Add a point above.</div>
|
||||
|
||||
<v-divider class="my-4"></v-divider>
|
||||
<v-card variant="tonal" class="pa-3">
|
||||
<v-card-subtitle class="mb-2">Asset example flow (images + 3D)</v-card-subtitle>
|
||||
<div class="text-caption mb-2">
|
||||
Select a feature, choose a file, then upload. The backend stores metadata and links it under
|
||||
<code>feature.properties.assets</code>.
|
||||
</div>
|
||||
<v-alert v-if="!selectedFeature()" type="info" variant="tonal" density="compact" class="mb-2">
|
||||
Select a feature to enable asset actions.
|
||||
</v-alert>
|
||||
<div v-else class="text-caption mb-2">
|
||||
Target feature: <strong>{{ formatFeature(selectedFeature()).name }}</strong> ({{ selectedFeature().id }})
|
||||
</div>
|
||||
<input type="file" @change="onAssetFileChange" :disabled="!selectedFeature()" />
|
||||
<div class="text-caption mt-1 mb-2" v-if="state.selectedAssetFileName">Selected: {{ state.selectedAssetFileName }}</div>
|
||||
<v-row dense>
|
||||
<v-col cols="12" sm="4">
|
||||
<v-text-field v-model="state.newAssetName" label="Asset name" density="compact" hide-details></v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-text-field v-model="state.newAssetDescription" label="Asset description" density="compact" hide-details></v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="2">
|
||||
<v-btn color="primary" size="small" :disabled="!selectedFeature()" @click="createAndUploadAsset">Upload</v-btn>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<div v-if="selectedFeature() && formatFeature(selectedFeature()).assets.length > 0" class="mt-3">
|
||||
<div class="text-caption mb-2">Linked assets:</div>
|
||||
<div
|
||||
v-for="asset in formatFeature(selectedFeature()).assets"
|
||||
:key="asset.id"
|
||||
class="d-flex align-center py-2 px-2 mb-1 rounded"
|
||||
style="background: rgba(255,255,255,0.05)"
|
||||
>
|
||||
<div class="flex-grow-1 text-caption">
|
||||
<div><strong>{{ asset.kind }}</strong> • {{ asset.ext }} • {{ asset.id }}</div>
|
||||
<div>Visibility: {{ asset.isPublic ? "public" : "private" }}</div>
|
||||
</div>
|
||||
<v-btn variant="outlined" size="small" class="mr-2" @click="openAssetLink(asset)">Open</v-btn>
|
||||
<v-btn variant="tonal" size="small" @click="toggleAssetVisibility(asset)">
|
||||
Set {{ asset.isPublic ? "Private" : "Public" }}
|
||||
</v-btn>
|
||||
</div>
|
||||
</div>
|
||||
</v-card>
|
||||
</v-card>
|
||||
</v-card>
|
||||
</v-col>
|
||||
|
||||
Reference in New Issue
Block a user