- Ricerca Titolo per nome o autore o ISBN o codice articolo

This commit is contained in:
Surya Paolo
2025-03-31 23:55:53 +02:00
parent 7624f16723
commit 61c1dc3d0d
67 changed files with 760 additions and 1618 deletions

View File

@@ -103,7 +103,7 @@
@click="click_opendetail()"
/>
</a>
<div class="q-ma-md ">
<div class="q-ma-sm">
<div class="row absolute-top-left semi-transparent" style="z-index: 10;">
<q-btn-dropdown
push
@@ -243,7 +243,7 @@
<div
v-if="scheda.testo_right_attaccato.font?.posiz_text !== costanti.POSIZ_TESTO.IN_BASSO"
:style="{
alignSelf: scheda.testo_right_attaccato.font?.posiz_text === costanti.POSIZ_TESTO.IN_BASSO ? '' : 'end',
alignSelf: scheda.testo_right_attaccato.font?.posiz_text === costanti.POSIZ_TESTO.IN_BASSO ? '' : 'center',
marginTop:
scheda.testo_right_attaccato.font?.posiz_text === costanti.POSIZ_TESTO.IN_BASSO ? 'auto' : '0',
}"

View File

@@ -280,6 +280,9 @@ export default defineComponent({
if (!recscheda.scheda?.dimensioni?.pagina?.testo_up) {
recscheda.scheda!.dimensioni.pagina.testo_up = tools.resetIText(null)
}
if (!recscheda.scheda?.dimensioni?.pagina?.testo_title) {
recscheda.scheda!.dimensioni.pagina.testo_title = tools.resetIText(null)
}
if (!recscheda.scheda?.dimensioni?.pagina?.testo_down) {
recscheda.scheda!.dimensioni.pagina.testo_down = tools.resetIText(null)
}
@@ -435,7 +438,7 @@ export default defineComponent({
}
const dimensioni: IElementiScheda = {
pagina: { dimensioni: defaultDimensioniPag, testo_down: testodef, testo_up: testodef },
pagina: { dimensioni: defaultDimensioniPag, testo_down: testodef, testo_up: testodef, testo_title: testodef },
riga: defaultDimensioniRiga,
scheda_prodotto: defaultSchedaProdotto,
immagine_prodotto: {

View File

@@ -1989,6 +1989,14 @@
:show_imgsfondo="true"
@update:model-value="modifElem"
></CMyDimensioni>
<CMyText
v-model="recscheda.scheda.dimensioni.pagina.testo_title"
@modifElem="modifElem"
@saveFieldElem="saveFieldElem"
@update:model-value="modifElem"
label="Titolo in Alto"
>
</CMyText>
<CMyText
v-model="recscheda.scheda.dimensioni.pagina.testo_up"
@modifElem="modifElem"

View File

@@ -761,6 +761,31 @@ export default defineComponent({
// Seleziona tutto il testo all'interno della casella di testo
event.target.select();
}
function getLabelValue(opt: any): string {
const collabel = props.optlab
if (typeof collabel === 'function') {
// Se collabel è una funzione, chiamala con opt
return collabel(opt)
} else if (typeof collabel === 'string') {
// Se collabel è una stringa, usa il valore della proprietà corrispondente
return opt[collabel] || 'N/A'
}
// Fallback generico
return 'N/A';
}
function getOptionLabel(option: any): string {
console.log('getOptionLabel', option)
if (typeof props.optlab === 'function') {
return props.optlab(option); // Se optlab è una funzione, chiamala
} else {
return option[props.optlab]; // Se optlab è una stringa, usa la proprietà corrispondente
}
}
onMounted(mounted)
@@ -777,6 +802,8 @@ export default defineComponent({
getIcon,
tools,
selectText,
getLabelValue,
getOptionLabel,
}
}
})

View File

@@ -93,8 +93,7 @@
:input-class="myclass"
:options="valori"
:option-value="optval"
:option-label="optlab"
map-options
:option-label="getOptionLabel"
:use-chips="myvalue && myvalue !== '' ? true : false"
stack-label
:behavior="$q.platform.is.ios === true ? 'dialog' : 'menu'"
@@ -125,7 +124,8 @@
<q-item v-bind="scope.itemProps">
<q-item-section>
<q-item-label>
{{ tools.getValueByFunzOrVal(scope.opt, optlab) }}</q-item-label
{{ tools.getValueByFunzOrVal(scope.opt, optlab) }}
</q-item-label
>
</q-item-section>
</q-item>

View File

@@ -13,6 +13,9 @@ export default defineComponent({
type: [String, Number],
required: false,
default: '0',
validator: (value) => {
return true;
},
},
label: {
type: String,

View File

@@ -74,6 +74,15 @@ export default defineComponent({
}, { immediate: true });
function mounted() {
if (!internalModel.font) {
internalModel.font = {
line_height: 1,
posiz_text: 0,
perc_text: '',
name: '',
size: '14px',
}
}
if (!internalModel.font?.perc_text) {
internalModel.font!.perc_text = ''
}

View File

@@ -12,77 +12,82 @@
@update_col="update_col"
>
</CMyFieldRec>
<q-select
v-model="internalModel.font.posiz_text"
:options="tools.posizTextOptions"
label="Posizione"
options-dense
dense
emit-value
map-options
style="width: 100px"
@update:model-value="modifElem"
fill-input
text-color="white"
>
</q-select>
<CMySlider
label="Margine % tra l'immagine"
v-model="internalModel.font.perc_text"
:min="0"
:max="100"
color="blue"
addstr="%"
@update:model-value="modifElem"
></CMySlider>
<CMySlider
label="Line Height:"
v-model="internalModel.font.line_height"
:min="0.5"
:max="2"
color="blue"
@update:model-value="modifElem"
></CMySlider>
<CMySlider
v-if="show_maxlength"
label="Max numero di caratteri:"
v-model="internalModel.maxlength"
:min="0"
:max="1000"
color="blue"
addstr=""
@update:model-value="modifElem"
></CMySlider>
<CMySize
v-if="show_dimensioni"
label="Dimensioni:"
v-model="internalModel.size"
@update:model-value="modifElem"
></CMySize>
<div v-if="internalModel">
<q-select
v-if="internalModel.font"
v-model="internalModel.font.posiz_text"
:options="tools.posizTextOptions"
label="Posizione"
options-dense
dense
emit-value
map-options
style="width: 100px"
@update:model-value="modifElem"
fill-input
text-color="white"
>
</q-select>
<CMySlider
v-if="internalModel.font"
label="Margine % tra l'immagine"
v-model="internalModel.font.perc_text"
:min="0"
:max="100"
color="blue"
addstr="%"
@update:model-value="modifElem"
></CMySlider>
<CMySlider
v-if="internalModel.font"
label="Line Height:"
v-model="internalModel.font.line_height"
:min="0.5"
:max="2"
color="blue"
@update:model-value="modifElem"
></CMySlider>
<CMySlider
v-if="show_maxlength"
label="Max numero di caratteri:"
v-model="internalModel.maxlength"
:min="0"
:max="1000"
color="blue"
addstr=""
@update:model-value="modifElem"
></CMySlider>
<CMySize
v-if="show_dimensioni"
label="Dimensioni:"
v-model="internalModel.size"
@update:model-value="modifElem"
></CMySize>
<div>
Parole Chiave: {autore} {titolo} {descrizione} {date_pub} {ranking}
{sottotitolo} {prezzo} {prezzo_scontato} {descrizione_estesa}
<div>
Parole Chiave: {autore} {titolo} {descrizione} {date_pub} {ranking} {sottotitolo} {prezzo} {prezzo_scontato}
{descrizione_estesa}
</div>
<q-select
v-if="internalModel.font"
v-model="internalModel.font.size"
:options="tools.fontSizeOptions"
label="Size Titolo"
options-dense
dense
emit-value
map-options
style="width: 120px"
@update:model-value="modifElem"
fill-input
text-color="white"
>
</q-select>
</div>
<q-select
v-model="internalModel.font.size"
:options="tools.fontSizeOptions"
label="Size Titolo"
options-dense
dense
emit-value
map-options
style="width: 120px"
@update:model-value="modifElem"
fill-input
text-color="white"
>
</q-select>
</template>
<script lang="ts" src="./CMyText.ts">
</script>
<script lang="ts" src="./CMyText.ts"></script>
<style lang="scss" scoped>
@import './CMyText.scss';

View File

@@ -0,0 +1,7 @@
.drag-handle {
cursor: grab; /* Mostra la manina */
}
.drag-handle:active {
cursor: grabbing; /* Cambia la manina quando l'utente sta trascinando */
}

View File

@@ -0,0 +1,131 @@
import { defineComponent, onMounted, ref, watch } from "vue";
import draggable from 'vuedraggable'
import { tools } from '@tools'
import { useGlobalStore } from '@src/store/globalStore'
import { costanti } from '@costanti'
import { IAuthor, ICatProd } from "app/src/model";
export default defineComponent({
name: "CProductTable",
components: {
draggable,
},
props: {
lista_prodotti: {
type: Array,
required: true,
},
},
emits: ["update:lista_prodotti"],
setup(props, { emit }) {
// Copia locale della lista_prodotti per manipolazione interna
const internalProducts = ref([...props.lista_prodotti]);
const globalStore = useGlobalStore()
async function mounted() {
}
// Aggiorna la copia locale quando il prop cambia
watch(
() => props.lista_prodotti,
(newVal) => {
internalProducts.value = [...newVal];
}
);
// Colonne della tabella
const allColumns = [
{ name: "drag", label: "", field: "", align: "left", style: "width: 50px" },
{ name: "image", label: "Immagine", field: "image", align: "center" },
{ name: "title", label: "Titolo", field: "title", align: "left" },
{ name: "author", label: "Autore", field: "author", align: "left" },
{ name: "topic", label: "Argomento", field: "topic", align: "left" },
{ name: "isbn", label: "ISBN", field: "isbn", align: "left" },
{ name: "actions", label: "Azioni", field: "", align: "center" },
];
const selectedColumns = ref(
tools.getCookie("selColCat")
? JSON.parse(tools.getCookie("selColCat"))
: ["drag", "image", "name", "authors", "catprods", "isbn", "actions"] // Valori di default
)
// 3. Funzione per verificare se una colonna è visibile (isColumnVisible)
const isColumnVisible = (column) => {
return selectedColumns.value.includes(column);
}
// Funzione per eliminare un prodotto
const removeProduct = (product) => {
internalProducts.value = internalProducts.value.filter((p: any) => p._id !== product._id);
emit("update:lista_prodotti", internalProducts.value); // Notifica il parent del cambiamento
}
// 8. Salvataggio delle colonne selezionate in un cookie
const saveSelectedColumns = () => {
tools.setCookie("selColCat", JSON.stringify(selectedColumns.value));
};
// 9. Watcher per salvare automaticamente le preferenze quando cambiano
watch(() => selectedColumns.value, () => {
saveSelectedColumns();
});
// Funzione chiamata alla fine del drag-and-drop
const onDragEnd = () => {
// console.log("Nuovo ordine:", internalProducts.value);
emit("update:lista_prodotti", internalProducts.value); // Notifica il parent del cambiamento
}
function formatAuthors(authors: IAuthor[] | undefined | null): string {
if (!authors || !Array.isArray(authors)) {
return ""; // Restituisci una stringa vuota se authors non è un array valido
}
// Estrai il nome e il cognome di ogni autore e uniscili con ', '
return authors
.map((author) => `${author.name ?? ""} ${author.surname ?? ""}`.trim())
.filter((name) => name.length > 0) // Filtra eventuali nomi vuoti
.join(", ");
}
function formatCatProds(catprods: ICatProd[] | undefined | null): string {
if (!catprods || !Array.isArray(catprods)) {
return "";
}
// Estrai il nome e il cognome di ogni autore e uniscili con ', '
return catprods
.map((catprod) => `${catprod.name ?? ""}`.trim())
.filter((name) => name.length > 0) // Filtra eventuali nomi vuoti
.join(", ");
}
// Caricamento delle preferenze al mount del componente
onMounted(() => {
const savedColumns = tools.getCookie("selColCat");
if (savedColumns) {
selectedColumns.value = JSON.parse(savedColumns);
}
});
return {
allColumns,
selectedColumns,
isColumnVisible,
internalProducts,
formatAuthors,
formatCatProds,
removeProduct,
tools,
globalStore,
costanti,
onDragEnd,
}
},
})

View File

@@ -0,0 +1,94 @@
<template>
<div>
<!-- Selezione Colonne -->
<div class="q-mb-md">
<q-select
v-model="selectedColumns"
:options="allColumns"
label="Colonne da visualizzare"
multiple
emit-value
map-options
filled
style="max-width: 400px"
/>
</div>
<!-- Tabella Prodotti -->
<table>
<!-- Intestazioni (Thead) -->
<thead>
<tr>
<th v-if="isColumnVisible('drag')">Drag</th>
<th v-if="isColumnVisible('image')">Immagine</th>
<th v-if="isColumnVisible('name')">Nome</th>
<th v-if="isColumnVisible('authors')">Autore</th>
<th v-if="isColumnVisible('catprods')">Argomento</th>
<th v-if="isColumnVisible('isbn')">ISBN</th>
<th v-if="isColumnVisible('actions')">Azioni</th>
</tr>
</thead>
<!-- Corpo della Tabella (Tbody) -->
<draggable
v-model="internalProducts"
tag="tbody"
handle=".drag-handle"
item-key="_id"
@end="onDragEnd"
>
<template #item="{ element }">
<tr :key="element._id">
<!-- Icona Drag Handle -->
<td v-if="isColumnVisible('drag')" class="drag-handle">
<q-icon name="drag_handle" size="32px" color="primary" />
</td>
<!-- Immagine Piccola -->
<td v-if="isColumnVisible('image')">
<q-img
:src="
element.productInfo?.imagefile
? tools.getFullFileNameByImageFile('productInfos', element.productInfo?.imagefile)
: element.productInfo?.image_link
"
style="width: 50px; height: 50px"
class="rounded-borders"
/>
</td>
<!-- Titolo -->
<td v-if="isColumnVisible('name')">{{ element.productInfo?.name }}</td>
<!-- Autore -->
<td v-if="isColumnVisible('authors')">{{ formatAuthors(element.productInfo?.authors) }}</td>
<!-- Argomento -->
<td v-if="isColumnVisible('catprods')">{{ formatCatProds(element.productInfo?.catprods) }}</td>
<!-- ISBN -->
<td v-if="isColumnVisible('isbn')">{{ element.isbn }}</td>
<!-- Azioni -->
<td v-if="isColumnVisible('actions')">
<q-btn-dropdown label="Azioni" color="primary" flat>
<q-list>
<q-item clickable v-close-popup @click="removeProduct(element)">
<q-item-section>
<q-item-label>Elimina</q-item-label>
</q-item-section>
</q-item>
</q-list>
</q-btn-dropdown>
</td>
</tr>
</template>
</draggable>
</table>
</div>
</template>
<script lang="ts" src="./CProductTable.ts"></script>
<style lang="scss" scoped>
@import './CProductTable.scss';
</style>

View File

@@ -0,0 +1 @@
export { default as CProductTable } from './CProductTable.vue'

View File

@@ -54,7 +54,7 @@ export default defineComponent({
const idPage = ref('')
const selauthor = ref('')
const searchList = ref(<any[]>[])
const searchList = ref(<ISearchList[]>[])
const optcatalogo = ref<IOptCatalogo | null>(null);
@@ -99,6 +99,8 @@ export default defineComponent({
myproduct.value = null
}
console.log('myproduct.value', myproduct.value)
if (myproduct.value) {
tools.setCookie(tools.COOK_LAST_PROD_SEARCH, myproduct.value._id.toString())
} else {
@@ -142,8 +144,8 @@ export default defineComponent({
table: 'products',
key: 'titolo',
type: costanti.FieldType.select_by_server,
value: myproduct.value?.productInfo?.name,
// addall: true,
value: myproduct.value,
collabel: collabel,
arrvalue: [],
useinput: true,
filter: null,
@@ -161,6 +163,16 @@ export default defineComponent({
router.push(path)
}
function collabel (rec: any) {
console.log('Record:', rec)
let label = ''
if (rec && rec.productInfo) {
label = `${rec.productInfo.name} - ${rec.productInfo.authors.map((a: any) => a.name + ' ' + a.surname).join(', ')}`
console.log('Computed label:', label)
}
return label
}
onMounted(mounted)
return {

View File

@@ -32,7 +32,7 @@
myclass=""
:icon_alternative="item.icon"
:optval="fieldsTable.getKeyByTable(item.table)"
:optlab="fieldsTable.getLabelByTable(item.table)"
:optlab="item.collabel"
:options="valoriopt(item, false)"
:filter="item.filter"
:filter_extra="item.filter_extra"