522 lines
13 KiB
TypeScript
Executable File
522 lines
13 KiB
TypeScript
Executable File
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<IImgGallery[] | string | undefined | null>,
|
||
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(<IImgGallery[]>[]);
|
||
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,
|
||
};
|
||
},
|
||
});
|