import type { PropType } from 'vue'; import { defineComponent, ref, watch, onMounted, computed } from 'vue'; import { useI18n } from 'vue-i18n'; import { useUserStore } from '@store/UserStore'; import { useQuasar } from 'quasar'; import type { IImgGallery } from 'model'; import { IGallery } from 'model'; import { CMyPage } from '@src/components/CMyPage'; import { tools } from '@tools'; import { useGlobalStore } from '@store/globalStore'; import { costanti } from '@costanti'; import { shared_consts } from 'app/src/common/shared_vuejs'; import { Api } from 'app/src/store/Api'; import axios from 'app/src/boot/axios'; import { toolsext } from 'app/src/store/Modules/toolsext'; export default defineComponent({ name: 'CGallery', props: { edit: { type: Boolean, required: true, }, canModify: { type: Boolean, required: true, }, isInModif: { type: Boolean, required: false, default: false, }, single: { type: Boolean, required: false, default: false, }, title: String, directory: { type: String, required: true, }, imagebak: { type: String, required: false, default: '', }, filetype: { type: Number, required: false, default: shared_consts.FILETYPE.IMG, }, quality: { type: String, required: false, default: 'original', }, resize: { type: Boolean, required: false, default: false, }, fieldtype: { type: Number, required: false, default: 0, }, imgGall: { type: Object as PropType, required: true, }, }, emits: ['showandsave'], components: { CMyPage }, setup(props, { emit }) { const $q = useQuasar(); const { t } = useI18n(); const userStore = useUserStore(); const globalStore = useGlobalStore(); const displayGall = ref(false); const gallerylist = ref([]); const maximizedToggle = ref(true); const fullscreen = ref(false); const fullscreensrc = ref(''); const upl = ref(); const uploadOptions = ref({ // qui definisci le opzioni da passare quality: 'original', // esempio di opzione di qualità resize: true, // opzione per abilitare il ridimensionamento }); function isValid(myobj: any): boolean { return myobj && typeof myobj !== 'string' && typeof myobj !== 'undefined'; } const isListImgValid = computed(() => { const arr = getlistimages(); if (arr && tools.isArray(arr)) { return arr.length > 0; } else { return !!arr; } }); watch( () => props.imgGall, (newval, oldval) => { if (isValid(props.imgGall)) { // @ts-ignore gallerylist.value = props.imgGall; } } ); function created() { // console.log('created cgallery') if (isValid(props.imgGall)) { // @ts-ignore let myarr: any = props.imgGall; gallerylist.value = []; if (Array.isArray(myarr)) { myarr.forEach((pic: any) => { if (pic?.imagefile) { gallerylist.value.push(pic); } else { gallerylist.value.push(pic); } }); } } else { gallerylist.value = []; } uploadOptions.value = { quality: props.quality, resize: props.resize, }; } function getnumimages() { if (gallerylist.value) return gallerylist.value.length; else return 0; } function getlistimages() { if (gallerylist.value) // return gallerylist.value.slice().sort((a: any, b: any) => a.order! - b.order!) //return gallerylist.value.filter(filename => !filename) return gallerylist.value; else return null; } function onDragStart(e: any) { console.log('onDragStart'); e.dataTransfer.setData('text', e.target.id); e.dataTransfer.dropEffect = 'move'; } function onDragEnter(e: any) { if (props.canModify) { // don't drop on other draggables if (e.target.draggable !== true) { e.target.classList.add('drag-enter'); } } } function onDragLeave(e: any) { if (props.canModify) { e.target.classList.remove('drag-enter'); } } function onDragOver(e: any) { if (props.canModify) { e.preventDefault(); } } function onDrop(e: any) { if (props.canModify) { console.log('onDrop', e); e.preventDefault(); // don't drop on other draggables if (e.target.draggable === true) { return; } if (gallerylist.value) { const draggedId = e.dataTransfer.getData('text'); let dragout = ''; try { dragout = e.target.parentNode.parentNode.parentNode.id; } catch (err) { dragout = ''; } const draggedEl = document.getElementById(draggedId); console.log('draggedId', draggedId, 'draggedEl', draggedEl); console.log('dragout', dragout); // check if original parent node if (draggedEl) { if (draggedEl.parentNode === e.target) { e.target.classList.remove('drag-enter'); return; } } const myindexIn = gallerylist.value.findIndex( (rec: any) => rec._id === draggedId ); const myrecIn: IImgGallery = gallerylist.value[myindexIn]; let myrecOut: IImgGallery; const myindexout = gallerylist.value.findIndex( (rec: any) => rec._id === dragout ); myrecOut = gallerylist.value[myindexout]; if (myindexIn === myindexout) return; tools.array_move(gallerylist.value, myindexIn, myindexout); // make the exchange // draggedEl.parentNode.removeChild(draggedEl) // e.target.appendChild(draggedEl) e.target.classList.remove('drag-enter'); save(); } } } function getclass() { return props.edit || displayGall.value ? props.isInModif ? 'my-card-gallery' : 'my-card-gallery-noModif' : 'my-card-gallery-view' + ' text-center'; } function getclimg() { let mycl = props.edit || displayGall.value ? 'myimg' : 'myimg-view'; if (props.canModify && props.edit) mycl = mycl + ' myimg-modify'; return mycl; } /*function getlastord() { if (gallerylist.value) { let myord = 0 for (const file of gallerylist.value) { if (file.order! > myord) myord = file.order! } return myord + 10 } }*/ function uploaded(info: any) { console.log('uploaded', info); let vers_img = tools.getGenerateVersionImage(); if (gallerylist.value) { console.log('vers_img', vers_img); if (props.single && info.files) { console.log('gallerylist.value[0]', info.files[0].name); if (info.files[0].name.imagefile) { gallerylist.value[0] = info.files[0].name; } else { gallerylist.value[0] = { imagefile: info.files[0].name, vers_img, fieldtype: props.fieldtype }; } } else { for (const file of info.files) { if (file.name.imagefile) { gallerylist.value.push(file.name); } else { gallerylist.value.push({ imagefile: file.name, vers_img, fieldtype: props.fieldtype }); } } } save(); console.log('CGALLERY gallerylist', gallerylist.value); } } function apri() { displayGall.value = true; } function deleted(rec: any) { console.log('deleted', rec.imagefile); // console.table(mylistimages) if (gallerylist.value) { const index = gallerylist.value.findIndex( (elem: any) => elem.imagefile === rec.imagefile ); if (index > -1) { gallerylist.value.splice(index, 1); } gallerylist.value = gallerylist.value.filter( (elem: any) => typeof elem.imagefile === 'string' && elem.imagefile ); // mylistimages = mylistimages.pop((elem) => elem.imagefile !== rec.imagefile) // console.table(mylistimages) console.log('single', props.single); save(); } } function getfullname(rec: any) { if (rec) { return tools.getDirUpload() + props.directory + '/' + rec.imagefile; } else { return props.imagebak; } } function copytoclipboard(rec: any) { const filename = getfullname(rec); tools.copyStringToClipboard($q, filename, true); } function deleteFile(rec: any) { console.log('deleteFile....'); const filename = getfullname(rec); const filenamerel = filename.replace(/^.*[\\\/]/, ''); $q.dialog({ message: 'Eliminare il file ' + filenamerel + '?', html: true, ok: { label: 'Elimina', push: true, }, title: filenamerel, cancel: true, persistent: false, }).onOk(async () => { // Delete File on server: const ris = await globalStore.DeleteFile({ filename }); // console.log('ris', ris) //if (ris) deleted(rec); }); } function save() { console.log('CGallery save', gallerylist.value); if (gallerylist.value.length > 0) { if (!props.single) { emit('showandsave', gallerylist.value); } else { emit('showandsave', gallerylist.value[0]); } } else { emit('showandsave', !props.single ? [] : ''); } } function close() { return ''; } function getrealdirectory() { if (props.directory == 'productinfos') return 'products'; else return props.directory; } function getParamDir() { return tools.escapeslash(getrealdirectory()); } function getUrl() { const myurl = tools.geturlupload() + getParamDir(); console.log('myurl', myurl); return myurl; } function ImgFullScreen(mygallery: IImgGallery) { fullscreen.value = true; fullscreensrc.value = getfullname(mygallery); } function onRejected(rejectedEntries: any) { // Notify plugin needs to be installed // https://quasar.dev/quasar-plugins/notify#Installation console.log('rejectedEntries', rejectedEntries); $q.notify({ type: 'negative', message: "La Dimensione massima dell'immagine è di 2 MB", }); } function getFileTypeStr() { let tipo = ''; if (props.filetype === shared_consts.FILETYPE.IMG) tipo = 'Immagine'; else if (props.filetype === shared_consts.FILETYPE.PDF) tipo = 'PDF'; return tipo; } function getAccept() { let tipo = ''; if (props.filetype === shared_consts.FILETYPE.IMG) tipo = 'image/*'; else if (props.filetype === shared_consts.FILETYPE.PDF) tipo = 'application/pdf'; return tipo; } function isPDF() { return props.filetype === shared_consts.FILETYPE.PDF; } function isIMG() { return props.filetype === shared_consts.FILETYPE.IMG; } const uploadFactory = async (files: readonly File[]) => { const userStore = useUserStore(); const url = getUrl(); const buildFormData = () => { const fd = new FormData(); // "file" è il fieldName atteso dal backend (adegua se diverso) files.forEach((f) => fd.append('file', f, f.name)); // opzionale: passaggio di options come nel tuo backend fd.append('options', JSON.stringify({ quality: 'original' })); return fd; }; const sendOnce = async () => { return Api.SendReq(url, 'POST', buildFormData()); }; try { await sendOnce(); } catch (err: any) { const status = err?.response?.status; try { // usa la tua logica centralizzata Api.checkTokenScaduto( status, /*evitaloop*/ false, url, 'POST', null, /*setAuthToken*/ true ); if (ret !== null) { // token aggiornato -> ritenta UNA volta await sendOnce(); } else { throw err; } } catch (err2: any) { // se l’handler segnala re-login, mostra messaggio e rilancia const mystatus = err2?.status || err2?.code; if (mystatus === toolsext.ERR_RETRY_LOGIN) { $q.notify({ type: 'warning', message: 'Sessione scaduta. Effettua nuovamente il login.', }); } throw err2; } } }; onMounted(created); return { getlistimages, onDragStart, onDragEnter, onDragLeave, onDragOver, onDrop, getclass, getclimg, copytoclipboard, deleteFile, tools, uploaded, gallerylist, getnumimages, apri, displayGall, save, maximizedToggle, getUrl, close, ImgFullScreen, fullscreen, fullscreensrc, onRejected, isListImgValid, costanti, getrealdirectory, uploadOptions, getFileTypeStr, getAccept, shared_consts, isIMG, isPDF, upl, uploadFactory, }; }, });