Add public map with JWT admin login and protect admin APIs.
Keep map reads open; gate admin UI/nav and object mutations behind env-based admin credentials, and default parser batch limit to 10. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -4,11 +4,15 @@ import { onMounted, onUnmounted, watch } from "vue";
|
||||
import { useLeafletMap } from "../composables/useLeafletMap";
|
||||
import type { MapObjectWithEvent } from "../types/map";
|
||||
|
||||
const props = defineProps<{
|
||||
objects: MapObjectWithEvent[];
|
||||
selectedId: number | null;
|
||||
openPopupId: number | null;
|
||||
}>();
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
objects: MapObjectWithEvent[];
|
||||
selectedId: number | null;
|
||||
openPopupId: number | null;
|
||||
editable?: boolean;
|
||||
}>(),
|
||||
{ editable: false },
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
select: [object: MapObjectWithEvent];
|
||||
@@ -53,7 +57,7 @@ function buildPopupHtml(obj: MapObjectWithEvent): string {
|
||||
}
|
||||
|
||||
function isDraggable(obj: MapObjectWithEvent): boolean {
|
||||
return obj.id === props.selectedId && !obj.event_id;
|
||||
return props.editable && obj.id === props.selectedId && !obj.event_id;
|
||||
}
|
||||
|
||||
function syncMarkers() {
|
||||
@@ -170,7 +174,7 @@ onUnmounted(() => {
|
||||
});
|
||||
|
||||
watch(
|
||||
() => [props.objects, props.selectedId] as const,
|
||||
() => [props.objects, props.selectedId, props.editable] as const,
|
||||
() => {
|
||||
syncMarkers();
|
||||
panToSelected(false);
|
||||
|
||||
@@ -9,9 +9,13 @@ import {
|
||||
import { MEDIA_ACCEPT, OBJECT_TYPE_LABELS } from "../types/object";
|
||||
import type { MapObjectWithEvent } from "../types/map";
|
||||
|
||||
const props = defineProps<{
|
||||
object: MapObjectWithEvent | null;
|
||||
}>();
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
object: MapObjectWithEvent | null;
|
||||
canEdit?: boolean;
|
||||
}>(),
|
||||
{ canEdit: false },
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
openEvents: [];
|
||||
@@ -151,7 +155,7 @@ watch(() => props.object?.id, () => loadMedia(), { immediate: true });
|
||||
<section v-if="!isIngested" class="media-section">
|
||||
<div class="media-header">
|
||||
<h4>Медиа</h4>
|
||||
<label class="upload-btn">
|
||||
<label v-if="canEdit" class="upload-btn">
|
||||
{{ uploading ? "Загрузка..." : "Добавить" }}
|
||||
<input
|
||||
type="file"
|
||||
@@ -185,7 +189,14 @@ watch(() => props.object?.id, () => loadMedia(), { immediate: true });
|
||||
<span class="name" :title="item.original_name">{{ item.original_name }}</span>
|
||||
<span class="size">{{ formatFileSize(item.size) }}</span>
|
||||
</div>
|
||||
<button type="button" class="delete-btn" @click="handleDelete(item.id)">Удалить</button>
|
||||
<button
|
||||
v-if="canEdit"
|
||||
type="button"
|
||||
class="delete-btn"
|
||||
@click="handleDelete(item.id)"
|
||||
>
|
||||
Удалить
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
Reference in New Issue
Block a user