2023-09-12 09:15:28 +00:00
< script setup lang = "ts" >
2023-10-06 23:13:51 +00:00
import { computed , ref , watch } from "vue" ;
2023-11-02 14:14:05 +00:00
import type { CRU , PadData } from "facilmap-types" ;
2023-11-07 01:19:20 +00:00
import { generateRandomPadId } from "facilmap-utils" ;
2023-09-12 09:15:28 +00:00
import { getUniqueId , mergeObject } from "../../utils/utils" ;
2023-11-07 01:19:20 +00:00
import { cloneDeep , isEqual } from "lodash-es" ;
2023-10-30 00:14:54 +00:00
import ModalDialog from "../ui/modal-dialog.vue" ;
import { useToasts } from "../ui/toasts/toasts.vue" ;
2023-10-06 23:13:51 +00:00
import { showConfirm } from "../ui/alert.vue" ;
import PadIdEdit from "./pad-id-edit.vue" ;
2023-11-06 02:22:33 +00:00
import { injectContextRequired , requireClientContext } from "../facil-map-context-provider/facil-map-context-provider.vue" ;
2023-09-12 09:15:28 +00:00
const context = injectContextRequired ( ) ;
2023-11-06 02:22:33 +00:00
const client = requireClientContext ( context ) ;
2023-09-12 09:15:28 +00:00
2023-10-30 00:14:54 +00:00
const toasts = useToasts ( ) ;
2023-09-12 09:15:28 +00:00
const props = defineProps < {
proposedAdminId ? : string ;
noCancel ? : boolean ;
isCreate ? : boolean ;
} > ( ) ;
const emit = defineEmits < {
2023-11-01 18:45:16 +00:00
hidden : [ ] ;
2023-09-12 09:15:28 +00:00
} > ( ) ;
2023-10-06 23:13:51 +00:00
const id = getUniqueId ( "fm-pad-settings" ) ;
2023-09-12 09:15:28 +00:00
const isDeleting = ref ( false ) ;
const deleteConfirmation = ref ( "" ) ;
2023-11-07 01:19:20 +00:00
const initialPadData : PadData < CRU .CREATE > | undefined = props . isCreate ? {
2023-10-06 23:13:51 +00:00
name : "New FacilMap" ,
searchEngines : false ,
description : "" ,
clusterMarkers : false ,
adminId : ( props . proposedAdminId || generateRandomPadId ( 16 ) ) ,
writeId : generateRandomPadId ( 14 ) ,
id : generateRandomPadId ( 12 ) ,
legend1 : "" ,
legend2 : "" ,
defaultViewId : null
2023-11-07 01:19:20 +00:00
} : undefined ;
const originalPadData = computed ( ( ) => props . isCreate ? initialPadData ! : client . value . padData as PadData < CRU .CREATE > ) ;
const padData = ref ( cloneDeep ( originalPadData . value ) ) ;
2023-10-06 23:13:51 +00:00
2023-11-01 18:45:16 +00:00
const modalRef = ref < InstanceType < typeof ModalDialog > > ( ) ;
2023-09-12 09:15:28 +00:00
2023-11-07 01:19:20 +00:00
const isModified = computed ( ( ) => ! isEqual ( padData . value , originalPadData . value ) ) ;
2023-09-12 09:15:28 +00:00
2023-11-06 02:22:33 +00:00
watch ( ( ) => client . value . padData , ( newPadData , oldPadData ) => {
2023-10-06 23:13:51 +00:00
if ( ! props . isCreate && padData . value && newPadData )
mergeObject ( oldPadData , newPadData , padData . value as PadData ) ;
2023-09-12 09:15:28 +00:00
} , { deep : true } ) ;
async function save ( ) : Promise < void > {
2023-10-30 00:14:54 +00:00
toasts . hideToast ( ` fm ${ context . id } -pad-settings-error ` ) ;
2023-09-12 09:15:28 +00:00
try {
if ( props . isCreate )
2023-11-06 02:22:33 +00:00
await client . value . createPad ( padData . value as PadData < CRU .CREATE > ) ;
2023-09-12 09:15:28 +00:00
else
2023-11-06 02:22:33 +00:00
await client . value . editPad ( padData . value ) ;
2023-11-01 18:45:16 +00:00
modalRef . value ? . modal . hide ( ) ;
2023-09-12 09:15:28 +00:00
} catch ( err ) {
2023-10-30 00:14:54 +00:00
toasts . showErrorToast ( ` fm ${ context . id } -pad-settings-error ` , props . isCreate ? "Error creating map" : "Error saving map settings" , err ) ;
2023-09-12 09:15:28 +00:00
}
} ;
2021-03-04 15:45:34 +00:00
2023-09-12 09:15:28 +00:00
async function deletePad ( ) : Promise < void > {
2023-10-30 00:14:54 +00:00
toasts . hideToast ( ` fm ${ context . id } -pad-settings-error ` ) ;
2023-09-12 09:15:28 +00:00
if ( ! await showConfirm ( {
title : "Delete map" ,
message : ` Are you sure you want to delete the map “ ${ padData . value . name } ”? Deleted maps cannot be restored! ` ,
variant : "danger"
} ) ) {
return ;
}
isDeleting . value = true ;
try {
2023-11-06 02:22:33 +00:00
await client . value . deletePad ( ) ;
2023-11-01 18:45:16 +00:00
modalRef . value ? . modal . hide ( ) ;
2023-09-12 09:15:28 +00:00
} catch ( err ) {
2023-10-30 00:14:54 +00:00
toasts . showErrorToast ( ` fm ${ context . id } -pad-settings-error ` , "Error deleting map" , err ) ;
2023-09-12 09:15:28 +00:00
} finally {
isDeleting . value = false ;
}
} ;
< / script >
< template >
2023-10-30 00:14:54 +00:00
< ModalDialog
2023-11-07 01:19:20 +00:00
: title = "props.isCreate ? 'Create collaborative map' : 'Map settings'"
2023-10-30 00:14:54 +00:00
class = "fm-pad-settings"
2023-11-07 01:19:20 +00:00
: noCancel = "props.noCancel"
2023-11-01 18:45:16 +00:00
: isBusy = "isDeleting"
2023-11-07 01:19:20 +00:00
: isCreate = "props.isCreate"
2023-11-01 18:45:16 +00:00
: isModified = "isModified"
2023-11-07 01:19:20 +00:00
: okLabel = "props.isCreate ? 'Create' : undefined"
2023-11-01 18:45:16 +00:00
ref = "modalRef"
2023-10-30 00:14:54 +00:00
@ submit = "$event.waitUntil(save())"
2023-11-01 18:45:16 +00:00
@ hidden = "emit('hidden')"
2023-10-06 23:13:51 +00:00
>
< template v-if ="padData" >
< PadIdEdit
: padData = "padData"
idProp = "adminId"
2023-11-01 18:45:16 +00:00
v - model = "padData.adminId"
2023-10-06 23:13:51 +00:00
label = "Admin link"
description = "When opening the map through this link, all parts of the map can be edited, including the map settings, object types and views."
> < / PadIdEdit >
< PadIdEdit
: padData = "padData"
idProp = "writeId"
2023-11-01 18:45:16 +00:00
v - model = "padData.writeId"
2023-10-06 23:13:51 +00:00
label = "Editable link"
description = "When opening the map through this link, markers and lines can be added, changed and deleted, but the map settings, object types and views cannot be modified."
> < / PadIdEdit >
< PadIdEdit
: padData = "padData"
idProp = "id"
2023-11-01 18:45:16 +00:00
v - model = "padData.id"
2023-10-06 23:13:51 +00:00
label = "Read-only link"
description = "When opening the map through this link, markers, lines and views can be seen, but nothing can be changed."
> < / PadIdEdit >
< div class = "row mb-3" >
< label :for ="`${id}-pad-name-input`" class = "col-sm-3 col-form-label" > Map name < / label >
< div class = "col-sm-9" >
2023-11-07 01:19:20 +00:00
< input
: id = "`${id}-pad-name-input`"
class = "form-control"
type = "text"
v - model = "padData.name"
/ >
2023-10-06 23:13:51 +00:00
< / div >
< / div >
< div class = "row mb-3" >
< label :for ="`${id}-search-engines-input`" class = "col-sm-3 col-form-label" > Search engines < / label >
< div class = "col-sm-9" >
2023-11-07 01:19:20 +00:00
< div class = "form-check fm-form-check-with-label" >
< input
: id = "`${id}-search-engines-input`"
class = "form-check-input"
type = "checkbox"
v - model = "padData.searchEngines"
/ >
< label :for ="`${id}-search-engines-input`" class = "form-check-label" >
Accessible for search engines
< / label >
< / div >
2023-10-06 23:13:51 +00:00
< div class = "form-text" >
2023-09-12 09:15:28 +00:00
If this is enabled , search engines like Google will be allowed to add the read - only version of this map .
2023-10-06 23:13:51 +00:00
< / div >
< / div >
< / div >
< div class = "row mb-3" >
< label :for ="`${id}-description-input`" class = "col-sm-3 col-form-label" > Short description < / label >
< div class = "col-sm-9" >
2023-11-07 01:19:20 +00:00
< input
: id = "`${id}-description-input`"
class = "form-control"
type = "text"
v - model = "padData.description"
/ >
2023-10-06 23:13:51 +00:00
< div class = "form-text" >
2023-09-12 09:15:28 +00:00
This description will be shown under the result in search engines .
2023-10-06 23:13:51 +00:00
< / div >
< / div >
< / div >
< div class = "row mb-3" >
< label :for ="`${id}-cluster-markers-input`" class = "col-sm-3 col-form-label" > Search engines < / label >
< div class = "col-sm-9" >
2023-11-07 01:19:20 +00:00
< div class = "form-check fm-form-check-with-label" >
< input
: id = "`${id}-cluster-markers-input`"
class = "form-check-input"
type = "checkbox"
v - model = "padData.clusterMarkers"
/ >
< label :for ="`${id}-cluster-markers-input`" class = "form-check-label" >
Cluster markers
< / label >
< / div >
2023-10-06 23:13:51 +00:00
< div class = "form-text" >
2023-09-12 09:15:28 +00:00
If enabled , when there are many markers in one area , they will be replaced by a placeholder at low zoom levels . This improves performance on maps with many markers .
2023-10-06 23:13:51 +00:00
< / div >
< / div >
< / div >
< div class = "row mb-3" >
< label :for ="`${id}-legend1-input`" class = "col-sm-3 col-form-label" > Legend text < / label >
< div class = "col-sm-9" >
2023-11-07 01:19:20 +00:00
< textarea
: id = "`${id}-legend1-input`"
class = "form-control"
type = "text"
v - model = "padData.legend1"
> < / textarea >
< textarea
: id = "`${id}-legend2-input`"
class = "form-control mt-1"
type = "text"
v - model = "padData.legend2"
> < / textarea >
2023-10-06 23:13:51 +00:00
< div class = "form-text" >
2023-09-12 09:15:28 +00:00
Text that will be shown above and below the legend . Can be formatted with < a href = "http://commonmark.org/help/" target = "_blank" > Markdown < / a > .
2023-10-06 23:13:51 +00:00
< / div >
< / div >
< / div >
< / template >
2023-11-07 01:19:20 +00:00
< template v-if ="padData && !props.isCreate" >
2023-10-06 23:13:51 +00:00
< hr / >
< div class = "row mb-3" >
< label :for ="`${id}-delete-input`" class = "col-sm-3 col-form-label" > Delete map < / label >
< div class = "col-sm-9" >
< div class = "input-group" >
2023-11-07 01:19:20 +00:00
< input
: form = "`${id}-delete-form`"
: id = "`${id}-delete-input`"
class = "form-control"
type = "text"
v - model = "deleteConfirmation"
/ >
< button
: form = "`${id}-delete-form`"
class = "btn btn-danger"
type = "submit"
: disabled = "isDeleting || modalRef?.formData?.isSubmitting || deleteConfirmation != 'DELETE'"
>
2023-10-06 23:13:51 +00:00
< div v-if ="isDeleting" class="spinner-border spinner-border-sm" > < / div >
Delete map
< / button >
< / div >
< div class = "form-text" >
To delete this map , type < code > DELETE < / code > into the field and click the “ Delete map ” button .
< / div >
< / div >
< / div >
< / template >
2023-10-30 00:14:54 +00:00
< / ModalDialog >
2023-10-06 23:13:51 +00:00
< form :id ="`${id}-delete-form`" @ submit.prevent = " deleteConfirmation = = ' DELETE ' & & deletePad ( ) " >
< / form >
< / template >