- Creazione "AbitareGliIblei"
- Mappa Interattiva con i markers
This commit is contained in:
@@ -7,6 +7,8 @@
|
||||
// @ts-ignore
|
||||
import { boot } from 'quasar/wrappers'
|
||||
|
||||
import { useGlobalStore } from '@src/store/globalStore';
|
||||
|
||||
export default boot(({ app, router }) => {
|
||||
// ******************************************
|
||||
// *** Per non permettere di accedere alle pagine in cui è necessario essere Loggati ! ***
|
||||
@@ -16,6 +18,39 @@ export default boot(({ app, router }) => {
|
||||
// runs the default `next()` callback but also triggers
|
||||
// the subsequent Middleware function.
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
console.log('beforeEach ROUTER')
|
||||
// Execute your command before each navigation
|
||||
// executeCommand();
|
||||
|
||||
const globalStore = useGlobalStore()
|
||||
try {
|
||||
globalStore.editOn = false
|
||||
} catch(e) {
|
||||
|
||||
}
|
||||
|
||||
next()
|
||||
|
||||
/* const answer = window.confirm('Do you really want to leave? you have unsaved changes!')
|
||||
if (answer) {
|
||||
next()
|
||||
} else {
|
||||
next(false)
|
||||
}
|
||||
*/
|
||||
|
||||
//if (to.matched.some(record => record.meta.requiresAuth) && !userStore.isLogged) {
|
||||
// next({ name: 'login', query: { next: to.fullPath } })
|
||||
//} else {
|
||||
// next()
|
||||
//}
|
||||
|
||||
|
||||
// Continue with the navigation
|
||||
|
||||
});
|
||||
|
||||
/* router.beforeEach((to, from, next) => {
|
||||
var accessToken = store.state.session.userSession.accessToken
|
||||
// ESTANDO LOGEADO
|
||||
|
||||
20
src/boot/vue-html-to-paper.ts.off
Normal file
20
src/boot/vue-html-to-paper.ts.off
Normal file
@@ -0,0 +1,20 @@
|
||||
import { boot } from 'quasar/wrappers';
|
||||
import { VueHtmlToPaper } from 'vue-html-to-paper';
|
||||
|
||||
const options = {
|
||||
name: '_blank',
|
||||
specs: [
|
||||
'fullscreen=yes',
|
||||
'titlebar=yes',
|
||||
'scrollbars=yes'
|
||||
],
|
||||
styles: [
|
||||
'https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css',
|
||||
// Aggiungi qui i link ai tuoi stili CSS, se necessario
|
||||
]
|
||||
};
|
||||
|
||||
// Definisce un componente di boot per Vue
|
||||
export default boot(({ app }) => {
|
||||
app.use(VueHtmlToPaper, options);
|
||||
});
|
||||
@@ -164,6 +164,8 @@ export const shared_consts = {
|
||||
MAPPA: 350,
|
||||
MAPPAUTENTI: 360,
|
||||
MAPPACOMUNI: 370,
|
||||
MAPPAGETCOORDINATE: 380,
|
||||
EDITADDRESSBYCOORD: 390,
|
||||
},
|
||||
|
||||
QUERYTYPE_MYGROUP: 1,
|
||||
@@ -1764,6 +1766,14 @@ export const shared_consts = {
|
||||
value: 370,
|
||||
label: 'MAPPACOMUNI',
|
||||
},
|
||||
{
|
||||
value: 380,
|
||||
label: 'MAPPA GET COORD',
|
||||
},
|
||||
{
|
||||
value: 390,
|
||||
label: 'EDIT ADDRESS BY COORD',
|
||||
},
|
||||
|
||||
],
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ export default defineComponent({
|
||||
formato: [],
|
||||
Categoria: [],
|
||||
Editore: [],
|
||||
pdf: false,
|
||||
}),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -65,6 +65,7 @@ export default defineComponent({
|
||||
formato: [],
|
||||
Categoria: [],
|
||||
Editore: [],
|
||||
pdf: false,
|
||||
}),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
v-if="complete"
|
||||
position="bottom-right"
|
||||
:offset="[18, 0]"
|
||||
style="z-index: 1000;"
|
||||
style="z-index: 1000"
|
||||
>
|
||||
<q-btn
|
||||
fab
|
||||
@@ -57,11 +57,6 @@
|
||||
}"
|
||||
@click="click_opendetail()"
|
||||
>
|
||||
<!--@click="
|
||||
complete
|
||||
? toggleFullScreen
|
||||
: naviga(`/catalogo/` + myproduct._id + '/' + cosa)
|
||||
"-->
|
||||
<div
|
||||
class="absolute transparent"
|
||||
style="left: 90%; top: -18px; transform: translateX(-50%)"
|
||||
@@ -77,6 +72,12 @@
|
||||
</div>
|
||||
</q-img>
|
||||
|
||||
<!--@click="
|
||||
complete
|
||||
? toggleFullScreen
|
||||
: naviga(`/catalogo/` + myproduct._id + '/' + cosa)
|
||||
"-->
|
||||
|
||||
<div class="scheda-book">
|
||||
<q-card-title>
|
||||
<span class="book-title" :data-col="options.quante_col">
|
||||
@@ -324,7 +325,7 @@
|
||||
style="align-items: center"
|
||||
>
|
||||
<span class="q-mr-sm">{{ $t('products.editore') }}:</span>
|
||||
<q-badge
|
||||
<q-badge
|
||||
:color="
|
||||
tools.getRecByVersioneProd(variazione.versione).color
|
||||
"
|
||||
|
||||
@@ -52,6 +52,7 @@ export default defineComponent({
|
||||
formato: [],
|
||||
Categoria: [],
|
||||
Editore: [],
|
||||
pdf: false,
|
||||
}),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div>
|
||||
<div>
|
||||
<CCatalogoCard
|
||||
:id="id"
|
||||
:complete="complete"
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<template>
|
||||
<div class="q-ma-xs">
|
||||
<div
|
||||
v-if="tools.visualizzaHomeApp()"
|
||||
v-if="true"
|
||||
class="row q-my-xs shadow"
|
||||
style="border-radius: 4px; border: 1px solid rgba(0, 0, 0, 0.12)"
|
||||
>
|
||||
|
||||
<!--<div class="col-md-3 col-lg-3 col-sm-12 col-xs-12 box_4" style="border-left: 1px solid #efefef;"
|
||||
v-bind:class="{'border-top': $q.platform.is.mobile}">
|
||||
<q-card class="no-shadow q-pa-sm">
|
||||
|
||||
@@ -35,6 +35,11 @@ export default defineComponent({
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
showMap: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
noButtAdd: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
@@ -81,7 +86,6 @@ export default defineComponent({
|
||||
const strextra = ref('')
|
||||
const myoptions = ref(<any>[])
|
||||
|
||||
|
||||
const col = ref(<IColGridTable>{})
|
||||
|
||||
/*
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
:prop_SortFieldsAvailable="mySortFieldsAvailable"
|
||||
:labelBtnAddExtra="noButtAdd ? `` : (ind >= 0) ? `Aggiungi ` + costanti.MAINCARDS[ind].strsingolo : ''"
|
||||
:extraparams="tools.extraparams(table, {myrecfiltertoggle})"
|
||||
:prop_showMap="showMap"
|
||||
>
|
||||
</CGridTableRec>
|
||||
</div>
|
||||
|
||||
@@ -46,3 +46,9 @@
|
||||
.q-table__top{
|
||||
padding-top: 0 !important;
|
||||
}
|
||||
|
||||
.right-align-dialog .q-dialog {
|
||||
right: 0; /* Allinea a destra */
|
||||
left: auto; /* Disabilita l'allineamento a sinistra */
|
||||
margin: 0; /* Rimuovi qualsiasi margine */
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { defineComponent, PropType, ref, watch, toRef, onMounted, toRefs, computed, inject } from 'vue'
|
||||
import { defineComponent, PropType, ref, watch, toRef, onMounted, onBeforeUnmount, toRefs, computed, inject, onUnmounted } from 'vue'
|
||||
import { useI18n } from '@src/boot/i18n'
|
||||
|
||||
import { tools } from '../../store/Modules/tools'
|
||||
@@ -25,6 +25,7 @@ import { CMyUser } from '../CMyUser'
|
||||
import { CMyGroups } from '../CMyGroups'
|
||||
import { CMyFieldDb } from '../CMyFieldDb'
|
||||
import { CMyRecCard } from '../CMyRecCard'
|
||||
import { CMapByTable } from '../CMapByTable'
|
||||
import { CMyRecGrpCard } from '../CMyRecGrpCard'
|
||||
import { CMyRecCircuitCard } from '../CMyRecCircuitCard'
|
||||
import { CMySelect } from '../CMySelect'
|
||||
@@ -40,7 +41,12 @@ import { CMyCardPopup } from '@/components/CMyCardPopup'
|
||||
import { CMyCardService } from '@/components/CMyCardService'
|
||||
import { CMyCardGrpPopup } from '@/components/CMyCardGrpPopup'
|
||||
import { CMyCardCircuitPopup } from '@/components/CMyCardCircuitPopup'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { onBeforeRouteLeave, onBeforeRouteUpdate, beforeRouteEnter, useRouter } from 'vue-router'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { NavigationGuardNext, RouteLocationNormalized } from 'vue-router'
|
||||
|
||||
import { Dialog } from 'quasar'; // Assicurati di importare correttamente Dialog da Quasar.
|
||||
|
||||
|
||||
export default defineComponent({
|
||||
name: 'CGridTableRec',
|
||||
@@ -295,14 +301,22 @@ export default defineComponent({
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
prop_showMap: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
}
|
||||
},
|
||||
components: {
|
||||
CMyPopupEdit, CTitleBanner, CMyFieldDb, CMySelect, CMyFriends, CMyGroups,
|
||||
CMyUser, CMyRecCard, CMyCardPopup, CMyRecGrpCard, CMyCardGrpPopup, CMyCardCircuitPopup,
|
||||
CMyRecCircuitCard, CMyCardService, CNotifSettings
|
||||
CMyRecCircuitCard, CMyCardService, CNotifSettings, CMapByTable,
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const $q = useQuasar()
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
const { t } = useI18n()
|
||||
const userStore = useUserStore()
|
||||
const globalStore = useGlobalStore()
|
||||
@@ -314,6 +328,8 @@ export default defineComponent({
|
||||
const actmonth = ref('')
|
||||
const drawmonth = ref(true)
|
||||
|
||||
const showMap = ref(false)
|
||||
|
||||
|
||||
const newRecordBool = ref(false)
|
||||
const newRecordBoolOld = ref(false)
|
||||
@@ -347,12 +363,11 @@ export default defineComponent({
|
||||
|
||||
const visupagedialog = ref(false)
|
||||
const myrecdialog = ref(null)
|
||||
const myIdRecDialog = ref(null)
|
||||
|
||||
const startsearch = ref(false)
|
||||
const clickbuttsearch = ref(false)
|
||||
|
||||
const $router = useRouter()
|
||||
|
||||
const myinfscroll = ref(null)
|
||||
|
||||
const serverData: any = ref([] as any[])
|
||||
@@ -397,7 +412,53 @@ export default defineComponent({
|
||||
const ordinam = ref('')
|
||||
const ordinam_desc = ref(false)
|
||||
|
||||
/*onBeforeRouteUpdate((to: any, from: any, next: any) => {
|
||||
console.log('onBeforeRouteUpdate', 'to', to, 'from', from, 'next', next)
|
||||
next()
|
||||
})*/
|
||||
|
||||
onBeforeRouteLeave((to: any, from: any, next: any) => {
|
||||
console.log('onBeforeRouteLeave', 'to', to, 'from', from, 'next', next)
|
||||
if (checkForChanges()) {
|
||||
const answer = window.confirm(t('dialog.uscire'))
|
||||
if (answer) {
|
||||
next()
|
||||
} else {
|
||||
next(false)
|
||||
}
|
||||
} else {
|
||||
next()
|
||||
}
|
||||
})
|
||||
|
||||
// Funzione per simulare il controllo delle modifiche
|
||||
const checkForChanges = (): boolean => {
|
||||
// Funzione di utilità per confrontare due valori
|
||||
const isEqual = (val1: any, val2: any): boolean => {
|
||||
if (typeof val1 !== typeof val2) return false
|
||||
if (typeof val1 === 'object' && val1 !== null && val2 !== null) {
|
||||
const keys1 = Object.keys(val1)
|
||||
const keys2 = Object.keys(val2)
|
||||
if (keys1.length !== keys2.length) return false
|
||||
return keys1.every(key => isEqual(val1[key], val2[key]))
|
||||
}
|
||||
return val1 === val2
|
||||
}
|
||||
|
||||
// Confronta recModif con recSaved
|
||||
return !isEqual(recModif.value, recSaved.value)
|
||||
// return true
|
||||
}
|
||||
|
||||
function saveChanges() {
|
||||
if (editRecordBool.value) {
|
||||
saverecModif()
|
||||
}
|
||||
if (newRecordBool.value) {
|
||||
saveNewRecord()
|
||||
}
|
||||
|
||||
}
|
||||
const getNumRecFromQuery = computed(() => () => {
|
||||
return serverData.value.length
|
||||
})
|
||||
@@ -493,8 +554,8 @@ export default defineComponent({
|
||||
}
|
||||
})
|
||||
|
||||
$router.beforeResolve((to: any) => {
|
||||
// console.log('beforeResolve', visupagedialog.value, 'to', to)
|
||||
router.beforeResolve((to: any) => {
|
||||
console.log('beforeResolve', visupagedialog.value, 'to', to)
|
||||
|
||||
if (visupagedialog.value && !to.meta.newpage) {
|
||||
// visupagedialog.value = false
|
||||
@@ -1544,8 +1605,11 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
function mounted() {
|
||||
console.log('mounted...')
|
||||
searchList.value = props.prop_searchList
|
||||
|
||||
showMap.value = props.prop_showMap
|
||||
|
||||
|
||||
// console.log('GridTable mounted', tablesel.value)
|
||||
|
||||
@@ -1583,6 +1647,9 @@ export default defineComponent({
|
||||
|
||||
changeTable(tablesel.value, true)
|
||||
|
||||
// Aggiungi gli listener agli eventi della tastiera
|
||||
document.addEventListener('keydown', onEscapeKey);
|
||||
// window.addEventListener('popstate', onBackButton);
|
||||
|
||||
}
|
||||
|
||||
@@ -2077,7 +2144,7 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
async function saverecModif() {
|
||||
// console.log('saverecModif')
|
||||
// console.log('saverecModif', recModif.value)
|
||||
const mydata = {
|
||||
table: mytable.value,
|
||||
data: {}
|
||||
@@ -2110,9 +2177,6 @@ export default defineComponent({
|
||||
})
|
||||
}
|
||||
|
||||
function hidewindow() {
|
||||
annulla(0)
|
||||
}
|
||||
|
||||
function getlabelAddRow() {
|
||||
return props.labelBtnAddRow
|
||||
@@ -2159,7 +2223,7 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
|
||||
function cmdExt(cmd: any, id: any, val2: any) {
|
||||
function cmdExt(cmd: any, id: any, myrec: any) {
|
||||
console.log('cmd', cmd)
|
||||
|
||||
if (cmd === costanti.CMD_CLONE) {
|
||||
@@ -2172,10 +2236,11 @@ export default defineComponent({
|
||||
|
||||
if (cmd === costanti.CMD_SHOW_PAGE) {
|
||||
visupagedialog.value = true
|
||||
myrecdialog.value = id
|
||||
myrecdialog.value = myrec
|
||||
myIdRecDialog.value = id
|
||||
return true
|
||||
} else if (cmd === costanti.CMD_OPEN_PAGE) {
|
||||
$router.push(tools.getPathByTableAndRec(mytable.value, id))
|
||||
router.push(tools.getPathByTableAndRec(mytable.value, myrec))
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -2193,7 +2258,7 @@ export default defineComponent({
|
||||
|
||||
const col = props.prop_mycolumns.find((rec: any) => rec.action === action)
|
||||
if (col) {
|
||||
console.log('col action', col)
|
||||
// console.log('col action', col)
|
||||
const myarr = serverData.value.find((rec: any) => rec._id === id)
|
||||
if (myarr)
|
||||
clickFunz(myarr, col)
|
||||
@@ -2326,11 +2391,36 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
/*function showNotification() {
|
||||
$router.push('/notifs')
|
||||
router.push('/notifs')
|
||||
} */
|
||||
|
||||
// Questa funzione viene chiamata quando il dialogo cerca di chiudersi
|
||||
const onEscapeKey = (event: KeyboardEvent) => {
|
||||
if (event.key === 'Escape') {
|
||||
event.preventDefault(); // Previene la chiusura da ESC
|
||||
}
|
||||
};
|
||||
|
||||
// Rimuovi i listener al distruggere del componente
|
||||
onBeforeUnmount(() => {
|
||||
document.removeEventListener('keydown', onEscapeKey);
|
||||
// window.removeEventListener('popstate', onBackButton);
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
mounted()
|
||||
})
|
||||
|
||||
function hidewindow() {
|
||||
annulla(0)
|
||||
}
|
||||
|
||||
function clickMarker(id: any) {
|
||||
console.log('clickMarker', id)
|
||||
cmdExt(costanti.CMD_SHOW_PAGE, id, null)
|
||||
}
|
||||
|
||||
created()
|
||||
mounted()
|
||||
|
||||
return {
|
||||
selItem,
|
||||
@@ -2410,6 +2500,7 @@ export default defineComponent({
|
||||
cmdExt,
|
||||
visupagedialog,
|
||||
myrecdialog,
|
||||
myIdRecDialog,
|
||||
showDate,
|
||||
getActualDate,
|
||||
actualDate,
|
||||
@@ -2440,6 +2531,8 @@ export default defineComponent({
|
||||
withdate,
|
||||
setShowMonth,
|
||||
ifShowMonth,
|
||||
showMap,
|
||||
clickMarker,
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2103,7 +2103,7 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
|
||||
function cmdExt(cmd: any, id: any, val2: any) {
|
||||
function cmdExt(cmd: any, id: any, myrec: any) {
|
||||
console.log('cmd', cmd)
|
||||
|
||||
if (cmd === costanti.CMD_CLONE) {
|
||||
@@ -2116,10 +2116,10 @@ export default defineComponent({
|
||||
|
||||
if (cmd === costanti.CMD_SHOW_PAGE) {
|
||||
visupagedialog.value = true
|
||||
myrecdialog.value = id
|
||||
myrecdialog.value = myrec
|
||||
return true
|
||||
} else if (cmd === costanti.CMD_OPEN_PAGE) {
|
||||
$router.push(tools.getPathByTableAndRec(mytable.value, id))
|
||||
$router.push(tools.getPathByTableAndRec(mytable.value, myrec))
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
3
src/components/CMapByTable/CMapByTable.scss
Executable file
3
src/components/CMapByTable/CMapByTable.scss
Executable file
@@ -0,0 +1,3 @@
|
||||
.map-container {
|
||||
height: 400px;
|
||||
}
|
||||
177
src/components/CMapByTable/CMapByTable.ts
Executable file
177
src/components/CMapByTable/CMapByTable.ts
Executable file
@@ -0,0 +1,177 @@
|
||||
import { tools } from '@store/Modules/tools'
|
||||
import { useQuasar } from 'quasar'
|
||||
import { PropType, defineComponent, onMounted, ref, computed, toRef, watch } from 'vue'
|
||||
|
||||
import 'leaflet/dist/leaflet.css'
|
||||
// @ts-ignore
|
||||
import * as L from 'leaflet'
|
||||
import 'leaflet.markercluster/dist/MarkerCluster.css'
|
||||
import 'leaflet.markercluster/dist/MarkerCluster.Default.css'
|
||||
import 'leaflet.markercluster'
|
||||
|
||||
import { useUserStore } from '@src/store/UserStore'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'CMapByTable',
|
||||
props: {
|
||||
mytable: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
arrcord: {
|
||||
type: Array as PropType<any[]>,
|
||||
required: false,
|
||||
default: () => { return [] }
|
||||
}
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const $q = useQuasar()
|
||||
const userStore = useUserStore()
|
||||
|
||||
const iconWidth = ref(25)
|
||||
const iconHeight = ref(40)
|
||||
const map = ref(<any>null)
|
||||
const zoom = ref(6)
|
||||
|
||||
const initialMap = ref(<any>null);
|
||||
|
||||
const markers = ref(<any>null);
|
||||
|
||||
const myIcon = L.icon({
|
||||
iconUrl: 'images/icon.png',
|
||||
iconSize: [30, 30],
|
||||
iconAnchor: [22, 35],
|
||||
popupAnchor: [-6, -36],
|
||||
shadowUrl: 'images/marker-shadow.png',
|
||||
shadowSize: [60, 30],
|
||||
shadowAnchor: [22, 35]
|
||||
});
|
||||
|
||||
const arrcord = toRef(props, 'arrcord')
|
||||
|
||||
function mywidth() {
|
||||
return tools.getwidth($q) - 20
|
||||
}
|
||||
|
||||
function myheight() {
|
||||
return $q.screen.height - 150
|
||||
}
|
||||
|
||||
const iconUrl = computed(() => {
|
||||
return `https://placekitten.com/${iconWidth.value}/${iconHeight.value}`;
|
||||
})
|
||||
|
||||
const iconSize = computed(() => {
|
||||
return [iconWidth.value, iconHeight.value];
|
||||
})
|
||||
|
||||
function changeIcon() {
|
||||
iconWidth.value += 2;
|
||||
if (iconWidth.value > iconHeight.value) {
|
||||
iconWidth.value = Math.floor(iconHeight.value / 2);
|
||||
}
|
||||
}
|
||||
|
||||
function getColor(d: any) {
|
||||
return d > 1000 ? '#800026' :
|
||||
d > 500 ? '#BD0026' :
|
||||
d > 200 ? '#E31A1C' :
|
||||
d > 100 ? '#FC4E2A' :
|
||||
d > 50 ? '#FD8D3C' :
|
||||
d > 20 ? '#FEB24C' :
|
||||
d > 10 ? '#FED976' :
|
||||
'#FFEDA0';
|
||||
}
|
||||
|
||||
function style(feature: any) {
|
||||
return {
|
||||
fillColor: getColor(feature.properties.density),
|
||||
weight: 2,
|
||||
opacity: 1,
|
||||
color: 'white',
|
||||
dashArray: '3',
|
||||
fillOpacity: 0.7
|
||||
};
|
||||
}
|
||||
|
||||
watch(arrcord, () => {
|
||||
updateMap()
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
// Ottengo la lista degli utenti con i lat e long
|
||||
// arrcord.value = await userStore.getProvincesForMap()
|
||||
|
||||
// @ts-ignore
|
||||
markers.value = L.markerClusterGroup()
|
||||
|
||||
initialMap.value = L.map('map',
|
||||
{
|
||||
zoomControl: true, zoom: zoom.value, zoomAnimation: true,
|
||||
fadeAnimation: true, markerZoomAnimation: true,
|
||||
center: [42.71, 12.934],
|
||||
}
|
||||
);
|
||||
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 15,
|
||||
attribution: ''
|
||||
}).addTo(initialMap.value);
|
||||
|
||||
updateMap()
|
||||
|
||||
// @ts-ignore
|
||||
});
|
||||
|
||||
function log(str: string) {
|
||||
console.log(str)
|
||||
}
|
||||
|
||||
function getCoordinates(e: any) {
|
||||
// Ottieni la latitudine e la longitudine dal click
|
||||
const lat = e.latlng.lat
|
||||
const lng = e.latlng.lng
|
||||
|
||||
// Fai qualcosa con le coordinate, ad esempio stamparle in console
|
||||
console.log(`Latitudine: ${lat}, Longitudine: ${lng}`)
|
||||
}
|
||||
|
||||
function updateMap() {
|
||||
if (initialMap.value) {
|
||||
markers.value.clearLayers();
|
||||
|
||||
for (const rec of arrcord.value) {
|
||||
if (rec.coordinate_gps.coordinates) {
|
||||
// @ts-ignore
|
||||
let each_marker = new L.marker(
|
||||
[rec.coordinate_gps.coordinates[1], rec.coordinate_gps.coordinates[0]], { icon: myIcon })
|
||||
.bindPopup(`<strong>${rec.descr}</strong>`)
|
||||
.on('click', () => markerClick(rec._id)); // Collega il click al bottone
|
||||
markers.value.addLayer(each_marker);
|
||||
}
|
||||
}
|
||||
|
||||
// Aggiungi il gruppo di marker cluster alla mappa
|
||||
initialMap.value.addLayer(markers.value);
|
||||
}
|
||||
}
|
||||
|
||||
function markerClick(id: any) {
|
||||
emit('clickMarker', id)
|
||||
}
|
||||
|
||||
return {
|
||||
mywidth,
|
||||
myheight,
|
||||
map,
|
||||
iconWidth,
|
||||
iconHeight,
|
||||
iconUrl,
|
||||
iconSize,
|
||||
changeIcon,
|
||||
zoom,
|
||||
log,
|
||||
getCoordinates,
|
||||
arrcord,
|
||||
}
|
||||
}
|
||||
})
|
||||
12
src/components/CMapByTable/CMapByTable.vue
Executable file
12
src/components/CMapByTable/CMapByTable.vue
Executable file
@@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<div>
|
||||
<div id="map" :style="`height:${myheight()}px; width:99%`">
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" src="./CMapByTable.ts">
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './CMapByTable.scss';
|
||||
</style>
|
||||
1
src/components/CMapByTable/index.ts
Executable file
1
src/components/CMapByTable/index.ts
Executable file
@@ -0,0 +1 @@
|
||||
export {default as CMapByTable} from './CMapByTable.vue'
|
||||
@@ -187,7 +187,7 @@ export default defineComponent({
|
||||
|
||||
initialMap.value = L.map('map',
|
||||
{
|
||||
zoomControl: true, zoom: zoom.value, zoomAnimation: false,
|
||||
zoomControl: true, zoom: zoom.value, zoomAnimation: true,
|
||||
fadeAnimation: true, markerZoomAnimation: true,
|
||||
center: center.value,
|
||||
}
|
||||
|
||||
13
src/components/CMapEditAddressByCoord/CMapEditAddressByCoord.scss
Executable file
13
src/components/CMapEditAddressByCoord/CMapEditAddressByCoord.scss
Executable file
@@ -0,0 +1,13 @@
|
||||
.map-container {
|
||||
width: 100%; /* Imposta la larghezza del contenitore */
|
||||
height: 400px; /* Imposta un'altezza fissa o usa % */
|
||||
position: relative; /* Assicurati che la posizione sia relativa o assoluta */
|
||||
}
|
||||
#map {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.leaflet-popup-content >* {
|
||||
display: block !important;
|
||||
}
|
||||
390
src/components/CMapEditAddressByCoord/CMapEditAddressByCoord.ts
Executable file
390
src/components/CMapEditAddressByCoord/CMapEditAddressByCoord.ts
Executable file
@@ -0,0 +1,390 @@
|
||||
import { tools } from '@store/Modules/tools'
|
||||
import { useQuasar } from 'quasar'
|
||||
import { defineComponent, onMounted, onBeforeUnmount, ref, watch, computed, PropType, nextTick } from 'vue'
|
||||
|
||||
import 'leaflet/dist/leaflet.css'
|
||||
import * as L from 'leaflet'
|
||||
import 'leaflet.markercluster/dist/MarkerCluster.css'
|
||||
import 'leaflet.markercluster/dist/MarkerCluster.Default.css'
|
||||
import 'leaflet.markercluster'
|
||||
|
||||
import { useUserStore } from '@src/store/UserStore'
|
||||
|
||||
// Importa le immagini dei marker
|
||||
import icon from 'leaflet/dist/images/marker-icon.png'
|
||||
import iconShadow from 'leaflet/dist/images/marker-shadow.png'
|
||||
import { ICoordGPS, ICoordLatLng } from '@src/model'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'CMapEditAddressByCoord',
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Object as PropType<ICoordGPS>,
|
||||
required: true,
|
||||
},
|
||||
editaddress: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
visuMappa: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
}
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const $q = useQuasar()
|
||||
const userStore = useUserStore()
|
||||
|
||||
const mapContainer = ref(<any>null);
|
||||
|
||||
const iconWidth = ref(25)
|
||||
const iconHeight = ref(41)
|
||||
const map = ref<L.Map | null>(null)
|
||||
const marker = ref<L.Marker | null>(null)
|
||||
const suggestions = ref([]);
|
||||
const isMapDialogOpen = ref(false)
|
||||
const mostraMappa = ref(true)
|
||||
|
||||
const localAddress = ref(props.modelValue.address);
|
||||
const localAddressObj = ref({ label: '', value: '' });
|
||||
const localCoordinates = ref(<ICoordLatLng>{ lat: props.modelValue.coordinates[1], lng: props.modelValue.coordinates[0] });
|
||||
|
||||
const modificato = ref(false)
|
||||
|
||||
const fineLoad = ref(false)
|
||||
|
||||
const zoomLevel = ref(17)
|
||||
|
||||
const updateAll = () => {
|
||||
if (localAddress.value)
|
||||
emit('update:modelValue',
|
||||
{
|
||||
address: localAddress.value,
|
||||
type: 'Point',
|
||||
coordinates: [localCoordinates.value.lng, localCoordinates.value.lat]
|
||||
} as ICoordGPS);
|
||||
};
|
||||
|
||||
// Funzione per aggiornare il nome
|
||||
const updateAddress = () => {
|
||||
if (localAddress.value)
|
||||
updateAll()
|
||||
};
|
||||
|
||||
// Funzione per aggiornare il cognome
|
||||
const updateCoordinates = () => {
|
||||
updateAll()
|
||||
};
|
||||
|
||||
// Monitoraggio delle modifiche alle props
|
||||
watch(() => props.modelValue.address, (newValue) => {
|
||||
localAddress.value = newValue;
|
||||
});
|
||||
|
||||
watch(() => props.modelValue.coordinates, (newValue) => {
|
||||
localCoordinates.value.lat = newValue[1];
|
||||
localCoordinates.value.lng = newValue[0];
|
||||
});
|
||||
|
||||
|
||||
watch(() => localCoordinates.value.lng, (newValue) => {
|
||||
if (fineLoad.value) {
|
||||
modificato.value = true
|
||||
}
|
||||
updateMarker(localCoordinates.value.lat, localCoordinates.value.lng);
|
||||
getAddressFromCoordinates(localCoordinates.value.lat, localCoordinates.value.lng);
|
||||
});
|
||||
watch(() => localCoordinates.value.lng, (newValue) => {
|
||||
if (fineLoad.value) {
|
||||
modificato.value = true
|
||||
}
|
||||
updateMarker(localCoordinates.value.lat, localCoordinates.value.lng);
|
||||
getAddressFromCoordinates(localCoordinates.value.lat, localCoordinates.value.lng);
|
||||
|
||||
});
|
||||
|
||||
const myheight = computed(() => {
|
||||
return $q.screen.height - 150
|
||||
})
|
||||
|
||||
// Funzione per ottenere e stampare il livello di zoom
|
||||
function getZoomLevel() {
|
||||
zoomLevel.value = map.value ? map.value.getZoom() : 17;
|
||||
// console.log('Current zoom level:', zoomLevel);
|
||||
}
|
||||
|
||||
const initMap = () => {
|
||||
// Configura l'icona di default
|
||||
const DefaultIcon = L.icon({
|
||||
iconUrl: icon,
|
||||
shadowUrl: iconShadow,
|
||||
iconSize: [iconWidth.value, iconHeight.value],
|
||||
iconAnchor: [iconWidth.value / 2, iconHeight.value],
|
||||
popupAnchor: [1, -iconHeight.value],
|
||||
shadowSize: [iconHeight.value, iconHeight.value]
|
||||
})
|
||||
L.Marker.prototype.options.icon = DefaultIcon
|
||||
|
||||
zoomLevel.value = 17
|
||||
|
||||
map.value = L.map(mapContainer.value,
|
||||
{
|
||||
zoomControl: true, zoom: zoomLevel.value, zoomAnimation: true,
|
||||
fadeAnimation: true, markerZoomAnimation: true,
|
||||
center: [42.71, 12.934],
|
||||
}
|
||||
)
|
||||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map.value)
|
||||
|
||||
|
||||
getZoomLevel();
|
||||
|
||||
// Ottenere il livello di zoom quando la mappa viene ridimensionata
|
||||
map.value.on('zoomend', getZoomLevel);
|
||||
|
||||
/*
|
||||
const closeButton = L.control({ position: 'topright' });
|
||||
|
||||
closeButton.onAdd = function () {
|
||||
const button = L.DomUtil.create('button', 'leaflet-control-button');
|
||||
button.innerHTML = 'Chiudi'; // Testo del pulsante
|
||||
button.style.backgroundColor = 'red';
|
||||
button.style.color = 'white';
|
||||
button.style.border = 'none';
|
||||
button.style.borderRadius = '5px';
|
||||
button.style.padding = '10px';
|
||||
button.style.cursor = 'pointer';
|
||||
|
||||
button.onclick = () => {
|
||||
mostraMappa.value = false; // Chiudi il dialog della mappa
|
||||
};
|
||||
|
||||
return button;
|
||||
};
|
||||
|
||||
closeButton.addTo(map.value);
|
||||
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
const onResize = () => {
|
||||
if (map.value) {
|
||||
map.value.invalidateSize();
|
||||
}
|
||||
};
|
||||
|
||||
const updateMarker = (lat: number, lng: number) => {
|
||||
// console.log('aggiorna marker', lat, lng)
|
||||
if (fineLoad.value) {
|
||||
modificato.value = true
|
||||
}
|
||||
if (marker.value) {
|
||||
marker.value.setLatLng([lat, lng])
|
||||
} else {
|
||||
marker.value = L.marker([lat, lng], { draggable: true }).addTo(map.value!)
|
||||
marker.value.on('dragend', (event: L.LeafletEvent) => {
|
||||
const position = (event.target as L.Marker).getLatLng()
|
||||
localCoordinates.value = {
|
||||
lat: parseFloat(position.lat.toFixed(6)),
|
||||
lng: parseFloat(position.lng.toFixed(6)),
|
||||
};
|
||||
if (fineLoad.value) {
|
||||
mostraMappa.value = true
|
||||
}
|
||||
getAddressFromCoordinates(localCoordinates.value.lat, localCoordinates.value.lng);
|
||||
// updateCoordinates()
|
||||
})
|
||||
}
|
||||
map.value?.setView([lat, lng], zoomLevel.value)
|
||||
}
|
||||
|
||||
function updateMap() {
|
||||
|
||||
map.value?.setView([localCoordinates.value.lat, localCoordinates.value.lng], zoomLevel.value)
|
||||
}
|
||||
|
||||
const searchAddress = async () => {
|
||||
try {
|
||||
const response = await fetch(`https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(localAddress.value)}`)
|
||||
const data = await response.json()
|
||||
if (data && data.length > 0) {
|
||||
localCoordinates.value = { lat: parseFloat(data[0].lat), lng: parseFloat(data[0].lon) }
|
||||
localAddress.value = data[0].display_name
|
||||
if (fineLoad.value) {
|
||||
mostraMappa.value = true
|
||||
}
|
||||
isMapDialogOpen.value = true
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error searching address:', error)
|
||||
}
|
||||
}
|
||||
|
||||
const getAddressSuggestions = async (val: string, update: Function) => {
|
||||
try {
|
||||
if (val.length === 0) {
|
||||
suggestions.value = [];
|
||||
update();
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await fetch(
|
||||
`https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(val)}`
|
||||
);
|
||||
const data = await response.json();
|
||||
suggestions.value = data.map((item: any) => ({
|
||||
label: item.display_name,
|
||||
value: item.display_name,
|
||||
lat: item.lat,
|
||||
lon: item.lon
|
||||
}));
|
||||
|
||||
update();
|
||||
} catch (error) {
|
||||
console.error('Error fetching address suggestions:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const getAddressFromCoordinates = async (lat: number, lon: number) => {
|
||||
const url = `https://nominatim.openstreetmap.org/reverse?lat=${lat}&lon=${lon}&format=json`;
|
||||
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) {
|
||||
throw new Error('Errore nella richiesta di geocoding');
|
||||
}
|
||||
const data = await response.json();
|
||||
localAddress.value = data.display_name; // Ottieni l'indirizzo
|
||||
localAddressObj.value = { label: localAddress.value, value: localAddress.value }
|
||||
} catch (error) {
|
||||
console.error('Errore durante il geocoding:', error);
|
||||
localAddress.value = ''; // In caso di errore, resetta l'indirizzo
|
||||
localAddressObj.value = { label: '', value: '' }
|
||||
}
|
||||
};
|
||||
|
||||
watch(localAddressObj, (newAddress: any) => {
|
||||
if (newAddress) {
|
||||
const match: any = suggestions.value.find((suggestion: any) => suggestion.value === newAddress.value);
|
||||
if (match && match.lat) {
|
||||
localAddress.value = match.value;
|
||||
localCoordinates.value = {
|
||||
lat: parseFloat(parseFloat(match.lat).toFixed(6)),
|
||||
lng: parseFloat(parseFloat(match.lon).toFixed(6)),
|
||||
};
|
||||
updateCoordinates()
|
||||
updateAddress()
|
||||
|
||||
updateMarker(localCoordinates.value.lat, localCoordinates.value.lng);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function salvaCoordinate() {
|
||||
updateCoordinates()
|
||||
updateAddress()
|
||||
$q.notify({
|
||||
type: 'positive',
|
||||
message: 'Coordinate modificate, Salvare per rendere effettiva la modifica',
|
||||
position: 'bottom',
|
||||
timeout: 2000
|
||||
})
|
||||
modificato.value = false
|
||||
mostraMappa.value = false
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
if (!props.modelValue.address) {
|
||||
localAddress.value = ''
|
||||
localAddressObj.value = { label: '', value: '' }
|
||||
} else {
|
||||
localAddressObj.value = { label: props.modelValue.address, value: props.modelAddress }
|
||||
}
|
||||
if (!props.modelValue.coordinates) {
|
||||
localCoordinates.value = { lat: 0, lng: 0 }
|
||||
}
|
||||
|
||||
initMap()
|
||||
|
||||
updateMap()
|
||||
updateMarker(localCoordinates.value.lat, localCoordinates.value.lng);
|
||||
|
||||
if (!localCoordinates.value || !localCoordinates.value.lat) {
|
||||
mostraMappa.value = false
|
||||
}
|
||||
fineLoad.value = true
|
||||
window.addEventListener('resize', onResize);
|
||||
|
||||
nextTick(() => {
|
||||
mostraMappa.value = props.visuMappa
|
||||
})
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('resize', onResize);
|
||||
});
|
||||
|
||||
const getCurrentLocation = () => {
|
||||
if ('geolocation' in navigator) {
|
||||
navigator.geolocation.getCurrentPosition(
|
||||
(position) => {
|
||||
localCoordinates.value = {
|
||||
lat: parseFloat(position.coords.latitude.toFixed(6)),
|
||||
lng: parseFloat(position.coords.longitude.toFixed(6)),
|
||||
};
|
||||
if (fineLoad.value) {
|
||||
mostraMappa.value = true;
|
||||
}
|
||||
updateCoordinates();
|
||||
updateMarker(localCoordinates.value.lat, localCoordinates.value.lng);
|
||||
},
|
||||
(error) => {
|
||||
console.error('Error getting location:', error);
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: 'Errore durante il rilevamento della posizione.',
|
||||
});
|
||||
}
|
||||
);
|
||||
} else {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: 'Geolocalizzazione non supportata dal browser.',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function annullaSalvataggio() {
|
||||
localCoordinates.value.lng = props.modelValue.coordinates[0]
|
||||
localCoordinates.value.lat = props.modelValue.coordinates[1]
|
||||
localAddress.value = props.modelValue.address
|
||||
updateMarker(localCoordinates.value.lat, localCoordinates.value.lng);
|
||||
mostraMappa.value = false
|
||||
modificato.value = false
|
||||
}
|
||||
|
||||
// evento dopo il mounting
|
||||
return {
|
||||
searchAddress,
|
||||
myheight,
|
||||
isMapDialogOpen,
|
||||
suggestions,
|
||||
getAddressSuggestions,
|
||||
localAddress,
|
||||
localCoordinates,
|
||||
updateAddress,
|
||||
updateCoordinates,
|
||||
mostraMappa,
|
||||
localAddressObj,
|
||||
getCurrentLocation,
|
||||
salvaCoordinate,
|
||||
modificato,
|
||||
annullaSalvataggio,
|
||||
mapContainer,
|
||||
fineLoad,
|
||||
}
|
||||
}
|
||||
})
|
||||
90
src/components/CMapEditAddressByCoord/CMapEditAddressByCoord.vue
Executable file
90
src/components/CMapEditAddressByCoord/CMapEditAddressByCoord.vue
Executable file
@@ -0,0 +1,90 @@
|
||||
<template>
|
||||
<div class="q-pa-sm">
|
||||
<div class="q-gutter-sm">
|
||||
<div class="row q-col-gutter-sm q-mb-sm items-center">
|
||||
<div class="col">
|
||||
<q-select
|
||||
v-model="localAddressObj"
|
||||
label="Indirizzo"
|
||||
use-input
|
||||
input-debounce="300"
|
||||
:options="suggestions"
|
||||
@filter="getAddressSuggestions"
|
||||
filled
|
||||
dense
|
||||
hide-dropdown-icon
|
||||
clearable
|
||||
/>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<q-btn @click="searchAddress" label="Cerca" color="primary" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row q-col-gutter-sm q-mb-sm items-center no-wrap">
|
||||
<q-col class="q-col-auto" style="width: 120px">
|
||||
<q-input
|
||||
v-model="localCoordinates.lat"
|
||||
label="Latitudine:"
|
||||
filled
|
||||
:label-color="modificato ? 'negative' : 'primary'"
|
||||
dense
|
||||
/>
|
||||
</q-col>
|
||||
<q-col class="q-col-auto" style="width: 120px">
|
||||
<q-input
|
||||
v-model="localCoordinates.lng"
|
||||
label="Longitudine:"
|
||||
filled
|
||||
:label-color="modificato ? 'negative' : 'primary'"
|
||||
dense
|
||||
/>
|
||||
</q-col>
|
||||
<q-col class="q-col-auto" style="width: 60px">
|
||||
<q-btn
|
||||
@click="getCurrentLocation"
|
||||
label=""
|
||||
color="primary"
|
||||
icon="gps_fixed"
|
||||
/>
|
||||
</q-col>
|
||||
<q-col class="q-col-auto" style="width: 60px">
|
||||
<q-btn
|
||||
@click="mostraMappa = !mostraMappa"
|
||||
:color="mostraMappa ? 'negative' : 'positive'"
|
||||
class="q-ma-sm"
|
||||
icon="fas fa-map"
|
||||
/>
|
||||
</q-col>
|
||||
</div>
|
||||
|
||||
<div v-if="modificato" class="row justify-center q-ma-sm">
|
||||
<q-btn
|
||||
@click="salvaCoordinate"
|
||||
color="primary"
|
||||
label="Salva"
|
||||
:disable="!modificato"
|
||||
class="q-ma-sm"
|
||||
/>
|
||||
<q-btn
|
||||
@click="annullaSalvataggio"
|
||||
label="Annulla"
|
||||
class="q-ma-sm"
|
||||
:disable="!modificato"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
id="map"
|
||||
ref="mapContainer"
|
||||
v-show="mostraMappa"
|
||||
:style="`height:${myheight}px; width:99%`"
|
||||
></div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" src="./CMapEditAddressByCoord.ts">
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './CMapEditAddressByCoord.scss';
|
||||
</style>
|
||||
1
src/components/CMapEditAddressByCoord/index.ts
Executable file
1
src/components/CMapEditAddressByCoord/index.ts
Executable file
@@ -0,0 +1 @@
|
||||
export {default as CMapEditAddressByCoord} from './CMapEditAddressByCoord.vue'
|
||||
3
src/components/CMapGetCoordinates/CMapGetCoordinates.scss
Executable file
3
src/components/CMapGetCoordinates/CMapGetCoordinates.scss
Executable file
@@ -0,0 +1,3 @@
|
||||
.map-container {
|
||||
height: 400px;
|
||||
}
|
||||
170
src/components/CMapGetCoordinates/CMapGetCoordinates.ts
Executable file
170
src/components/CMapGetCoordinates/CMapGetCoordinates.ts
Executable file
@@ -0,0 +1,170 @@
|
||||
import { tools } from '@store/Modules/tools'
|
||||
import { useQuasar } from 'quasar'
|
||||
import { defineComponent, onMounted, ref, watch, computed } from 'vue'
|
||||
|
||||
import 'leaflet/dist/leaflet.css'
|
||||
import * as L from 'leaflet'
|
||||
import 'leaflet.markercluster/dist/MarkerCluster.css'
|
||||
import 'leaflet.markercluster/dist/MarkerCluster.Default.css'
|
||||
import 'leaflet.markercluster'
|
||||
|
||||
import { useUserStore } from '@src/store/UserStore'
|
||||
|
||||
// Importa le immagini dei marker
|
||||
import icon from 'leaflet/dist/images/marker-icon.png'
|
||||
import iconShadow from 'leaflet/dist/images/marker-shadow.png'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'CMapGetCoordinates',
|
||||
setup(props, { emit }) {
|
||||
const $q = useQuasar()
|
||||
const userStore = useUserStore()
|
||||
|
||||
const iconWidth = ref(25)
|
||||
const iconHeight = ref(41)
|
||||
const map = ref<L.Map | null>(null)
|
||||
const marker = ref<L.Marker | null>(null)
|
||||
const address = ref('')
|
||||
const suggestions = ref([]);
|
||||
const coordinates = ref(<[number, number]>[0, 0])
|
||||
const isMapDialogOpen = ref(false)
|
||||
|
||||
const zoomLevel = ref(17)
|
||||
|
||||
const myheight = computed(() => {
|
||||
return $q.screen.height - 150
|
||||
})
|
||||
|
||||
const initMap = () => {
|
||||
// Configura l'icona di default
|
||||
const DefaultIcon = L.icon({
|
||||
iconUrl: icon,
|
||||
shadowUrl: iconShadow,
|
||||
iconSize: [iconWidth.value, iconHeight.value],
|
||||
iconAnchor: [iconWidth.value / 2, iconHeight.value],
|
||||
popupAnchor: [1, -iconHeight.value],
|
||||
shadowSize: [iconHeight.value, iconHeight.value]
|
||||
})
|
||||
L.Marker.prototype.options.icon = DefaultIcon
|
||||
|
||||
map.value = L.map('map',
|
||||
{
|
||||
zoomControl: true, zoom: zoomLevel.value, zoomAnimation: true,
|
||||
fadeAnimation: true, markerZoomAnimation: true,
|
||||
center: [42.71, 12.934],
|
||||
}
|
||||
)
|
||||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map.value)
|
||||
|
||||
const closeButton = L.control({ position: 'topright' });
|
||||
|
||||
closeButton.onAdd = function () {
|
||||
const button = L.DomUtil.create('button', 'leaflet-control-button');
|
||||
button.innerHTML = 'Chiudi'; // Testo del pulsante
|
||||
button.style.backgroundColor = 'red';
|
||||
button.style.color = 'white';
|
||||
button.style.border = 'none';
|
||||
button.style.borderRadius = '5px';
|
||||
button.style.padding = '10px';
|
||||
button.style.cursor = 'pointer';
|
||||
|
||||
button.onclick = () => {
|
||||
isMapDialogOpen.value = false; // Chiudi il dialog della mappa
|
||||
};
|
||||
|
||||
return button;
|
||||
};
|
||||
|
||||
closeButton.addTo(map.value);
|
||||
|
||||
}
|
||||
|
||||
const updateMarker = (lat: number, lng: number) => {
|
||||
console.log('aggiorna marker', lat, lng)
|
||||
if (marker.value) {
|
||||
marker.value.setLatLng([lat, lng])
|
||||
} else {
|
||||
marker.value = L.marker([lat, lng], { draggable: true }).addTo(map.value!)
|
||||
marker.value.on('dragend', (event: L.LeafletEvent) => {
|
||||
const position = (event.target as L.Marker).getLatLng()
|
||||
coordinates.value = [
|
||||
parseFloat(position.lng.toFixed(6)),
|
||||
parseFloat(position.lat.toFixed(6)),
|
||||
]
|
||||
|
||||
emit('update:coordinates', coordinates.value)
|
||||
})
|
||||
}
|
||||
map.value?.setView([lat, lng], 17)
|
||||
}
|
||||
|
||||
const searchAddress = async () => {
|
||||
try {
|
||||
const response = await fetch(`https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(address.value)}`)
|
||||
const data = await response.json()
|
||||
if (data && data.length > 0) {
|
||||
coordinates.value = [
|
||||
parseFloat(data[0].lon),
|
||||
parseFloat(data[0].lat)
|
||||
]
|
||||
emit('update:coordinates', coordinates.value)
|
||||
isMapDialogOpen.value = true
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error searching address:', error)
|
||||
}
|
||||
}
|
||||
|
||||
const getAddressSuggestions = async (val: string, update: Function) => {
|
||||
try {
|
||||
if (val.length === 0) {
|
||||
suggestions.value = [];
|
||||
update();
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await fetch(
|
||||
`https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(val)}`
|
||||
);
|
||||
const data = await response.json();
|
||||
suggestions.value = data.map((item: any) => ({
|
||||
label: item.display_name,
|
||||
value: item.display_name,
|
||||
lat: item.lat,
|
||||
lon: item.lon
|
||||
}));
|
||||
|
||||
update();
|
||||
} catch (error) {
|
||||
console.error('Error fetching address suggestions:', error);
|
||||
}
|
||||
};
|
||||
|
||||
watch(address, (newAddress) => {
|
||||
const match: any = suggestions.value.find((suggestion: any) => suggestion.value === newAddress.value);
|
||||
if (match && match.lat) {
|
||||
coordinates.value = [
|
||||
parseFloat(parseFloat(match.lon).toFixed(6)),
|
||||
parseFloat(parseFloat(match.lat).toFixed(6))
|
||||
]
|
||||
};
|
||||
|
||||
updateMarker(coordinates.value[1], coordinates.value[0]);
|
||||
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
initMap()
|
||||
})
|
||||
|
||||
return {
|
||||
address,
|
||||
coordinates,
|
||||
searchAddress,
|
||||
myheight,
|
||||
isMapDialogOpen,
|
||||
suggestions,
|
||||
getAddressSuggestions,
|
||||
}
|
||||
}
|
||||
})
|
||||
57
src/components/CMapGetCoordinates/CMapGetCoordinates.vue
Executable file
57
src/components/CMapGetCoordinates/CMapGetCoordinates.vue
Executable file
@@ -0,0 +1,57 @@
|
||||
<template>
|
||||
<div class="q-pa-sm">
|
||||
<div class="q-gutter-sm">
|
||||
<div class="row q-col-gutter-sm q-mb-sm items-center no-wrap">
|
||||
<div class="col-grow">
|
||||
<q-select
|
||||
v-model="address"
|
||||
label="Indirizzo"
|
||||
use-input
|
||||
input-class="col-auto"
|
||||
input-debounce="300"
|
||||
:options="suggestions"
|
||||
@filter="getAddressSuggestions"
|
||||
filled
|
||||
dense
|
||||
hide-dropdown-icon
|
||||
clearable
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<q-btn @click="searchAddress" label="Cerca" color="primary" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row q-col-gutter-sm">
|
||||
<q-col cols="6">
|
||||
<q-input
|
||||
v-model="coordinates.lat" label="Latitudine:"
|
||||
filled dense />
|
||||
</q-col>
|
||||
<q-col cols="6">
|
||||
<q-input
|
||||
v-model="coordinates.lng"
|
||||
label="Longitudine:"
|
||||
filled
|
||||
dense
|
||||
/>
|
||||
</q-col>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
id="map"
|
||||
:style="`height:${myheight}px; width:99%`"
|
||||
>
|
||||
<p v-if="coordinates && coordinates.lat">
|
||||
Coordinate: {{ coordinates.lat.toFixed(6) }},
|
||||
{{ coordinates.lng.toFixed(6) }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" src="./CMapGetCoordinates.ts">
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './CMapGetCoordinates.scss';
|
||||
</style>
|
||||
1
src/components/CMapGetCoordinates/index.ts
Executable file
1
src/components/CMapGetCoordinates/index.ts
Executable file
@@ -0,0 +1 @@
|
||||
export {default as CMapGetCoordinates} from './CMapGetCoordinates.vue'
|
||||
@@ -87,7 +87,7 @@ export default defineComponent({
|
||||
|
||||
initialMap.value = L.map('map',
|
||||
{
|
||||
zoomControl: true, zoom: zoom.value, zoomAnimation: false,
|
||||
zoomControl: true, zoom: zoom.value, zoomAnimation: true,
|
||||
fadeAnimation: true, markerZoomAnimation: true,
|
||||
center: [42.71, 12.934],
|
||||
}
|
||||
|
||||
@@ -153,4 +153,28 @@ $graytext: #555;
|
||||
.container_butt{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
.expand-fade-enter-active, .expand-fade-leave-active {
|
||||
transition: height 0.3s ease, opacity 0.3s ease; /* Aggiunge transizioni per height e opacity */
|
||||
}
|
||||
|
||||
.expand-fade-enter, .expand-fade-leave-to {
|
||||
height: 0; /* Imposta l'altezza a 0 per l'uscita */
|
||||
opacity: 0; /* Rende invisibile durante l'uscita */
|
||||
}
|
||||
|
||||
.height-transition {
|
||||
transition: height 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.well-positioned-dialog {
|
||||
width: 50vw; /* Imposta la larghezza al 50% della vista */
|
||||
height: auto; /* Puoi regolare l'altezza come preferisci */
|
||||
margin-left: auto; /* Allinea il dialogo a destra */
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); /* Aggiunge una leggera ombra */
|
||||
}
|
||||
|
||||
.riempi {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { computed, defineComponent, onMounted, PropType, ref, watch } from 'vue'
|
||||
import { computed, defineComponent, onMounted, PropType, ref, watch, nextTick } from 'vue'
|
||||
|
||||
import { CMyFieldDb } from '@/components/CMyFieldDb'
|
||||
import { CTitleBanner } from '@/components/CTitleBanner'
|
||||
@@ -58,6 +58,11 @@ export default defineComponent({
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
showAnteprima: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
}
|
||||
},
|
||||
setup(props) {
|
||||
|
||||
@@ -143,6 +148,17 @@ export default defineComponent({
|
||||
const idnotif = computed(() => $route.query.idnotif ? $route.query.idnotif.toString() : '')
|
||||
const arrbookings = computed(() => calendarStore.findAllBookedByIdEvent(myrec.value._id))
|
||||
|
||||
const isSmall = ref(props.showAnteprima);
|
||||
|
||||
const cardRef = ref(<any>null)
|
||||
const smallHeight = ref('30vh')
|
||||
const largeHeight = ref('100vh')
|
||||
|
||||
const cardStyle = computed(() => ({
|
||||
height: isSmall.value ? smallHeight.value : largeHeight.value,
|
||||
transition: 'height 0.3s ease-in-out'
|
||||
}))
|
||||
|
||||
const filtercustom: any = computed(() => {
|
||||
|
||||
let queryreact = {}
|
||||
@@ -201,8 +217,18 @@ export default defineComponent({
|
||||
load()
|
||||
})
|
||||
|
||||
function mounted() {
|
||||
async function mounted() {
|
||||
load()
|
||||
await nextTick()
|
||||
|
||||
}
|
||||
|
||||
function updateCard() {
|
||||
if (cardRef.value) {
|
||||
largeHeight.value = !isSmall.value ? `${cardRef.value.clientHeight}px` : largeHeight.value
|
||||
if (isSmall.value)
|
||||
smallHeight.value = `${cardRef.value.clientHeight}px`
|
||||
}
|
||||
}
|
||||
|
||||
function getlinkpage() {
|
||||
@@ -610,9 +636,20 @@ export default defineComponent({
|
||||
tools.openUrl(tools.getLinkBotTelegram('', ''))
|
||||
}
|
||||
|
||||
const expandDialog = () => {
|
||||
isSmall.value = false; // Cambia lo stato a 'non piccolo'
|
||||
};
|
||||
|
||||
function toggleShowScheda() {
|
||||
// updateCard()
|
||||
isSmall.value = !isSmall.value
|
||||
|
||||
}
|
||||
|
||||
onMounted(mounted)
|
||||
|
||||
return {
|
||||
expandDialog,
|
||||
profile,
|
||||
tools,
|
||||
costanti,
|
||||
@@ -659,6 +696,11 @@ export default defineComponent({
|
||||
extraparams,
|
||||
condividi,
|
||||
getTipodiAttivita,
|
||||
isSmall,
|
||||
cardStyle,
|
||||
cardRef,
|
||||
smallHeight,
|
||||
toggleShowScheda,
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1044,6 +1044,9 @@
|
||||
|
||||
>
|
||||
</q-select>
|
||||
Versione PDF: <q-toggle v-model="myel.catalogo.pdf" color="positive" icon="fas fa-file-pdf"
|
||||
@update:model-value="modifElem">
|
||||
</q-toggle>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
defineComponent, onMounted, PropType, ref, toRef, watch,
|
||||
} from 'vue'
|
||||
|
||||
import { IMyCard, IMyElem, IMyPage, IOperators, ISocial } from '@src/model'
|
||||
import { ICoordGPS, IMyCard, IMyElem, IMyPage, IOperators, ISocial } from '@src/model'
|
||||
import { useGlobalStore } from '@store/globalStore'
|
||||
|
||||
import { CImgTitle } from '../CImgTitle/index'
|
||||
@@ -18,6 +18,8 @@ import { CAITools } from '@/components/CAITools'
|
||||
import { CCatalogo } from '@/components/CCatalogo'
|
||||
// import { CMapMarker } from '@src/components/CMapMarker.off'
|
||||
import { CMapUsers } from '@/components/CMapUsers'
|
||||
import { CMapGetCoordinates } from '@/components/CMapGetCoordinates'
|
||||
import { CMapEditAddressByCoord } from '@/components/CMapEditAddressByCoord'
|
||||
import { CMapComuni } from '@/components/CMapComuni'
|
||||
import { COpenStreetMap } from '@src/components/COpenStreetMap'
|
||||
import { CCardCarousel } from '@src/components/CCardCarousel'
|
||||
@@ -48,6 +50,7 @@ import MixinBase from '@/mixins/mixin-base'
|
||||
import { useQuasar } from 'quasar'
|
||||
import { useI18n } from '@/boot/i18n'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { LatLng } from 'leaflet'
|
||||
|
||||
|
||||
export default defineComponent({
|
||||
@@ -61,7 +64,8 @@ export default defineComponent({
|
||||
CMyProfileTutorial, CSendRISTo,
|
||||
CTitleBanner, CShareSocial, CCheckAppRunning, CRegistration,
|
||||
CVisuVideoPromoAndPDF, CECommerce, CCatalogo, CAITools,
|
||||
CMapComuni, CMapUsers, CDashGroup,
|
||||
CMapComuni, CMapUsers, CMapGetCoordinates, CMapEditAddressByCoord,
|
||||
CDashGroup,
|
||||
// , //CMapMarker,
|
||||
},
|
||||
emits: ['selElemClick'],
|
||||
@@ -119,6 +123,8 @@ export default defineComponent({
|
||||
|
||||
const isAppRunning = computed(() => globalStore.isAppRunning)
|
||||
|
||||
const coordaddr = ref(<ICoordGPS> { address: '', coordinates: [0, 0] })
|
||||
|
||||
watch(() => myel.value.order, (value, oldval) => {
|
||||
mounted()
|
||||
})
|
||||
@@ -289,6 +295,7 @@ export default defineComponent({
|
||||
social,
|
||||
clickshare,
|
||||
isAppRunning,
|
||||
coordaddr,
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -573,6 +573,18 @@
|
||||
<CMapUsers
|
||||
></CMapUsers>
|
||||
</div>
|
||||
<div v-else-if="myel.type === shared_consts.ELEMTYPE.MAPPAGETCOORDINATE">
|
||||
<div v-if="editOn" class="elemEdit">MAPPA COORDINATE:</div>
|
||||
<CMapGetCoordinates
|
||||
></CMapGetCoordinates>
|
||||
</div>
|
||||
<div v-else-if="myel.type === shared_consts.ELEMTYPE.EDITADDRESSBYCOORD">
|
||||
<div v-if="editOn" class="elemEdit">EDIT ADDRESS BY COORD:</div>
|
||||
<CMapEditAddressByCoord
|
||||
:editaddress="true"
|
||||
v-model:model-value="coordaddr"
|
||||
></CMapEditAddressByCoord>
|
||||
</div>
|
||||
<div v-else-if="myel.type === shared_consts.ELEMTYPE.MAPPACOMUNI">
|
||||
<div v-if="editOn" class="elemEdit">MAPPA COMUNI:</div>
|
||||
<CMapComuni
|
||||
|
||||
@@ -11,6 +11,7 @@ import { CLabel } from '../CLabel'
|
||||
import { CMyToggleList } from '../CMyToggleList'
|
||||
import { CMySelect } from '../CMySelect'
|
||||
import { CCurrencyValue } from '../CCurrencyValue'
|
||||
import { CMapEditAddressByCoord } from '../CMapEditAddressByCoord'
|
||||
import { CMyEditor } from '../CMyEditor'
|
||||
import { CGallery } from '../CGallery'
|
||||
import { CSelectImage } from '../CSelectImage'
|
||||
@@ -221,7 +222,7 @@ export default defineComponent({
|
||||
},
|
||||
components: {
|
||||
CMyChipList, CDateTime, CDate, CMyToggleList, CMySelect, CMyEditor, CGallery,
|
||||
CCurrencyValue, CLabel, CAccomodation, CSelectImage
|
||||
CCurrencyValue, CLabel, CAccomodation, CSelectImage, CMapEditAddressByCoord,
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const $q = useQuasar()
|
||||
@@ -240,6 +241,8 @@ export default defineComponent({
|
||||
|
||||
const $router = useRouter()
|
||||
|
||||
const loaded = ref(false)
|
||||
|
||||
const col = ref(<IColGridTable>{
|
||||
name: 'test',
|
||||
fieldtype: 0,
|
||||
@@ -389,7 +392,23 @@ export default defineComponent({
|
||||
return null
|
||||
}
|
||||
|
||||
function changeValRecCoordAddr(newval: any) {
|
||||
// console.log('changeValRecCoordAddr', newval, 'myrow', myrow.value[col.value.name])
|
||||
if (!myrow.value[col.value.name]) {
|
||||
myrow.value[col.value.name] = {}
|
||||
}
|
||||
if (newval.coordinates && newval.coordinates.lat) {
|
||||
newval.coordinates.lat = tools.convertToDecimal6(newval.coordinates.lat)
|
||||
newval.coordinates.lng = tools.convertToDecimal6(newval.coordinates.lng)
|
||||
}
|
||||
// console.log('newval...', newval)
|
||||
return changevalRecOrig(newval)
|
||||
}
|
||||
function changevalRec(newval: any) {
|
||||
return changevalRecOrig(newval, '')
|
||||
}
|
||||
|
||||
function changevalRecOrig(newval: any, subcol: string = '') {
|
||||
// console.log('changevalRec', newval)
|
||||
// if (!props.insertMode || (props.insertMode && col.value.fieldtype !== costanti.FieldType.multioption)) {
|
||||
if (col.value && col.value.allowchar === costanti.ALLOWCHAR_CODE) {
|
||||
@@ -407,7 +426,15 @@ export default defineComponent({
|
||||
newval = tools.rimuoviAtPrimoCarattere(newval)
|
||||
}
|
||||
|
||||
myrow.value[col.value.name] = newval
|
||||
if (subcol) {
|
||||
if (!myrow.value[col.value.name]) {
|
||||
myrow.value[col.value.name] = {}
|
||||
}
|
||||
myrow.value[col.value.name][subcol] = newval
|
||||
// console.log('myrow.value[col.value.name]', myrow.value[col.value.name])
|
||||
} else {
|
||||
myrow.value[col.value.name] = newval
|
||||
}
|
||||
|
||||
|
||||
// console.log('changevalRec update:row', myrow.value)
|
||||
@@ -434,6 +461,7 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
function mounted() {
|
||||
console.log('mounted')
|
||||
|
||||
myrow.value = props.rec && props.isrec ? { ...props.rec } : { ...props.row }
|
||||
|
||||
@@ -466,30 +494,50 @@ export default defineComponent({
|
||||
|
||||
// console.log('popupedit: myvalue.value', myvalue.value)
|
||||
|
||||
if (col.value.fieldtype === costanti.FieldType.listimages) {
|
||||
if (myvalue.value === '' || myvalue.value === undefined) {
|
||||
// console.log('set default myvalue.value ')
|
||||
myvalue.value = {
|
||||
title: 'Galleria',
|
||||
directory: 'none',
|
||||
list: []
|
||||
}
|
||||
}
|
||||
} else if (col.value.fieldtype === costanti.FieldType.listobj) {
|
||||
if (myvalue.value === '' || myvalue.value === undefined) {
|
||||
// console.log('set default myvalue.value ')
|
||||
myvalue.value = [{
|
||||
type: 0, // Letto matrimoniale / letto singolo / divano-letto / almaca / a terra sul tappeto (per sacco a pelo)
|
||||
location: 0, // in camera privata / in camera condivisa / in soggiorno / in camper / in tenda / in giardino / all'aperto
|
||||
num: 0,
|
||||
}]
|
||||
}
|
||||
}
|
||||
// console.log('myvalue.value', myvalue.value)
|
||||
myvalueprec.value = myvalue.value
|
||||
|
||||
crea()
|
||||
|
||||
if (!loaded.value) {
|
||||
|
||||
if (col.value.fieldtype === costanti.FieldType.listimages) {
|
||||
if (myvalue.value === '' || myvalue.value === undefined) {
|
||||
// console.log('set default myvalue.value ')
|
||||
myvalue.value = {
|
||||
title: 'Galleria',
|
||||
directory: 'none',
|
||||
list: []
|
||||
}
|
||||
}
|
||||
} else if (col.value.fieldtype === costanti.FieldType.listobj) {
|
||||
if (myvalue.value === '' || myvalue.value === undefined) {
|
||||
// console.log('set default myvalue.value ')
|
||||
myvalue.value = [{
|
||||
type: 0, // Letto matrimoniale / letto singolo / divano-letto / almaca / a terra sul tappeto (per sacco a pelo)
|
||||
location: 0, // in camera privata / in camera condivisa / in soggiorno / in camper / in tenda / in giardino / all'aperto
|
||||
num: 0,
|
||||
}]
|
||||
}
|
||||
} else if (col.value.fieldtype === costanti.FieldType.coordinates) {
|
||||
if (myvalue.value === '' || myvalue.value === undefined) {
|
||||
// console.log('set default myvalue.value ')
|
||||
myvalue.value = {
|
||||
address: '',
|
||||
coordinates: [0, 0]
|
||||
}
|
||||
}
|
||||
if (!myvalue.value.address) {
|
||||
myvalue.value.address = ''
|
||||
}
|
||||
if (!myvalue.value.coordinates) {
|
||||
myvalue.value.coordinates = [0, 0]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loaded.value = true
|
||||
|
||||
// console.log('myvalueprec', myvalueprec)
|
||||
}
|
||||
|
||||
@@ -868,6 +916,7 @@ export default defineComponent({
|
||||
nameKeydown,
|
||||
gotoPage,
|
||||
mypath,
|
||||
changeValRecCoordAddr,
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -299,6 +299,14 @@
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="col.fieldtype === costanti.FieldType.coordinates">
|
||||
<CMapEditAddressByCoord
|
||||
:visuMappa="false"
|
||||
:editaddress="true"
|
||||
v-model:model-value="myvalue"
|
||||
@update:model-value="changeValRecCoordAddr"
|
||||
></CMapEditAddressByCoord>
|
||||
</div>
|
||||
<div
|
||||
v-else-if="
|
||||
col.fieldtype === costanti.FieldType.number ||
|
||||
@@ -368,6 +376,9 @@
|
||||
v-else-if="col.fieldtype === costanti.FieldType.listimages"
|
||||
style="text-align: center"
|
||||
>
|
||||
<span class="text-h7 text-weight-bold row justify-center">
|
||||
{{ $t(col.label_trans) }}
|
||||
</span>
|
||||
<CGallery
|
||||
:imagebak="
|
||||
col.showpicprofile_ifnotset
|
||||
@@ -399,10 +410,14 @@
|
||||
>
|
||||
</CAccomodation>
|
||||
</div>
|
||||
<div v-else-if="col.fieldtype === costanti.FieldType.image"
|
||||
style="text-align: center">
|
||||
<div
|
||||
v-else-if="col.fieldtype === costanti.FieldType.image"
|
||||
style="text-align: center"
|
||||
>
|
||||
<div v-if="canEdit">
|
||||
{{ $t('reg.photo') }}
|
||||
<span class="text-h7 text-weight-bold row justify-center">
|
||||
{{ $t(col.label_trans) }}
|
||||
</span>
|
||||
<CGallery
|
||||
:imagebak="
|
||||
col.showpicprofile_ifnotset
|
||||
@@ -1120,7 +1135,11 @@
|
||||
<q-popup-edit
|
||||
v-if="!isInModif && canEdit && noPopupeditByCol(col)"
|
||||
v-model="myvalue"
|
||||
:disable="(col.disable || disable) || (col.fieldtype === costanti.FieldType.image_and_filename)"
|
||||
:disable="
|
||||
col.disable ||
|
||||
disable ||
|
||||
col.fieldtype === costanti.FieldType.image_and_filename
|
||||
"
|
||||
:readonly="col.disable || disable"
|
||||
:title="col.title ? col.title : col.titlepopupedit"
|
||||
buttons
|
||||
@@ -1197,6 +1216,14 @@
|
||||
>
|
||||
</CCurrencyValue>
|
||||
</div>
|
||||
<div v-else-if="col.fieldtype === costanti.FieldType.coordinates">
|
||||
<CMapEditAddressByCoord
|
||||
:visuMappa="false"
|
||||
:editaddress="true"
|
||||
v-model:model-value="scope.value"
|
||||
@update:model-value="changeValRec"
|
||||
></CMapEditAddressByCoord>
|
||||
</div>
|
||||
<div v-else-if="col.fieldtype === costanti.FieldType.hours">
|
||||
<div v-if="visulabel">
|
||||
<q-input
|
||||
@@ -1552,7 +1579,11 @@
|
||||
</CMyEditor>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="col.fieldtype === costanti.FieldType.image_and_filename">
|
||||
<div
|
||||
v-else-if="
|
||||
col.fieldtype === costanti.FieldType.image_and_filename
|
||||
"
|
||||
>
|
||||
<div v-if="canEdit">
|
||||
{{ $t('reg.photo') }}
|
||||
<q-input
|
||||
|
||||
@@ -92,7 +92,7 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
function navigaExt(obj: any) {
|
||||
cmdExt(costanti.CMD_SHOW_PAGE, obj, null)
|
||||
cmdExt(costanti.CMD_SHOW_PAGE, null, obj)
|
||||
//let link = shared_consts.getDirectoryByTable(props.table) + '/' + obj._id
|
||||
//console.log('link', link)
|
||||
//$router.push(link)
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
img-class="imgprofile"
|
||||
height="270px"
|
||||
fit="contain"
|
||||
@click="cmdExt(costanti.CMD_SHOW_PAGE, myrec)"
|
||||
@click="cmdExt(costanti.CMD_SHOW_PAGE, null, myrec)"
|
||||
/>
|
||||
<div>
|
||||
{{ tools.getstrDateTimeEvent($t, myrec, false) }}
|
||||
@@ -57,7 +57,7 @@
|
||||
(myrec.mygrp && myrec.mygrp.photos.length > 0)
|
||||
"
|
||||
avatar
|
||||
@click="cmdExt(costanti.CMD_SHOW_PAGE, myrec)"
|
||||
@click="cmdExt(costanti.CMD_SHOW_PAGE, null, myrec)"
|
||||
>
|
||||
<q-badge
|
||||
v-if="showBadge()"
|
||||
@@ -286,7 +286,7 @@
|
||||
<q-item
|
||||
clickable
|
||||
v-close-popup
|
||||
@click="cmdExt(costanti.CMD_MODIFY, myrec._id)"
|
||||
@click="cmdExt(costanti.CMD_MODIFY, myrec._id, null)"
|
||||
>
|
||||
<q-item-section side>
|
||||
<q-icon name="fas fa-pencil-alt" />
|
||||
@@ -298,7 +298,7 @@
|
||||
<q-item
|
||||
clickable
|
||||
v-close-popup
|
||||
@click="cmdExt(costanti.CMD_CLONE, myrec._id)"
|
||||
@click="cmdExt(costanti.CMD_CLONE, myrec._id, null)"
|
||||
>
|
||||
<q-item-section side>
|
||||
<q-icon name="fas fa-copy" />
|
||||
@@ -310,7 +310,7 @@
|
||||
<q-item
|
||||
clickable
|
||||
v-close-popup
|
||||
@click="cmdExt(costanti.CMD_DELETE, myrec._id)"
|
||||
@click="cmdExt(costanti.CMD_DELETE, myrec._id, null)"
|
||||
>
|
||||
<q-item-section side>
|
||||
<q-icon name="fas fa-trash-alt" />
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
v-if="circuit.photos"
|
||||
avatar
|
||||
class="items-center"
|
||||
@click="cmdExt(costanti.CMD_OPEN_PAGE, circuit)"
|
||||
@click="cmdExt(costanti.CMD_OPEN_PAGE, null, circuit)"
|
||||
>
|
||||
<q-avatar size="60px">
|
||||
<q-img
|
||||
@@ -48,7 +48,7 @@
|
||||
</span>
|
||||
</q-item-section>
|
||||
|
||||
<q-item-section @click="cmdExt(costanti.CMD_OPEN_PAGE, circuit)">
|
||||
<q-item-section @click="cmdExt(costanti.CMD_OPEN_PAGE, null, circuit)">
|
||||
<q-item-label
|
||||
@click="naviga(tools.getPathByTableAndRec(table, circuit))"
|
||||
><strong>{{ circuit.name }}</strong>
|
||||
@@ -132,7 +132,7 @@
|
||||
<q-item
|
||||
clickable
|
||||
v-close-popup
|
||||
@click="cmdExt(costanti.CMD_MODIFY, circuit._id)"
|
||||
@click="cmdExt(costanti.CMD_MODIFY, circuit._id, null)"
|
||||
>
|
||||
<q-item-section side>
|
||||
<q-icon name="fas fa-pencil-alt" />
|
||||
@@ -144,7 +144,7 @@
|
||||
<q-item
|
||||
clickable
|
||||
v-close-popup
|
||||
@click="cmdExt(costanti.CMD_DELETE, circuit._id)"
|
||||
@click="cmdExt(costanti.CMD_DELETE, circuit._id, null)"
|
||||
>
|
||||
<q-item-section side>
|
||||
<q-icon name="fas fa-trash-alt" />
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
</q-avatar>
|
||||
</q-item-section>
|
||||
|
||||
<q-item-section @click="cmdExt(costanti.CMD_OPEN_PAGE, myrec)">
|
||||
<q-item-section @click="cmdExt(costanti.CMD_OPEN_PAGE, null, myrec)">
|
||||
<q-item-label class="full-width">
|
||||
<span v-for="(rec, ind) of myrec.recCatGrp" :key="ind"> <q-chip
|
||||
dense
|
||||
@@ -46,7 +46,7 @@
|
||||
<q-menu>
|
||||
<q-list style="min-width: 150px">
|
||||
<q-item clickable v-close-popup
|
||||
@click="cmdExt(costanti.CMD_MODIFY, myrec._id)">
|
||||
@click="cmdExt(costanti.CMD_MODIFY, myrec._id, null)">
|
||||
<q-item-section side>
|
||||
<q-icon name="fas fa-pencil-alt"/>
|
||||
</q-item-section>
|
||||
@@ -54,7 +54,7 @@
|
||||
</q-item>
|
||||
</q-list>
|
||||
<q-list style="min-width: 150px">
|
||||
<q-item clickable v-close-popup @click="cmdExt(costanti.CMD_DELETE, myrec._id)">
|
||||
<q-item clickable v-close-popup @click="cmdExt(costanti.CMD_DELETE, myrec._id, null)">
|
||||
<q-item-section side>
|
||||
<q-icon name="fas fa-trash-alt"/>
|
||||
</q-item-section>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
const msg_website_it = {
|
||||
ws: {
|
||||
sitename: 'Riso',
|
||||
siteshortname: 'RISO',
|
||||
description: 'Siamo la Rete Italiana di Scambio Orizzontale, abbiamo creato questa piattaforma per metterla al servizio di chi vuole riscoprire il valore della condivisione e della cooperazione. Valori semplici e profondi che ci aiutano a ritrovare il Senso della Vita, perduto in questa società consumista, e riporti quei Sani Pricìpi Naturali ed Umani di Fratellanza che intere popolazioni antiche conoscevano bene.',
|
||||
keywords: 'riso, piattaforma di scambio, rete italiana scambio orizzontale, riso app, riso piattaforma, scambio e baratto, momenta RIS',
|
||||
sitename: 'AbitareGliIblei',
|
||||
siteshortname: 'AbitareGliIblei',
|
||||
description: 'Abitare Gli Iblei',
|
||||
keywords: '',
|
||||
},
|
||||
hours: {
|
||||
descr: 'Descrizione',
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<meta name="description" content="<%= productDescription %>">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<meta name="msapplication-tap-highlight" content="no">
|
||||
<meta name="version" content="1.0.53">
|
||||
<meta name="version" content="1.0.55">
|
||||
<meta name="viewport"
|
||||
content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width<% if (ctx.mode.cordova || ctx.mode.capacitor) { %>, viewport-fit=cover<% } %>">
|
||||
|
||||
|
||||
@@ -645,6 +645,7 @@ export interface ICatalogo {
|
||||
formato: string[]
|
||||
Categoria: string[]
|
||||
Editore: string[]
|
||||
pdf: boolean
|
||||
}
|
||||
|
||||
|
||||
@@ -1234,18 +1235,34 @@ export interface IAnim {
|
||||
timingtype: string,
|
||||
}
|
||||
|
||||
export interface ICoordLatLng {
|
||||
lat: any
|
||||
lng: any
|
||||
}
|
||||
|
||||
|
||||
|
||||
export interface ICoordinates {
|
||||
lat: any
|
||||
long: any
|
||||
}
|
||||
|
||||
export interface ICoordinatesGPS {
|
||||
coordinates: [number, number]; // [lng, lat]
|
||||
}
|
||||
|
||||
export interface ITipoDiAttivita {
|
||||
_id: string
|
||||
label: string
|
||||
note: string
|
||||
}
|
||||
|
||||
export interface ICoordGPS {
|
||||
address: string
|
||||
type: string
|
||||
coordinates: [number, number]
|
||||
}
|
||||
|
||||
export interface IAttivita {
|
||||
_id: string
|
||||
|
||||
@@ -1256,7 +1273,7 @@ export interface IAttivita {
|
||||
idSector: number[]
|
||||
|
||||
idCity: number[]
|
||||
coordinate_gps: string
|
||||
coordinate_gps: ICoordGPS
|
||||
|
||||
// FOTO
|
||||
logo: IGallery
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
<CFinder
|
||||
:ind="tools.getIndMainCardsByTable(shared_consts.TABLES_ATTIVITAS)"
|
||||
:table="shared_consts.TABLES_ATTIVITAS"
|
||||
:showMap="true"
|
||||
/>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -3,11 +3,14 @@ import {
|
||||
} from 'vue-router'
|
||||
|
||||
import { cfgrouter } from './route-config'
|
||||
import { useGlobalStore } from '@src/store/globalStore';
|
||||
|
||||
export default function (/* { store, ssrContext } */) {
|
||||
import { useUserStore } from '@src/store/UserStore';
|
||||
|
||||
export default function ({ store, /*ssrContext } */}: {store: any}) {
|
||||
const routermode = process.env.VUE_ROUTER_MODE === 'history' ? createWebHistory : createWebHashHistory
|
||||
|
||||
const userStore = useUserStore(store)
|
||||
|
||||
const createHistory = process.env.SERVER
|
||||
? createMemoryHistory
|
||||
: routermode
|
||||
@@ -20,8 +23,10 @@ export default function (/* { store, ssrContext } */) {
|
||||
),
|
||||
});
|
||||
|
||||
/*
|
||||
// Add the beforeEach hook
|
||||
router.beforeEach((to, from, next) => {
|
||||
console.log('beforeEach ROUTER')
|
||||
// Execute your command before each navigation
|
||||
// executeCommand();
|
||||
|
||||
@@ -31,11 +36,18 @@ export default function (/* { store, ssrContext } */) {
|
||||
} catch(e) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
//if (to.matched.some(record => record.meta.requiresAuth) && !userStore.isLogged) {
|
||||
// next({ name: 'login', query: { next: to.fullPath } })
|
||||
//} else {
|
||||
// next()
|
||||
//}
|
||||
|
||||
|
||||
// Continue with the navigation
|
||||
next();
|
||||
});
|
||||
}); */
|
||||
|
||||
return router;
|
||||
}
|
||||
|
||||
5
src/shims-vue.d.ts
vendored
5
src/shims-vue.d.ts
vendored
@@ -6,3 +6,8 @@ declare module '*.vue' {
|
||||
export default Component;
|
||||
|
||||
}
|
||||
|
||||
declare module '*.png' {
|
||||
const value: string;
|
||||
export default value;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ const msg_it = {
|
||||
csv: 'Esporta Movimenti',
|
||||
},
|
||||
grid: {
|
||||
showlist: 'Mostra la Lista',
|
||||
showmap: 'Mostra la Mappa',
|
||||
editvalues: 'Modifica Valori',
|
||||
addrecord: 'Aggiungi Riga',
|
||||
showprevedit: 'Mostra Eventi Passati',
|
||||
@@ -277,6 +279,7 @@ const msg_it = {
|
||||
},
|
||||
scrivi: 'Contatta',
|
||||
telegram: 'Messaggia su Telegram',
|
||||
uscire: 'Uscire senza salvare?',
|
||||
},
|
||||
comp: {
|
||||
Conta: 'Conta',
|
||||
@@ -1807,7 +1810,7 @@ const msg_it = {
|
||||
},
|
||||
attivita: {
|
||||
tipodiattivita: 'Tipologia',
|
||||
name: 'Nome Attività',
|
||||
nome_attivita: 'Nome Attività',
|
||||
email: 'Email',
|
||||
cell_phone: 'Telefono',
|
||||
whatsapp: 'Whatsapp',
|
||||
|
||||
@@ -262,7 +262,7 @@ export const costanti = {
|
||||
small: true,
|
||||
table: '',
|
||||
},
|
||||
/*{
|
||||
{
|
||||
visible: false,
|
||||
title: ' Attività ',
|
||||
subtitle: 'Artigiani, Aziende, Società, Negozi',
|
||||
@@ -275,7 +275,7 @@ export const costanti = {
|
||||
visuonstat: true,
|
||||
small: false,
|
||||
showfavorite: true,
|
||||
},*/
|
||||
},
|
||||
],
|
||||
|
||||
GROUPCARDS: [
|
||||
@@ -409,6 +409,7 @@ export const costanti = {
|
||||
image: 3000,
|
||||
image_and_filename: 3100,
|
||||
imgcard: 3500,
|
||||
coordinates: 3800,
|
||||
select_by_server: 4000,
|
||||
multiselect_by_server: 4010,
|
||||
nationality: 4096,
|
||||
|
||||
@@ -1261,6 +1261,13 @@ export const colAttivita = [
|
||||
isadvanced_field: true,
|
||||
numpag_carousel: 3,
|
||||
}),
|
||||
AddCol({
|
||||
name: 'coordinate_gps',
|
||||
label_trans: 'attivita.coordinate_gps',
|
||||
fieldtype: costanti.FieldType.coordinates,
|
||||
showWhen: costanti.showWhen.NewRec + costanti.showWhen.InPage + costanti.showWhen.InEdit + costanti.showWhen.InView_OnlyifExist,
|
||||
required: false,
|
||||
}),
|
||||
AddCol({
|
||||
name: 'idCity',
|
||||
label_trans: 'skill.city',
|
||||
@@ -1314,8 +1321,6 @@ export const colAttivita = [
|
||||
}),
|
||||
AddCol({ name: 'website', label_trans: 'attivita.website' }),
|
||||
|
||||
AddCol({ name: 'coordinate_gps', label_trans: 'attivita.coordinate_gps', fieldtype: costanti.FieldType.string }),
|
||||
|
||||
AddCol({
|
||||
name: 'logo',
|
||||
label_trans: 'attivita.logo',
|
||||
|
||||
19
src/store/Modules/geocodingmap.ts
Normal file
19
src/store/Modules/geocodingmap.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
// geocoding.ts
|
||||
export const getCityFromCoordinates = async (lat: number, lon: number): Promise<string | null> => {
|
||||
const url = `https://nominatim.openstreetmap.org/reverse?lat=${lat}&lon=${lon}&format=json`;
|
||||
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) {
|
||||
throw new Error('Errore nella richiesta di geocoding');
|
||||
}
|
||||
const data = await response.json();
|
||||
|
||||
// Controlla se la città è presente nei risultati
|
||||
return data.address?.city || data.address?.town || data.address?.village || null;
|
||||
} catch (error) {
|
||||
console.error('Errore durante il geocoding:', error);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -73,6 +73,7 @@ export const tools = {
|
||||
COOK_MAP_CENTER_LAT: 'MAP_LAT',
|
||||
COOK_MAP_CENTER_LONG: 'MAP_LONG',
|
||||
COOK_MAP_ZOOM: 'MAP_Z',
|
||||
COOK_CATEGORIA: 'CATEG',
|
||||
|
||||
FRIENDS_SEARCH: 'FR_SE',
|
||||
GROUP_SEARCH: 'GR_SE',
|
||||
@@ -6561,7 +6562,7 @@ export const tools = {
|
||||
userStore.my.profile.useraccounts = res.useraccounts
|
||||
}
|
||||
$router.push('/circuits')
|
||||
tools.showPositiveNotif($q, t('circuit.coins_sent', {qty: sendcoinrec.qty, symbol: circuit.symbol, dest}))
|
||||
tools.showPositiveNotif($q, t('circuit.coins_sent', { qty: sendcoinrec.qty, symbol: circuit.symbol, dest }))
|
||||
//tools.showPositiveNotif($q, t('circuit.coins_sendrequest_sent'))
|
||||
} else {
|
||||
tools.showNegativeNotif($q, res.errormsg)
|
||||
@@ -8687,8 +8688,27 @@ export const tools = {
|
||||
},
|
||||
|
||||
getRecByVersioneProd(versione: number) {
|
||||
|
||||
return shared_consts.VERSIONI_PRODOTTO.find((rec: any) => rec.value === versione)
|
||||
|
||||
return shared_consts.VERSIONI_PRODOTTO.find((rec: any) => rec.value === versione)
|
||||
},
|
||||
|
||||
convertToDecimal6(stringValue: string) {
|
||||
// Converti la stringa in un numero
|
||||
try {
|
||||
const numberValue = parseFloat(stringValue);
|
||||
|
||||
// Controlla se la conversione è un numero valido
|
||||
if (isNaN(numberValue)) {
|
||||
// console.error('Valore non valido:', stringValue);
|
||||
return 0
|
||||
}
|
||||
|
||||
// Usa toFixed per creare un numero con 6 decimali
|
||||
return parseFloat(numberValue.toFixed(6));
|
||||
} catch (error) {
|
||||
console.error('Errore durante la conversione:', error);
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
// FINE !
|
||||
|
||||
@@ -2122,6 +2122,7 @@ export const useGlobalStore = defineStore('GlobalStore', {
|
||||
formato: [],
|
||||
Categoria: [],
|
||||
Editore: [],
|
||||
pdf: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,10 @@ import { CContainerCatalogoCard } from '@src/components/CContainerCatalogoCard'
|
||||
import { CSelectUserActive } from '@src/components/CSelectUserActive'
|
||||
import { ICatalogo, IProduct, ISearchList } from 'model'
|
||||
|
||||
import html2canvas from 'html2canvas'
|
||||
// import { VueHtmlToPaper } from 'vue-html-to-paper'
|
||||
import html2pdf from 'html2pdf.js'
|
||||
|
||||
import { fieldsTable } from '@store/Modules/fieldsTable'
|
||||
|
||||
export default defineComponent({
|
||||
@@ -32,6 +36,7 @@ export default defineComponent({
|
||||
formato: [],
|
||||
Categoria: [],
|
||||
Editore: [],
|
||||
pdf: false,
|
||||
}),
|
||||
},
|
||||
},
|
||||
@@ -46,6 +51,9 @@ export default defineComponent({
|
||||
const search = ref('')
|
||||
const optauthors = ref(<any>[])
|
||||
|
||||
const pdfContent = ref(null);
|
||||
|
||||
|
||||
const filter = ref(<any>{
|
||||
author: '',
|
||||
sort: 1,
|
||||
@@ -105,6 +113,8 @@ export default defineComponent({
|
||||
watch(() => cat.value, (newval, oldval) => {
|
||||
|
||||
if (cat.value) {
|
||||
if (loadpage.value)
|
||||
tools.setCookie(tools.COOK_CATEGORIA, cat.value.toString())
|
||||
filter.value.author = '' // disattivo il filtro autore
|
||||
resetSearch()
|
||||
}
|
||||
@@ -127,6 +137,8 @@ export default defineComponent({
|
||||
// Se filtroAuthor attivato, allora evito il filtro per Categoria
|
||||
if (filter.value.author) {
|
||||
cat.value = '' // disattivo il filtro categoria
|
||||
if (loadpage.value)
|
||||
tools.setCookie(tools.COOK_CATEGORIA, '')
|
||||
resetSearch()
|
||||
}
|
||||
|
||||
@@ -145,10 +157,15 @@ export default defineComponent({
|
||||
})
|
||||
|
||||
watch(() => cosa.value, (newval, oldval) => {
|
||||
tools.setCookie(tools.COOK_COSA_PRODOTTI, cosa.value.toString())
|
||||
if (cosa.value !== shared_consts.PROD.TUTTI)
|
||||
cat.value = ''
|
||||
calcArrProducts()
|
||||
if (oldval !== 0) {
|
||||
tools.setCookie(tools.COOK_COSA_PRODOTTI, cosa.value.toString())
|
||||
if (cosa.value !== shared_consts.PROD.TUTTI) {
|
||||
cat.value = ''
|
||||
if (loadpage.value)
|
||||
tools.setCookie(tools.COOK_CATEGORIA, '')
|
||||
}
|
||||
calcArrProducts()
|
||||
}
|
||||
})
|
||||
|
||||
function resetSearch() {
|
||||
@@ -272,10 +289,10 @@ export default defineComponent({
|
||||
if (!search.value) {
|
||||
return arrprod
|
||||
}
|
||||
|
||||
|
||||
let lowerSearchText = search.value.toLowerCase();
|
||||
let catstr = cat.value;
|
||||
|
||||
|
||||
return arrprod.filter((product: IProduct) => {
|
||||
let lowerName = product.productInfo.name!.toLowerCase();
|
||||
const hasCategoria = !catstr || (catstr && product.productInfo.idCatProds?.includes(catstr));
|
||||
@@ -309,6 +326,8 @@ export default defineComponent({
|
||||
//++Todo: Per ora visualizzo solo il "Negozio" e non i GAS...
|
||||
cosa.value = shared_consts.PROD.BOTTEGA
|
||||
|
||||
cat.value = tools.getCookie(tools.COOK_CATEGORIA, '')
|
||||
|
||||
//cosa.value = tools.getCookie(tools.COOK_COSA_PRODOTTI, shared_consts.PROD.GAS, true)
|
||||
//if (cosa.value === shared_consts.PROD.TUTTI)
|
||||
|
||||
@@ -398,6 +417,49 @@ export default defineComponent({
|
||||
return globalStore.getTableJoinByName(item.table, addall, addnone, item.filter)
|
||||
})
|
||||
|
||||
const loadImage = (src) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const img = new Image()
|
||||
img.onload = () => resolve(img)
|
||||
img.onerror = reject
|
||||
img.src = src
|
||||
})
|
||||
}
|
||||
|
||||
const generatePDF = async () => {
|
||||
$q.loading.show({
|
||||
message: 'Caricamento immagini e generazione PDF in corso...'
|
||||
})
|
||||
|
||||
try {
|
||||
|
||||
const element = document.getElementById('pdf-content')
|
||||
const opt = {
|
||||
margin: 1,
|
||||
filename: 'catalogo_libri.pdf',
|
||||
image: { type: 'jpeg', quality: 0.98 },
|
||||
html2canvas: { scale: 2, useCORS: true },
|
||||
jsPDF: { unit: 'in', format: 'a4', orientation: 'portrait' }
|
||||
}
|
||||
|
||||
await html2pdf().from(element).set(opt).save()
|
||||
|
||||
$q.loading.hide()
|
||||
$q.notify({
|
||||
color: 'positive',
|
||||
message: 'PDF generato con successo!',
|
||||
icon: 'check'
|
||||
})
|
||||
} catch (error) {
|
||||
$q.loading.hide()
|
||||
$q.notify({
|
||||
color: 'negative',
|
||||
message: 'Errore nella generazione del PDF',
|
||||
icon: 'error'
|
||||
})
|
||||
console.error('Errore nella generazione del PDF:', error)
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(mounted)
|
||||
|
||||
@@ -434,6 +496,8 @@ export default defineComponent({
|
||||
mycolumns,
|
||||
tabvisu,
|
||||
getSearchText,
|
||||
generatePDF,
|
||||
pdfContent,
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
<template>
|
||||
<q-page>
|
||||
<q-btn v-if="optcatalogo.pdf" label="Crea PDF" @click="generatePDF"></q-btn>
|
||||
<!--<div ref="pdfContent" class="pdf-content">-->
|
||||
|
||||
<div class="text-center">
|
||||
<q-spinner v-if="!loadpage" color="primary" size="3em" :thickness="2" />
|
||||
</div>
|
||||
<div v-if="loadpage" class="panel">
|
||||
<div v-if="true"></div>
|
||||
|
||||
<div class="container">
|
||||
<q-tabs v-model="tabvisu" dense class="bg-indigo text-white">
|
||||
<q-tab name="categorie" icon="fas fa-folder-open" label="Categorie">
|
||||
@@ -140,7 +141,6 @@
|
||||
</q-tab-panel>
|
||||
</q-tab-panels>
|
||||
|
||||
|
||||
<div class="row justify-center q-mx-auto">
|
||||
<q-select
|
||||
v-model="filter.sort"
|
||||
@@ -175,19 +175,62 @@
|
||||
</div>
|
||||
|
||||
<div class="row justify-around">
|
||||
<q-infinite-scroll
|
||||
v-if="arrLoaded && arrLoaded.length > 0"
|
||||
ref="myinfscroll"
|
||||
:initial-index="0"
|
||||
@load="onLoadScroll"
|
||||
:offset="2000"
|
||||
debounce="200"
|
||||
class="q-pa-xs row items-start"
|
||||
style="place-content: center"
|
||||
>
|
||||
<div>
|
||||
<q-infinite-scroll
|
||||
v-if="!optcatalogo.pdf && arrLoaded && arrLoaded.length > 0"
|
||||
ref="myinfscroll"
|
||||
:initial-index="0"
|
||||
@load="onLoadScroll"
|
||||
:offset="2000"
|
||||
debounce="200"
|
||||
class="q-pa-xs row items-start"
|
||||
style="place-content: center"
|
||||
>
|
||||
<div
|
||||
class="q-pa-xs"
|
||||
v-for="(product, index) in arrLoaded"
|
||||
:key="index"
|
||||
>
|
||||
<CContainerCatalogoCard
|
||||
v-if="
|
||||
product.active ||
|
||||
(show_hide &&
|
||||
productInfo.productTypes.includes(
|
||||
shared_consts.PRODUCTTYPE.PRODUCT
|
||||
))
|
||||
"
|
||||
:id="product._id"
|
||||
:complete="false"
|
||||
:cosa="cosa"
|
||||
:optcatalogo="optcatalogo"
|
||||
:options="{
|
||||
show_short_descr: false,
|
||||
show_price: false,
|
||||
show_cat: false,
|
||||
quante_col: 'c2',
|
||||
in_3d: false,
|
||||
}"
|
||||
@selauthor="selauthor"
|
||||
/>
|
||||
<CProductCard
|
||||
v-else-if="product.active || show_hide"
|
||||
:id="product._id"
|
||||
:complete="false"
|
||||
:cosa="cosa"
|
||||
/>
|
||||
</div>
|
||||
<template v-slot:loading>
|
||||
<div class="text-center">
|
||||
<q-spinner-dots color="primary" size="40px" />
|
||||
</div>
|
||||
</template>
|
||||
</q-infinite-scroll>
|
||||
<div
|
||||
class="q-pa-xs"
|
||||
v-for="(product, index) in arrLoaded"
|
||||
v-else
|
||||
id="pdf-content"
|
||||
class="q-pa-xs row items-start"
|
||||
style="place-content: center"
|
||||
v-for="(product, index) in arrProducts"
|
||||
:key="index"
|
||||
>
|
||||
<CContainerCatalogoCard
|
||||
@@ -218,12 +261,7 @@
|
||||
:cosa="cosa"
|
||||
/>
|
||||
</div>
|
||||
<template v-slot:loading>
|
||||
<div class="text-center">
|
||||
<q-spinner-dots color="primary" size="40px" />
|
||||
</div>
|
||||
</template>
|
||||
</q-infinite-scroll>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user