- corretto gruppomacro catalogo, info prodotti, estrazione dati da amazon corretto.

This commit is contained in:
Surya Paolo
2025-09-27 17:24:40 +02:00
parent c8589e794f
commit d6c0bcf879
13 changed files with 330 additions and 252 deletions

View File

@@ -1,13 +1,11 @@
VITE_APP_ID="18" VITE_APP_ID="18"
VITE_APP_URL="https://gruppomacro.app" VITE_APP_URL="https://test.gruppomacro.app"
VITE_MONGODB_HOST="https://api.gruppomacro.app" VITE_MONGODB_HOST="https://testapi.gruppomacro.app"
VITE_LOGO_REG='gruppomacro-logo-full.png' VITE_LOGO_REG="gruppomacro-logo-full.png"
VITE_PUBLICKEY_PUSH="BJgo8XR_upbnbMLWgCAUELo6DK7dRXffYAnFOxbaMMz5favBgcQBKT-eISqouO-jRad4Sw8l5nd2wCF6KorGiTc" VITE_PUBLICKEY_PUSH="BJgo8XR_upbnbMLWgCAUELo6DK7dRXffYAnFOxbaMMz5favBgcQBKT-eISqouO-jRad4Sw8l5nd2wCF6KorGiTc"
VITE_DEBUG="0" VITE_DEBUG="1"
VITE_VUE_APP_ISTEST="0" VITE_VUE_APP_ISTEST="1"
DIRECTORY_LOCAL="myprojplanet_vite" DIRECTORY_LOCAL="myprojplanet_vite"
DIRECTORY_SERVER="/var/www/nodejs_piuchebuono_server" DIRECTORY_SERVER="/var/www/nodejs_test.piuchebuono_server"
SERVERDIR_WEBSITE="/var/www/gruppomacro.app" SERVERDIR_WEBSITE="/var/www/test.gruppomacro.app"
SERVERPW_WEBSITE="pwdadmin@1AOK" SERVERPW_WEBSITE="pwdadmin@1AOK"
PORT_SPA="8089"
PORT_PWA="8099"

View File

@@ -208,7 +208,7 @@ export default defineComponent({
function completeOrder() { function completeOrder() {
$q.dialog({ $q.dialog({
message: t('ecomm.conferma_acq', { qty: myTotalQty }), message: t('ecomm.conferma_acq', { qty: myTotalQty.value }),
ok: { ok: {
label: t('dialog.yes'), label: t('dialog.yes'),
push: true, push: true,

View File

@@ -789,7 +789,7 @@ export default defineComponent({
dataextractedWeb.value = '... caricamento in corso...'; dataextractedWeb.value = '... caricamento in corso...';
try { try {
const data = await scrapingBook(false); const data = await scrapingBook(false, false);
const html = tools.generateHtmlTableFromObject(data); const html = tools.generateHtmlTableFromObject(data);
dataextractedWeb.value = html; dataextractedWeb.value = html;
} catch (error) { } catch (error) {
@@ -885,6 +885,7 @@ export default defineComponent({
heightoggetto, heightoggetto,
mywidthogg, mywidthogg,
myheightogg, myheightogg,
scrapingBook,
}; };
}, },
}); });

View File

@@ -76,7 +76,7 @@
scheda, scheda,
true true
) ?? '100%', ) ?? '100%',
'height': tools.adjustSize( height: tools.adjustSize(
optcatalogo, optcatalogo,
scheda.dimensioni?.scheda_prodotto?.size?.height, scheda.dimensioni?.scheda_prodotto?.size?.height,
scheda, scheda,
@@ -84,13 +84,17 @@
), ),
}" }"
> >
<div <div :style="`position: relative; align-content: center;`">
:style="`position: relative; align-content: center;`"
>
<a <a
target="_blank" target="_blank"
:href="myCatalog?.disattiva_link_immagini ? null : myproduct.productInfo.link_macro" :href="
:style="myCatalog?.disattiva_link_immagini ? 'cursor: normal !important;' : ''" myCatalog?.disattiva_link_immagini
? null
: myproduct.productInfo.link_macro
"
:style="
myCatalog?.disattiva_link_immagini ? 'cursor: normal !important;' : ''
"
> >
<q-img <q-img
v-if="myproduct.productInfo" v-if="myproduct.productInfo"
@@ -143,7 +147,11 @@
: undefined, : undefined,
display: 'block', display: 'block',
}" }"
@click.stop.prevent="myCatalog?.disattiva_link_immagini ? null : tools.openUrl(myproduct.productInfo.link_macro)" @click.stop.prevent="
myCatalog?.disattiva_link_immagini
? null
: tools.openUrl(myproduct.productInfo.link_macro)
"
> >
</q-img> </q-img>
</a> </a>
@@ -158,18 +166,35 @@
z-index: 10; z-index: 10;
" "
> >
<div v-if="!optcatalogo.generazionePDFInCorso && !myCatalog?.disattiva_link_immagini"> <div
v-if="
!optcatalogo.generazionePDFInCorso &&
!myCatalog?.disattiva_link_immagini
"
>
<q-btn <q-btn
icon="fas fa-external-link-alt" icon="fas fa-external-link-alt"
color="primary" color="primary"
class="no-print" class="no-print"
rounded rounded
size="sm" size="sm"
@click.stop.prevent="tools.openUrl(myCatalog?.disattiva_link_immagini ? null : myproduct.productInfo.link_macro)" @click.stop.prevent="
tools.openUrl(
myCatalog?.disattiva_link_immagini
? null
: myproduct.productInfo.link_macro
)
"
> >
</q-btn> </q-btn>
</div> </div>
<div v-if="!optcatalogo.generazionePDFInCorso && tools.isLogged() && !myCatalog?.disattiva_link_immagini"> <div
v-if="
!optcatalogo.generazionePDFInCorso &&
tools.isLogged() &&
!myCatalog?.disattiva_link_immagini
"
>
<q-btn <q-btn
icon-right="fas fa-cart-plus" icon-right="fas fa-cart-plus"
color="positive" color="positive"
@@ -902,7 +927,8 @@
v-model="myproduct" v-model="myproduct"
titolo="Sinossi" titolo="Sinossi"
table="products" table="products"
mykey="productInfo.descr_trafiletto_catalogo" mykey="productInfo"
mysubkey="descr_trafiletto_catalogo"
:canModify="true" :canModify="true"
:type="costanti.FieldType.editor_nohtml" :type="costanti.FieldType.editor_nohtml"
@updateproductmodif="updateproductmodif" @updateproductmodif="updateproductmodif"

View File

@@ -1,11 +1,4 @@
import { import { PropType, computed, defineComponent, onMounted, ref, watch } from 'vue';
PropType,
computed,
defineComponent,
onMounted,
ref,
watch,
} from 'vue';
import draggable from 'vuedraggable'; import draggable from 'vuedraggable';
import { tools } from '@tools'; import { tools } from '@tools';
@@ -87,10 +80,14 @@ export default defineComponent({
const myproduct = ref<IProduct>({ ...props.modelValue }); const myproduct = ref<IProduct>({ ...props.modelValue });
const id = computed(() => myproduct.value.productInfo._id); const id = computed(() => myproduct.value._id);
const myvalue = computed<string>(() => { const myvalue = computed<string>(() => {
return myproduct.value.productInfo[props.mykey]; if (props.mysubkey) {
return myproduct.value[props.mykey][props.mysubkey];
} else {
return myproduct.value[props.mykey];
}
}); });
watch( watch(
@@ -105,7 +102,8 @@ export default defineComponent({
loading.value = true; loading.value = true;
try { try {
const myscrapingbookrec = await products.loadMyScrapingBook( const myscrapingbookrec = await products.loadMyScrapingBook(
myproduct.value.isbn, false myproduct.value.isbn,
false
); );
myscrapingbook.value = myscrapingbookrec; myscrapingbook.value = myscrapingbookrec;
} catch (error) { } catch (error) {
@@ -152,10 +150,7 @@ export default defineComponent({
} }
async function updateproduct(load?: boolean) { async function updateproduct(load?: boolean) {
myproduct.value = await products.getProductById( myproduct.value = await products.getProductById(myproduct.value._id, load);
myproduct.value._id,
load
);
} }
const copyToClipboard = (text) => { const copyToClipboard = (text) => {
@@ -187,8 +182,9 @@ export default defineComponent({
function getPrompt() { function getPrompt() {
// Prompt: // Prompt:
let mydescr = 'Scrivimi la sinossi del libro che ti indicherò, che andrà in un catalogo libri, la lunghezza del testo finale dev\'essere compresa tra 760 e 780 caratteri, senza spiegazione, senza titolo iniziale, solo la sinossi. Togli eventuali riferimenti a chi ha fatto la prefazione. Rendilo un po\' accattivante, ma non troppo. Senza immagine. Non inserire nessun link o riferimenti esterni o citazioni esterne. L\'output è solo la sinossi, senza altre spiegazioni. \n\n'; let mydescr =
return mydescr "Scrivimi la sinossi del libro che ti indicherò, che andrà in un catalogo libri, la lunghezza del testo finale dev'essere compresa tra 760 e 780 caratteri, senza spiegazione, senza titolo iniziale, solo la sinossi. Togli eventuali riferimenti a chi ha fatto la prefazione. Rendilo un po' accattivante, ma non troppo. Senza immagine. Non inserire nessun link o riferimenti esterni o citazioni esterne. L'output è solo la sinossi, senza altre spiegazioni. \n\n";
return mydescr;
} }
function copyDescrizioneFromScrapingData() { function copyDescrizioneFromScrapingData() {
@@ -197,9 +193,14 @@ export default defineComponent({
const data = myscrapingbook.value; const data = myscrapingbook.value;
if (!data) return false; if (!data) return false;
mydescr = getPrompt() mydescr = getPrompt();
mydescr += 'Titolo Libro: ' + data.titolo + '\n'; mydescr += 'Titolo Libro: ' + data.titolo + '\n';
mydescr += 'Autore Libro: ' + (data?.autore.trim() ? data?.autore.trim() : products.getAutoriByArrayAuthors(myproduct?.value.productInfo?.authors)) + '\n'; mydescr +=
'Autore Libro: ' +
(data?.autore.trim()
? data?.autore.trim()
: products.getAutoriByArrayAuthors(myproduct?.value.productInfo?.authors)) +
'\n';
mydescr += 'DESCRIZIONE LIBRO: \n'; mydescr += 'DESCRIZIONE LIBRO: \n';
mydescr += data.descrizione_lunga; mydescr += data.descrizione_lunga;
@@ -210,9 +211,12 @@ export default defineComponent({
function copyDescrizioneFromGruppoMacro() { function copyDescrizioneFromGruppoMacro() {
let mydescr = ''; let mydescr = '';
mydescr = getPrompt() mydescr = getPrompt();
mydescr += 'Titolo Libro: ' + myproduct?.value.productInfo?.name + '\n'; mydescr += 'Titolo Libro: ' + myproduct?.value.productInfo?.name + '\n';
mydescr += 'Autore Libro: ' + products.getAutoriByArrayAuthors(myproduct?.value.productInfo?.authors) + '\n'; mydescr +=
'Autore Libro: ' +
products.getAutoriByArrayAuthors(myproduct?.value.productInfo?.authors) +
'\n';
mydescr += 'DESCRIZIONE LIBRO: \n'; mydescr += 'DESCRIZIONE LIBRO: \n';
mydescr += myproduct?.value.productInfo?.descrizione_completa_macro; mydescr += myproduct?.value.productInfo?.descrizione_completa_macro;

View File

@@ -1,8 +1,8 @@
import { defineComponent, ref, watch, toRef, onMounted } from 'vue' import { defineComponent, ref, watch, toRef, onMounted } from 'vue';
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n';
import { useQuasar } from 'quasar' import { useQuasar } from 'quasar';
import { tools } from '@tools' import { tools } from '@tools';
import { costanti } from '@costanti' import { costanti } from '@costanti';
export default defineComponent({ export default defineComponent({
name: 'CMyChipList', name: 'CMyChipList',
@@ -36,22 +36,22 @@ export default defineComponent({
myclass: { myclass: {
type: String, type: String,
required: false, required: false,
default: '' default: '',
}, },
opticon: { opticon: {
type: String, type: String,
required: false, required: false,
default: '' default: '',
}, },
optcolor: { optcolor: {
type: String, type: String,
required: false, required: false,
default: '' default: '',
}, },
labelifblank: { labelifblank: {
type: String, type: String,
required: false, required: false,
default: '' default: '',
}, },
rec: { rec: {
type: Object, type: Object,
@@ -62,173 +62,185 @@ export default defineComponent({
type: String, type: String,
required: false, required: false,
default: '', default: '',
} },
}, },
components: {}, components: {},
setup(props, { emit }) { setup(props, { emit }) {
const { t } = useI18n() const { t } = useI18n();
const myval = toRef(props, 'value') const myval = toRef(props, 'value');
const myarrvalues = ref(<any>[]) const myarrvalues = ref(<any>[]);
watch(() => myval.value, (newval, oldval) => { watch(
refreshval() () => myval.value,
}) (newval, oldval) => {
refreshval();
}
);
function refreshval() { function refreshval() {
// console.log('refreshval') // azzero l'array di uscita
myarrvalues.value = [] myarrvalues.value = [];
// console.log('options', props.options) // --- MULTISELECT: itera sulle selezioni, non sulle options ---
if (props.options.length > 0) {
props.options.forEach((rec: any, index) => {
// console.log('rec', rec)
if (props.type === costanti.FieldType.multiselect) { if (props.type === costanti.FieldType.multiselect) {
if (!!myval.value) { if (Array.isArray(myval.value) && myval.value.length) {
myval.value.forEach((recout, idx) => {
// valore "chiave" della selezione
const value =
props.type_out === costanti.FieldType.object
? recout?.[props.optval]
: recout && typeof recout === 'object'
? recout._id
: recout;
/* if (value == null) return; // skip selezioni non valide
console.log('rec', rec)
console.log('optval', props.optval)
console.log('optlab', props.optlab)
console.log('myval.value', myval.value)
console.log('rec[props.optval]', rec[props.optval])
*/
let trovato = false // provo a trovare il record corrispondente tra le options (se presenti)
const recFromOptions = Array.isArray(props.options)
? props.options.find((o) => o && o[props.optval] === value)
: null;
if (props.type_out === costanti.FieldType.object) { const baseRec =
// @ts-ignore recFromOptions || (typeof recout === 'object' ? recout : null);
trovato = myval.value.find((recout) => recout[props.optval] === rec[props.optval])
} else {
// @ts-ignore
trovato = myval.value.includes(rec[props.optval])
}
if (trovato) { const mydata = {
const mydata: any = {
label: null, label: null,
value: rec[props.optval], value,
// myris = mylist.filter((myrec) => arrval.includes(myrec[key]))
valbool: true, valbool: true,
icon: '', icon: '',
color: tools.getColorByIndexBest(index) // priorità: optcolor -> color su record -> fallback colore
color:
(props.optcolor && baseRec?.[props.optcolor]) ||
baseRec?.color ||
tools.getColorByIndexBest(idx),
};
// icon (se disponibile)
if (props.opticon && baseRec?.[props.opticon]) {
mydata.icon = baseRec[props.opticon];
} }
if (rec['color']) { // label
mydata.color = rec['color']
}
/*
if (rec['theme']) {
mydata.class = rec['theme']
}
*/
// console.log('mydata', mydata)
if (tools.isObject(props.optlab)) { if (tools.isObject(props.optlab)) {
// @ts-ignore // se optlab è funzione/mapper, applico al record trovato in options
mydata.label = props.options.filter((myrec: any) => myrec[props.optval] === mydata.value).map(props.optlab) if (recFromOptions) {
if (mydata.label) mydata.label =
mydata.label = mydata.label[0] typeof props.optlab === 'function'
? props.optlab(recFromOptions)
: tools.getValueByFunzOrVal(recFromOptions, props.optlab);
} else { } else {
mydata.label = tools.getValueByFunzOrVal(rec, props.optlab) // fallback: provo su recout se è un oggetto
mydata.label = tools.getValueByFunzOrVal(baseRec || {}, props.optlab);
}
} else {
// optlab è chiave o funzione gestita dalla utility
mydata.label = tools.getValueByFunzOrVal(baseRec || {}, props.optlab);
} }
// console.log('mydata.label', mydata.label) myarrvalues.value.push(mydata);
});
if (props.opticon)
mydata.icon = rec[props.opticon]
if (props.optcolor)
mydata.color = rec[props.optcolor]
myarrvalues.value.push(mydata)
}
} }
// se multiselect non ha prodotto nulla, gestisco eventuale fallback sotto
} else if (props.type === costanti.FieldType.select) { } else if (props.type === costanti.FieldType.select) {
if (myval.value === rec[props.optval]) { // --- SELECT: itera sulle options e trova la corrispondenza ---
const mydata: any = { if (Array.isArray(props.options) && props.options.length) {
props.options.forEach((rec, index) => {
if (myval.value === rec?.[props.optval]) {
const mydata = {
value: myval.value, value: myval.value,
valbool: true, valbool: true,
icon: '', icon: '',
color: tools.getColorByIndexBest(index) color:
} (props.optcolor && rec?.[props.optcolor]) ||
rec?.color ||
tools.getColorByIndexBest(index),
label: null,
};
// console.log('mydata', mydata, 'optlab', optlab, 'myval.value', myval.value) if (props.opticon && rec?.[props.opticon]) mydata.icon = rec[props.opticon];
if (tools.isObject(props.optlab)) { if (tools.isObject(props.optlab)) {
// @ts-ignore // cerco l'option corrispondente e la mappo
mydata.label = props.options.filter((myrec: any) => myrec[props.optval] === mydata.value).map(props.optlab) const opt = props.options.find(
if (mydata.label) (o) => o && o[props.optval] === mydata.value
mydata.label = mydata.label[0] );
mydata.label = opt
? typeof props.optlab === 'function'
? props.optlab(opt)
: tools.getValueByFunzOrVal(opt, props.optlab)
: null;
} else { } else {
mydata.label = tools.getValueByFunzOrVal(rec, props.optlab) mydata.label = tools.getValueByFunzOrVal(rec, props.optlab);
} }
if (props.opticon) myarrvalues.value.push(mydata);
mydata.icon = rec[props.opticon] }
if (props.optcolor) });
mydata.color = rec[props.optcolor]
myarrvalues.value.push(mydata)
} }
} else { } else {
if (tools.isBitActive(myval.value, rec[props.optval])) { // --- BITMASK (o altro tipo legacy): itera sulle options e verifica i bit attivi ---
// console.log('rec', rec, 'props.optlab', props.optlab) if (Array.isArray(props.options) && props.options.length) {
props.options.forEach((rec, index) => {
const optVal = rec?.[props.optval];
if (optVal == null) return;
if (tools.isBitActive(myval.value, optVal)) {
const mydata = { const mydata = {
label: t(tools.getValueByFunzOrVal(rec, props.optlab)), label: t(tools.getValueByFunzOrVal(rec, props.optlab)),
value: rec[props.optval], value: optVal,
valbool: tools.isBitActive(myval.value, rec[props.optval]), valbool: true,
icon: '', icon: '',
color: tools.getColorByIndexBest(index) color:
(props.optcolor && rec?.[props.optcolor]) ||
rec?.color ||
tools.getColorByIndexBest(index),
};
if (props.opticon && rec?.[props.opticon]) mydata.icon = rec[props.opticon];
myarrvalues.value.push(mydata);
} }
});
if (props.opticon)
mydata.icon = rec[props.opticon]
if (props.optcolor)
mydata.color = rec[props.optcolor]
myarrvalues.value.push(mydata)
} }
} }
})
} else {
if (props.type === costanti.FieldType.select_by_server) {
const mydata: any = { // --- FALLBACK quando non ci sono options ma select_by_server ---
// @ts-ignore if (
label: props.rec[props.optlab], (!Array.isArray(props.options) || props.options.length === 0) &&
props.type === costanti.FieldType.select_by_server
) {
const mydata = {
label: props.rec?.[props.optlab],
value: 0, value: 0,
valbool: true, valbool: true,
icon: '', icon: '',
color: tools.getColorByIndexBest(0) color: tools.getColorByIndexBest(0),
} };
if (!mydata.label && props.labelifblank) { if (!mydata.label && props.labelifblank) {
mydata.label = props.labelifblank mydata.label = props.labelifblank;
mydata.color = 'grey' mydata.color = 'grey';
} }
myarrvalues.value.push(mydata) myarrvalues.value.push(mydata);
}
} }
if (myarrvalues.value.length === 0) // --- Nessuna selezione: placeholder "nessuno" ---
myarrvalues.value.push({ label: t('otherpages.manage.nessuno'), color: 'gray' }) if (!Array.isArray(myarrvalues.value) || myarrvalues.value.length === 0) {
myarrvalues.value = [{ label: t('otherpages.manage.nessuno'), color: 'gray' }];
// console.log('arrvalues=', myarrvalues) }
} }
function mounted() { function mounted() {
refreshval() refreshval();
} }
onMounted(mounted) onMounted(mounted);
return { return {
myarrvalues, myarrvalues,
} };
} },
}) });

View File

@@ -1068,6 +1068,7 @@
</div> </div>
<!-- Show Value --> <!-- Show Value -->
<div v-else-if="col.fieldtype === costanti.FieldType.multiselect"> <div v-else-if="col.fieldtype === costanti.FieldType.multiselect">
<div v-if="isInModif"> <div v-if="isInModif">
<CMySelect <CMySelect
:type_out="col.field_outtype" :type_out="col.field_outtype"

View File

@@ -462,19 +462,6 @@
</div> </div>
{{ myproduct.productInfo.imagefile }} {{ myproduct.productInfo.imagefile }}
</div> </div>
<!--<CMyFieldRec
title="Immagine:"
table="myelems"
:id="myproduct.productInfo._id"
:rec="myproduct.productInfo"
field="imagefile"
@update:model-value="modifElem"
:canEdit="true"
:canModify="true"
:fieldtype="costanti.FieldType.imagerec"
>
</CMyFieldRec>-->
</q-card-section> </q-card-section>
<q-card-section v-if="isOrdGas()"> <q-card-section v-if="isOrdGas()">
<q-item <q-item

View File

@@ -389,7 +389,8 @@
v-model="selProd" v-model="selProd"
titolo="Sinossi" titolo="Sinossi"
table="products" table="products"
mykey="productInfo.descr_trafiletto_catalogo" mykey="productInfo"
mysubkey="descr_trafiletto_catalogo"
:canModify="true" :canModify="true"
:type="costanti.FieldType.editor_nohtml" :type="costanti.FieldType.editor_nohtml"
@updateproductmodif="updateproductmodif" @updateproductmodif="updateproductmodif"

View File

@@ -83,8 +83,9 @@ export default defineComponent({
label: 'Fatturati', label: 'Fatturati',
table: 'products', table: 'products',
id: myproduct.value._id, // ID dinamico, da sostituire con il valore reale id: myproduct.value._id, // ID dinamico, da sostituire con il valore reale
rec: myproduct.value.productInfo, // Oggetto dinamico, da sostituire con il valore reale rec: myproduct.value,
mykey: 'totFat', mykey: 'productInfo',
mysubkey: 'totFat',
debounce: '1000', debounce: '1000',
type: costanti.FieldType.number, type: costanti.FieldType.number,
}, },
@@ -93,8 +94,9 @@ export default defineComponent({
label: 'Fatturati ultimi 3 Mesi', label: 'Fatturati ultimi 3 Mesi',
table: 'products', table: 'products',
id: myproduct.value._id, id: myproduct.value._id,
rec: myproduct.value.productInfo, rec: myproduct.value,
mykey: 'fatLast3M', mykey: 'productInfo',
mysubkey: 'fatLast3M',
debounce: '1000', debounce: '1000',
type: costanti.FieldType.number, type: costanti.FieldType.number,
}, },
@@ -103,8 +105,9 @@ export default defineComponent({
label: 'Fatturati ultimi 6 Mesi', label: 'Fatturati ultimi 6 Mesi',
table: 'products', table: 'products',
id: myproduct.value._id, id: myproduct.value._id,
rec: myproduct.value.productInfo, rec: myproduct.value,
mykey: 'fatLast6M', mykey: 'productInfo',
mysubkey: 'fatLast6M',
debounce: '1000', debounce: '1000',
type: costanti.FieldType.number, type: costanti.FieldType.number,
}, },
@@ -113,8 +116,9 @@ export default defineComponent({
label: 'Fatturati ultimo Anno', label: 'Fatturati ultimo Anno',
table: 'products', table: 'products',
id: myproduct.value._id, id: myproduct.value._id,
rec: myproduct.value.productInfo, rec: myproduct.value,
mykey: 'fatLast1Y', mykey: 'productInfo',
mysubkey: 'fatLast1Y',
debounce: '1000', debounce: '1000',
type: costanti.FieldType.number, type: costanti.FieldType.number,
}, },
@@ -123,8 +127,9 @@ export default defineComponent({
label: 'Fatturati ultimi 2 Anni', label: 'Fatturati ultimi 2 Anni',
table: 'products', table: 'products',
id: myproduct.value._id, id: myproduct.value._id,
rec: myproduct.value.productInfo, rec: myproduct.value,
mykey: 'fatLast2Y', mykey: 'productInfo',
mysubkey: 'fatLast2Y',
debounce: '1000', debounce: '1000',
type: costanti.FieldType.number, type: costanti.FieldType.number,
}, },
@@ -133,8 +138,9 @@ export default defineComponent({
label: 'Venduti', label: 'Venduti',
table: 'products', table: 'products',
id: myproduct.value._id, // ID dinamico, da sostituire con il valore reale id: myproduct.value._id, // ID dinamico, da sostituire con il valore reale
rec: myproduct.value.productInfo, // Oggetto dinamico, da sostituire con il valore reale rec: myproduct.value,
mykey: 'totVen', mykey: 'productInfo',
mysubkey: 'totVen',
debounce: '1000', debounce: '1000',
type: costanti.FieldType.number, type: costanti.FieldType.number,
}, },
@@ -143,8 +149,9 @@ export default defineComponent({
label: 'Venduti Ultimi 3 Mesi', label: 'Venduti Ultimi 3 Mesi',
table: 'products', table: 'products',
id: myproduct.value._id, id: myproduct.value._id,
rec: myproduct.value.productInfo, rec: myproduct.value,
mykey: 'vLast3M', mykey: 'productInfo',
mysubkey: 'vLast3M',
debounce: '1000', debounce: '1000',
type: costanti.FieldType.number, type: costanti.FieldType.number,
}, },
@@ -153,8 +160,9 @@ export default defineComponent({
label: 'Venduti Ultimi 6 Mesi', label: 'Venduti Ultimi 6 Mesi',
table: 'products', table: 'products',
id: myproduct.value._id, id: myproduct.value._id,
rec: myproduct.value.productInfo, rec: myproduct.value,
mykey: 'vLast6M', mykey: 'productInfo',
mysubkey: 'vLast6M',
debounce: '1000', debounce: '1000',
type: costanti.FieldType.number, type: costanti.FieldType.number,
}, },
@@ -163,8 +171,9 @@ export default defineComponent({
label: 'Venduti Ultimo Anno', label: 'Venduti Ultimo Anno',
table: 'products', table: 'products',
id: myproduct.value._id, id: myproduct.value._id,
rec: myproduct.value.productInfo, rec: myproduct.value,
mykey: 'vLast1Y', mykey: 'productInfo',
mysubkey: 'vLast1Y',
debounce: '1000', debounce: '1000',
type: costanti.FieldType.number, type: costanti.FieldType.number,
}, },
@@ -173,8 +182,9 @@ export default defineComponent({
label: 'Venduti Ultimi 2 Anni', label: 'Venduti Ultimi 2 Anni',
table: 'products', table: 'products',
id: myproduct.value._id, id: myproduct.value._id,
rec: myproduct.value.productInfo, rec: myproduct.value,
mykey: 'vLast2Y', mykey: 'productInfo',
mysubkey: 'vLast2Y',
debounce: '1000', debounce: '1000',
type: costanti.FieldType.number, type: costanti.FieldType.number,
}, },
@@ -216,8 +226,9 @@ export default defineComponent({
title: myproduct.value?.productInfo?.name, title: myproduct.value?.productInfo?.name,
table: 'products', table: 'products',
id: myproduct.value._id, // ID dinamico, da sostituire con il valore reale id: myproduct.value._id, // ID dinamico, da sostituire con il valore reale
rec: myproduct.value.productInfo, // Oggetto dinamico, da sostituire con il valore reale rec: myproduct.value,
mykey: 'descrizione_breve_macro', mykey: 'productInfo',
mysubkey: 'descrizione_breve_macro',
maxlength: 650, maxlength: 650,
debounce: '1000', debounce: '1000',
type: costanti.FieldType.editor_nohtml, type: costanti.FieldType.editor_nohtml,
@@ -229,8 +240,9 @@ export default defineComponent({
label: 'Descrizione Estesa', label: 'Descrizione Estesa',
table: 'products', table: 'products',
id: myproduct.value._id, // ID dinamico, da sostituire con il valore reale id: myproduct.value._id, // ID dinamico, da sostituire con il valore reale
rec: myproduct.value.productInfo, // Oggetto dinamico, da sostituire con il valore reale rec: myproduct.value,
mykey: 'descrizione_completa_macro', mykey: 'productInfo',
mysubkey: 'descrizione_completa_macro',
maxlength: props.scheda?.testo_bottom?.maxlength maxlength: props.scheda?.testo_bottom?.maxlength
? props.scheda?.testo_bottom?.maxlength ? props.scheda?.testo_bottom?.maxlength
: 10000, : 10000,
@@ -244,8 +256,9 @@ export default defineComponent({
label: 'Link a gruppomacro.com', label: 'Link a gruppomacro.com',
table: 'products', table: 'products',
id: myproduct.value._id, // ID dinamico, da sostituire con il valore reale id: myproduct.value._id, // ID dinamico, da sostituire con il valore reale
rec: myproduct.value.productInfo, // Oggetto dinamico, da sostituire con il valore reale rec: myproduct.value,
mykey: 'link_macro', mykey: 'productInfo',
mysubkey: 'link_macro',
debounce: '1000', debounce: '1000',
type: costanti.FieldType.string, type: costanti.FieldType.string,
dense: true, dense: true,
@@ -256,8 +269,9 @@ export default defineComponent({
label: 'Imagefile', label: 'Imagefile',
table: 'products', table: 'products',
id: myproduct.value._id, // ID dinamico, da sostituire con il valore reale id: myproduct.value._id, // ID dinamico, da sostituire con il valore reale
rec: myproduct.value.productInfo, // Oggetto dinamico, da sostituire con il valore reale rec: myproduct.value,
mykey: 'imagefile', mykey: 'productInfo',
mysubkey: 'imagefile',
debounce: '1000', debounce: '1000',
type: costanti.FieldType.string, type: costanti.FieldType.string,
dense: true, dense: true,
@@ -275,8 +289,9 @@ export default defineComponent({
label: 'Titolo', label: 'Titolo',
table: 'products', table: 'products',
id: myproduct.value._id, id: myproduct.value._id,
rec: myproduct.value.productInfo, // Oggetto dinamico, da sostituire con il valore reale rec: myproduct.value,
mykey: 'name', mykey: 'productInfo',
mysubkey: 'name',
debounce: '1000', debounce: '1000',
type: costanti.FieldType.string, type: costanti.FieldType.string,
dense: true, dense: true,
@@ -297,8 +312,9 @@ export default defineComponent({
label: 'SottoTitolo', label: 'SottoTitolo',
table: 'products', table: 'products',
id: myproduct.value._id, id: myproduct.value._id,
rec: myproduct.value.productInfo, rec: myproduct.value,
mykey: 'sottotitolo', mykey: 'productInfo',
mysubkey: 'sottotitolo',
debounce: '1000', debounce: '1000',
type: costanti.FieldType.string, type: costanti.FieldType.string,
dense: true, dense: true,
@@ -308,8 +324,9 @@ export default defineComponent({
label: 'Pubblicazione', label: 'Pubblicazione',
table: 'products', table: 'products',
id: myproduct.value._id, id: myproduct.value._id,
rec: myproduct.value.productInfo, rec: myproduct.value,
mykey: 'date_pub', mykey: 'productInfo',
mysubkey: 'date_pub',
debounce: '1000', debounce: '1000',
type: costanti.FieldType.onlydate, type: costanti.FieldType.onlydate,
dense: true, dense: true,
@@ -330,8 +347,9 @@ export default defineComponent({
label: 'Stato', label: 'Stato',
table: 'products', table: 'products',
id: myproduct.value._id, id: myproduct.value._id,
rec: myproduct.value.productInfo, rec: myproduct.value,
mykey: 'idStatoProdotto', mykey: 'productInfo',
mysubkey: 'idStatoProdotto',
debounce: '1000', debounce: '1000',
type: costanti.FieldType.select, type: costanti.FieldType.select,
jointable: 't_web_statiprodottos', jointable: 't_web_statiprodottos',
@@ -341,9 +359,10 @@ export default defineComponent({
editOn: true, editOn: true,
label: 'Argomento', label: 'Argomento',
table: 'products', table: 'products',
id: myproduct.value.productInfo?._id, id: myproduct.value._id,
rec: myproduct.value.productInfo, rec: myproduct.value,
mykey: 'idCatProds', mykey: 'productInfo',
mysubkey: 'idCatProds',
debounce: '1000', debounce: '1000',
type: costanti.FieldType.multiselect, type: costanti.FieldType.multiselect,
jointable: 'catprods', jointable: 'catprods',
@@ -448,8 +467,9 @@ export default defineComponent({
label: 'Aggiornato (da GM) il', label: 'Aggiornato (da GM) il',
table: 'products', table: 'products',
id: myproduct.value._id, id: myproduct.value._id,
rec: myproduct.value.productInfo, rec: myproduct.value,
mykey: 'date_updated_fromGM', mykey: 'productInfo',
mysubkey: 'date_updated_fromGM',
debounce: '1000', debounce: '1000',
type: costanti.FieldType.onlydate, type: costanti.FieldType.onlydate,
dense: true, dense: true,

View File

@@ -19,8 +19,11 @@ import MixinBase from '../../mixins/mixin-base'
export default defineComponent({ export default defineComponent({
name: 'LandingFooter', name: 'LandingFooter',
components: { Logo, FormNewsletter, CFacebookFrame }, components: { Logo, FormNewsletter, CFacebookFrame },
props: {
setup() { mykey: { type: String, required: false },
mysubkey: { type: String, required: false }
},
setup(props: { mykey?: string; mysubkey?: string }) {
const $q = useQuasar() const $q = useQuasar()
const { t } = useI18n() const { t } = useI18n()
const globalStore = useGlobalStore() const globalStore = useGlobalStore()
@@ -39,7 +42,37 @@ export default defineComponent({
return 'linear-gradient(180deg, ' + mycol + ' 95%, #FFF)' return 'linear-gradient(180deg, ' + mycol + ' 95%, #FFF)'
}) })
// console.log('LandingFooter - INIT') // New: Access nested product data via optional props
const productSource = computed(() => {
// Try to read a globally exposed product store value if present
try {
const gp: any = (globalStore as any).myproduct
if (gp && gp.value !== undefined) return gp.value
} catch {
// ignore
}
// Fallback: try to read from site.productInfo if available
try {
const s: any = site.value
if (s && s.productInfo) return s.productInfo
} catch {
// ignore
}
// Final fallback
return {}
})
const nestedProductValue = computed(() => {
const key = props.mykey
if (!key) return undefined
const base = (productSource.value as any)?.[key]
if (props.mysubkey && base && typeof base === 'object') {
return base[props.mysubkey]
}
return base
})
function TelegramSupport() { function TelegramSupport() {
return globalStore.getValueSettingsByKey('TELEGRAM_SUPPORT', false) return globalStore.getValueSettingsByKey('TELEGRAM_SUPPORT', false)
@@ -90,6 +123,7 @@ export default defineComponent({
site, site,
getBackColorText, getBackColorText,
t, t,
nestedProductValue,
} }
}, },
}) })

View File

@@ -256,13 +256,6 @@ export default function () {
if (idprod >= 0 && key) { if (idprod >= 0 && key) {
productStore.products[idprod][key as keyof IProduct] = value; productStore.products[idprod][key as keyof IProduct] = value;
} }
/*} else if (table === 'productinfos') {
const productStore = useProducts()
const idprod = productStore.products.findIndex((rec: IProduct) => rec.productInfo._id === id)
if (idprod >= 0 && key) {
const myfield = key as keyof IProductInfo
productStore.products[idprod].productInfo[myfield] = value
}*/
} else if (table === 'arrvariazioni') { } else if (table === 'arrvariazioni') {
const productStore = useProducts(); const productStore = useProducts();
const idprod = productStore.products.findIndex((rec: IProduct) => rec._id === id); const idprod = productStore.products.findIndex((rec: IProduct) => rec._id === id);

View File

@@ -14,12 +14,13 @@
v-model="checkAggiornaQta" v-model="checkAggiornaQta"
label="Aggiorna Quantità in Magazzino" label="Aggiorna Quantità in Magazzino"
></q-toggle> ></q-toggle>
<label class="text-reader"> <br>&nbsp;</br>
<div class="text-reader q-ma-md q-pa-md text-center">
<input <input
type="file" type="file"
@change="loadTextFromFile" @change="loadTextFromFile"
/> />
</label> </div>
<br /> <br />
<br /> <br />