- miglioramenti ricerca titoli e modifica del trafiletto

- miglior visualizzazione delle liste
This commit is contained in:
Surya Paolo
2025-04-30 13:27:47 +02:00
parent 493ebf51f3
commit 358f0d6816
40 changed files with 1093 additions and 148 deletions

View File

@@ -14,6 +14,7 @@ import { CPrice } from '../CPrice'
import { CText } from '../CText'
import { CLabel } from '@src/components/CLabel'
import { CSchedaProdotto } from '@src/components/CSchedaProdotto'
import { CModifTrafiletto } from '@src/components/CModifTrafiletto'
import { CBarCode } from '../CBarCode'
import { CTableCupleLabelValue } from '../CTableCupleLabelValue'
@@ -89,7 +90,7 @@ export default defineComponent({
},
components: {
CTitleBanner, CCardState, CCopyBtn, CMyValueDb, VuePdfApp, CPrice, CBarCode, CLabel,
CText, CViewTable, CTableCupleLabelValue, CSchedaProdotto
CText, CViewTable, CTableCupleLabelValue, CSchedaProdotto, CModifTrafiletto
},
setup(props, { emit }) {
const $q = useQuasar()
@@ -163,6 +164,7 @@ export default defineComponent({
const storeSelected = ref('')
const arrordersCart = ref(<IOrderCart[]>[])
const modifOn = ref(false)
const modifTrafiletto = ref(false)
const modifProd = ref(false)
const timerInterval = ref(<any>null)
@@ -788,6 +790,7 @@ export default defineComponent({
// refreshAllDataBookFromGM,
refreshSingleBookFromGM,
loading,
modifTrafiletto,
}
}
})

View File

@@ -137,6 +137,27 @@
<q-item-label>Modifica</q-item-label>
</q-item-section>
</q-item>
<q-item
v-if="
(tools.isManager() || tools.isEditor()) &&
!optcatalogo.generazionePDFInCorso &&
(editOn || options.show_edit_book)
"
clickable
v-close-popup
@click="modifTrafiletto = true"
>
<q-item-section avatar>
<q-avatar
icon="fas fa-pencil-alt"
color="primary"
text-color="white"
/>
</q-item-section>
<q-item-section>
<q-item-label>Modifica Trafiletto</q-item-label>
</q-item-section>
</q-item>
<!--<q-item
v-if="
@@ -656,6 +677,26 @@
updateFieldToGM
</q-dialog>
<q-dialog
v-if="myproduct && modifTrafiletto"
v-model="modifTrafiletto"
maximized
>
<CModifTrafiletto
v-model="myproduct"
titolo="Trafiletto"
table="productinfos"
mykey="descr_trafiletto_catalogo"
:canModify="true"
:type="costanti.FieldType.editor_nohtml"
@updateproductmodif="updateproductmodif"
@close="modifTrafiletto = false"
:maxlength="800"
>
</CModifTrafiletto>
updateFieldToGM
</q-dialog>
<q-dialog
v-if="visufromgm && myproduct"
v-model="visufromgm"

View File

@@ -0,0 +1,23 @@
.drag-handle {
cursor: grab; /* Mostra la manina */
}
.drag-handle:active {
cursor: grabbing; /* Cambia la manina quando l'utente sta trascinando */
}
.etichetta{
margin-top: 5px;
margin-bottom: 5px;
padding-top: 5px;
padding-bottom: 5px;
font-weight: bold;
font-size: 1.15rem;
}
.boxtitleval{
padding: 10px;
vertical-align: middle;
}

View File

@@ -0,0 +1,168 @@
import { PropType, computed, defineComponent, onMounted, ref, watch } from "vue";
import draggable from 'vuedraggable'
import { tools } from '@tools'
import { useGlobalStore } from '@src/store/globalStore'
import { CMyEditorAI } from '@src/components/CMyEditorAI'
import { CAITools } from '@src/components/CAITools'
import { costanti } from '@costanti'
import type {
IMyScheda,
IProduct,
IRecFields
} from '@src/model';
import { shared_consts } from "app/src/common/shared_vuejs";
import { useProducts } from "app/src/store/Products";
import { useI18n } from "vue-i18n";
import { useQuasar } from "quasar";
export default defineComponent({
name: "CModifTrafiletto",
emits: ['updateproductmodif', 'close', 'Savedb'],
components: {
CMyEditorAI, CAITools
},
props: {
modelValue: {
type: Object as PropType<IProduct>,
required: true,
},
table: {
type: String,
required: true,
},
mykey: {
type: String,
required: true,
},
mysubkey: {
type: String,
required: false,
default: '',
},
titolo: {
type: String,
required: false,
default: '',
},
type: {
type: String,
required: false,
default: '',
},
canModify: {
type: Boolean,
required: false,
default: false,
},
maxlength: {
type: Number,
required: false,
default: 0,
}
},
setup(props, { emit }) {
// Copia locale della lista_prodotti per manipolazione interna
const $q = useQuasar()
const { t } = useI18n()
const globalStore = useGlobalStore()
const products = useProducts()
const mytab = ref('descr')
const loading = ref(false)
const updatetogm = ref(false)
const field_updated_toGM = ref('')
const myproduct = ref<IProduct>({ ...props.modelValue })
const id = computed(() => myproduct.value.productInfo._id)
const myvalue = computed<string>(() => {
return myproduct.value.productInfo[props.mykey]
})
watch(() => props.modelValue, (newVal) => {
myproduct.value = { ...newVal };
}, { deep: false });
async function mounted() {
}
/*
// Aggiorna la copia locale quando il prop cambia
watch(
() => props.lista_prodotti,
(newVal) => {
internalProducts.value = [...newVal];
}
);
*/
function updateproductmodif(element: any) {
// console.log('CModifTrafiletto updateproductmodif ', element)
emit('updateproductmodif', element)
}
function Savedb(element: any) {
tools.saveInDBForTypes($q, props.mykey, element, props.type, true, props.table, props.mysubkey, id.value, null, '');
}
async function updateproduct(load?: boolean) {
myproduct.value = await products.getProductById(myproduct.value._id, load)
}
const copyToClipboard = (text) => {
navigator.clipboard.writeText(text)
.then(() => {
$q.notify({
message: 'Testo copiato negli appunti!',
color: 'positive',
icon: 'check',
position: 'top'
});
})
.catch(err => {
console.error('Errore durante la copia:', err);
$q.notify({
message: 'Errore nella copia',
color: 'negative',
icon: 'error',
position: 'top'
});
});
};
onMounted(mounted)
return {
tools,
globalStore,
costanti,
shared_consts,
t,
products,
mytab,
myproduct,
updateproductmodif,
Savedb,
updatetogm,
field_updated_toGM,
loading,
copyToClipboard,
myvalue,
// refreshDataFromGM,
}
}
})

View File

@@ -0,0 +1,77 @@
<template>
<q-card class="dialog_card">
<q-toolbar class="bg-primary text-white">
<q-toolbar-title> Modifica a {{ myproduct.productInfo.name }}</q-toolbar-title>
<q-btn
flat
round
color="white"
icon="close"
v-close-popup
></q-btn>
</q-toolbar>
<q-card-section class="q-pa-xs inset-shadow">
<div>
<q-inner-loading
id="spinner"
:showing="loading"
>
<q-spinner-tail
color="primary"
size="4em"
>
</q-spinner-tail>
</q-inner-loading>
<q-tabs
v-model="mytab"
inline-label
class="text-blue shadow-2"
>
<q-tab
label="Descrizioni"
name="descr"
icon="fas fa-align-left"
></q-tab>
</q-tabs>
<q-tab-panels
v-model="mytab"
animated
>
<q-tab-panel name="descr">
<q-btn
flat
round
dense
label="Copia la Risposta"
icon="content_copy"
@click="copyToClipboard"
v-tooltip="'Copia negli appunti'"
/>
<CAITools></CAITools>
<CMyEditorAI
v-if="modelValue"
v-model:value="myvalue"
:title="titolo"
@keyup.enter.stop
:showButtons="true"
:canModify="canModify"
:hideTools="true"
@update:value="updateproductmodif"
@showandsave="Savedb"
:maxlength="maxlength"
>
</CMyEditorAI>
</q-tab-panel>
</q-tab-panels>
</div>
</q-card-section>
</q-card>
</template>
<script lang="ts" src="./CModifTrafiletto.ts"></script>
<style lang="scss" scoped>
@import './CModifTrafiletto.scss';
</style>

View File

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

View File

@@ -1,6 +1,6 @@
.clchip{
display: flex;
justify-content: center;
justify-content: left;
//flex: 1;
//flex-direction: column;
}

View File

@@ -1,15 +1,22 @@
<template>
<div class="row clchip">
<div v-for="(rec, index) in myarrvalues" :key="index" class="row items-center no-wrap">
<div class="text-caption text-weight-bold q-mr-sm">{{ label }}</div>
<div class="q-mb-sm">
<!-- Etichetta / Titolo -->
<div class="text-subtitle2 text-primary text-weight-medium q-mb-xs">
{{ label }}
</div>
<!-- Chips come valori -->
<div class="q-gutter-sm row wrap">
<q-chip
v-for="(rec, index) in myarrvalues"
:key="index"
:dense="dense"
class="clchip shadow-2"
:color="rec.color"
class="shadow-1 q-px-sm"
:color="rec.color || 'primary'"
text-color="white"
:icon="rec.icon"
:style="`border-radius: 10px;`"
>
:icon="rec.icon || undefined"
style="border-radius: 10px;"
>
{{ rec.label }}
</q-chip>
</div>

View File

@@ -34,6 +34,11 @@ export default defineComponent({
required: false,
default: false,
},
hideTools: {
type: Boolean,
required: false,
default: false,
},
maxlength: {
type: Number,
required: false,
@@ -51,8 +56,6 @@ export default defineComponent({
const myvalue = ref('')
const mycolor = ref('')
const showeditor = ref(true)
const myfonts = ref({
arial: 'Arial',
arial_black: 'Arial Black',
@@ -157,7 +160,6 @@ export default defineComponent({
console.log('saveval', myvalue.value)
emit('showandsave', myvalue.value)
// emit('update:value', myvalue)
showeditor.value = false
}
function setcolor() {

View File

@@ -13,19 +13,19 @@
color="white"
icon="close"
v-close-popup
@click="showeditor = false"
></q-btn>
</q-toolbar>
<q-card-section class="inset-shadow" style="padding: 4px !important">
<CTitleBanner v-if="title" :title="title"></CTitleBanner>
<form autocapitalize="off" autocomplete="off" spellcheck="false">
<q-toggle
v-if="!hideTools"
v-model="showtools"
:label="showtools ? $t('editor.hidetool') : $t('editor.showtool')"
@click="tools.setCookie('showtools', showtools ? '1' : '0')"
></q-toggle>
<br />
<q-btn v-if="showtools" rounded size="sm" color="primary">
<q-btn v-if="showtools && !hideTools" rounded size="sm" color="primary">
<q-icon name="colorize" class="cursor-pointer">
<q-popup-proxy>
<q-color v-model="mycolor" @change="setcolor"></q-color>
@@ -40,10 +40,11 @@
toolbar-toggle-color="yellow-8"
toolbar-bg="primary"
:readonly="!canModify"
:toolbar="showtools ? toolbarcomp : []"
:toolbar="showtools && !hideTools ? toolbarcomp : []"
:fonts="myfonts"
@update:model-value="changeval"
@paste="onPaste"
@keyup.esc.stop="visueditor = false"
@keyup.enter.stop
v-model="myvalue"
>

View File

@@ -0,0 +1,4 @@
.myflex{
display: flex;
flex: 1;
}

View File

@@ -0,0 +1,275 @@
import { tools } from '@tools'
import { CTitleBanner } from '../CTitleBanner'
import { defineComponent, onMounted, ref, toRef, watch } from 'vue'
import { useQuasar } from 'quasar'
export default defineComponent({
name: 'CMyEditorAI',
components: { CTitleBanner },
props: {
title: {
type: String,
required: false,
default: '',
},
value: {
type: String,
required: false,
default: '',
},
myclass: {
type: String,
required: false,
default: '',
},
showButtons: {
type: Boolean,
required: false,
default: true,
},
canModify: {
type: Boolean,
required: false,
default: false,
},
hideTools: {
type: Boolean,
required: false,
default: false,
},
maxlength: {
type: Number,
required: false,
default: 0,
}
},
setup(props, { emit }) {
const $q = useQuasar()
const editorRef = ref(<any>null)
const editor = ref('')
const characterCount = ref(0)
//const myvalue = toRef(props, 'value')
const myvalue = ref('')
const mycolor = ref('')
const myfonts = ref({
arial: 'Arial',
arial_black: 'Arial Black',
AGaramondProRegular: 'AGaramondPro-Regular',
comic_sans: 'Comic Sans MS',
courier_new: 'Courier New',
impact: 'Impact',
lucida_grande: 'Lucida Grande',
times_new_roman: 'Times New Roman',
verdana: 'Verdana',
})
const showtools = ref(false)
const toolbarcomp = ref([
['left', 'center', 'right', 'justify'],
['bold', 'italic', 'underline', 'strike'],
['token', 'hr', 'link', 'custom_btn', 'print', 'fullscreen'],
[
{
label: $q.lang.editor.formatting,
icon: $q.iconSet.editor.formatting,
list: 'no-icons',
options: [
'p',
'h4',
'h5',
'h6',
'code'
]
},
{
label: $q.lang.editor.fontSize,
icon: $q.iconSet.editor.fontSize,
fixedLabel: true,
fixedIcon: true,
list: 'no-icons',
options: [
'size-1',
'size-2',
'size-3',
'size-4',
'size-5',
'size-6',
'size-7'
]
},
{
label: $q.lang.editor.defaultFont,
icon: $q.iconSet.editor.font,
fixedIcon: true,
list: 'no-icons',
options: [
'default_font',
'arial',
'arial_black',
'comic_sans',
'courier_new',
'impact',
'lucida_grande',
'times_new_roman',
'verdana'
]
},
'removeFormat'
],
['quote', 'unordered', 'ordered', 'outdent', 'indent'],
['undo', 'redo', 'viewsource'],
])
watch(() => props.value, (newval, oldval) => {
if (props.value === undefined)
myvalue.value = ''
else
myvalue.value = props.value
})
function getTextLength(html: string) {
// Crea un elemento temporaneo per convertire HTML in testo
const div = document.createElement('div');
div.innerHTML = html; // Imposta l'HTML
return div.innerText.length; // Restituisce la lunghezza del testo
}
function changeval(newval: any) {
// console.log('myEditor: changeval', newval)
characterCount.value = getTextLength(newval)
emit('update:value', newval)
}
function annulla() {
emit('annulla', true)
}
function saveval() {
// Converti i <b> in <strong>
myvalue.value = tools.convertiTagHTMLPerBOT(myvalue.value)
console.log('saveval', myvalue.value)
emit('showandsave', myvalue.value)
// emit('update:value', myvalue)
}
function setcolor() {
document.execCommand('foreColor', false, mycolor.value)
}
/**
* Capture the <CTL-V> paste event, only allow plain-text, no images.
*
* see: https://stackoverflow.com/a/28213320
*
* @param {object} evt - array of files
* @author Daniel Thompson-Yvetot
* @license MIT
*/
function pasteCapture(evt: any) {
// let text, onPasteStripFormattingIEPaste
// evt.preventDefault()
// if (evt.originalEvent && evt.originalEvent.clipboardData.getData) {
// text = evt.originalEvent.clipboardData.getData('text/plain')
// $refs.editor_ref.runCmd('insertText', text)
// }
// else if (evt.clipboardData && evt.clipboardData.getData) {
// text = evt.clipboardData.getData('text/plain')
// $refs.editor_ref.runCmd('insertText', text)
// }
// else if (window.clipboardData && window.clipboardData.getData) {
// if (!onPasteStripFormattingIEPaste) {
// onPasteStripFormattingIEPaste = true
// $refs.editor_ref.runCmd('ms-pasteTextOnly', text)
// }
// onPasteStripFormattingIEPaste = false
// }
}
function mounted() {
if (props.value === undefined)
myvalue.value = ''
else
myvalue.value = props.value
showtools.value = tools.getCookie('showtools', '0') === '1'
characterCount.value = getTextLength(myvalue.value)
}
function onPaste(evt: any) {
// Let inputs do their thing, so we don't break pasting of links.
if (evt.target.nodeName === 'INPUT') return
let text, onPasteStripFormattingIEPaste
evt.preventDefault()
evt.stopPropagation()
if (evt.originalEvent && evt.originalEvent.clipboardData.getData) {
text = evt.originalEvent.clipboardData.getData('text/plain')
editorRef.value.runCmd('insertText', text)
}
else if (evt.clipboardData && evt.clipboardData.getData) {
text = evt.clipboardData.getData('text/plain')
editorRef.value.runCmd('insertText', text)
}
/*else if (ClipboardEvent.clipboardData && ClipboardEvent.clipboardData.getData) {
if (!onPasteStripFormattingIEPaste) {
onPasteStripFormattingIEPaste = true
editorRef.value.runCmd('ms-pasteTextOnly', text)
}
onPasteStripFormattingIEPaste = false
}*/
}
const copyToClipboard = (text) => {
navigator.clipboard.writeText(text)
.then(() => {
$q.notify({
message: 'Testo copiato negli appunti!',
color: 'positive',
icon: 'check',
position: 'top'
});
})
.catch(err => {
console.error('Errore durante la copia:', err);
$q.notify({
message: 'Errore nella copia',
color: 'negative',
icon: 'error',
position: 'top'
});
});
};
onMounted(mounted)
return {
myfonts,
toolbarcomp,
editor,
myvalue,
mycolor,
changeval,
annulla,
saveval,
setcolor,
pasteCapture,
tools,
onPaste,
editorRef,
showtools,
characterCount,
copyToClipboard,
}
}
})

View File

@@ -0,0 +1,86 @@
<template>
<div>
<q-card class="dialog_card">
<q-toolbar
v-if="showButtons"
class="bg-primary text-white"
style="min-height: 30px"
>
<q-toolbar-title> Editor </q-toolbar-title>
<q-btn
flat
round
color="white"
icon="close"
v-close-popup
></q-btn>
</q-toolbar>
<q-card-section class="inset-shadow" style="padding: 4px !important">
<CTitleBanner v-if="title" :title="title"></CTitleBanner>
<form autocapitalize="off" autocomplete="off" spellcheck="false">
<q-toggle
v-if="!hideTools"
v-model="showtools"
:label="showtools ? $t('editor.hidetool') : $t('editor.showtool')"
@click="tools.setCookie('showtools', showtools ? '1' : '0')"
></q-toggle>
<br />
<q-btn v-if="showtools && !hideTools" rounded size="sm" color="primary">
<q-icon name="colorize" class="cursor-pointer">
<q-popup-proxy>
<q-color v-model="mycolor" @change="setcolor"></q-color>
</q-popup-proxy>
</q-icon>
</q-btn>
<q-editor
ref="editorRef"
content-class="wrap_anywhere"
toolbar-text-color="white"
toolbar-toggle-color="yellow-8"
toolbar-bg="primary"
:readonly="!canModify"
:toolbar="showtools && !hideTools ? toolbarcomp : []"
:fonts="myfonts"
@update:model-value="changeval"
@paste="onPaste"
@keyup.esc.stop="visueditor = false"
@keyup.enter.stop
v-model="myvalue"
>
</q-editor>
<div v-if="maxlength" class="text-gray text-italic">Caratteri: {{ characterCount }} / {{ maxlength }}</div>
</form>
</q-card-section>
<q-card-actions v-if="showButtons" align="center">
<q-btn
v-if="canModify"
:label="$t('dialog.save')"
color="primary"
@click="saveval"
></q-btn>
<q-btn
v-if="canModify"
flat
:label="$t('dialog.close')"
color="primary"
v-close-popup
@click="annulla"
></q-btn>
<q-btn
v-if="!canModify"
:label="$t('dialog.ok')"
color="primary"
v-close-popup
></q-btn>
</q-card-actions>
</q-card>
</div>
</template>
<script lang="ts" src="./CMyEditorAI.ts">
</script>
<style lang="scss" scoped>
@import './CMyEditorAI.scss';
</style>

View File

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

View File

@@ -15,6 +15,7 @@ import { CCurrencyValue } from '../CCurrencyValue'
import { CMapEditAddressByCoord } from '../CMapEditAddressByCoord'
import { CInput } from '../CInput'
import { CMyEditor } from '../CMyEditor'
import { CMyEditorAI } from '../CMyEditorAI'
import { CGallery } from '../CGallery'
import { CSelectImage } from '../CSelectImage'
import { CAccomodation } from '../CAccomodation'
@@ -219,7 +220,7 @@ export default defineComponent({
},
},
components: {
CMyChipList, CDateTime, CDate, CMyToggleList, CMySelect, CMyEditor, CGallery,
CMyChipList, CDateTime, CDate, CMyToggleList, CMySelect, CMyEditor, CGallery, CMyEditorAI,
CCurrencyValue, CLabel, CAccomodation, CSelectImage, CMapEditAddressByCoord, CInput,
},
setup(props, { emit }) {
@@ -254,6 +255,27 @@ export default defineComponent({
minlength: props.mycol ? props.mycol.minlength : undefined
})
const copyToClipboard = (text) => {
navigator.clipboard.writeText(text)
.then(() => {
$q.notify({
message: 'Testo copiato negli appunti!',
color: 'positive',
icon: 'check',
position: 'top'
});
})
.catch(err => {
console.error('Errore durante la copia:', err);
$q.notify({
message: 'Errore nella copia',
color: 'negative',
icon: 'error',
position: 'top'
});
});
};
const { setValDb, getValDb } = MixinBase()
const { getMyUsername } = MixinUsers()
@@ -414,7 +436,7 @@ export default defineComponent({
}
function changevalRecOrig(newval: any, subcol: string = '') {
console.log('changevalRec', newval)
// console.log('changevalRec', newval)
// if (!props.insertMode || (props.insertMode && col.value.fieldtype !== costanti.FieldType.multioption)) {
if (col.value && col.value.allowchar === costanti.ALLOWCHAR_CODE) {
newval = tools.removespaces_slash(newval)
@@ -481,8 +503,7 @@ export default defineComponent({
}
function mounted() {
console.log('mounted CMyPopupEdit')
//console.log('mounted CMyPopupEdit')
myrow.value = props.rec && props.isrec ? { ...props.rec } : { ...props.row }
@@ -928,6 +949,7 @@ export default defineComponent({
}
}
onBeforeMount(mounted)
@@ -975,6 +997,7 @@ export default defineComponent({
handleKeydown,
handleCancel,
popupEditRef,
copyToClipboard,
}
}
})

View File

@@ -183,6 +183,36 @@
</div>
</div>
</div>
<div v-else-if="col.fieldtype === costanti.FieldType.op_andor">
<div>
<q-select
v-if="isInModif"
v-model="myvalue"
:label="t('dialog.condition')"
:options="[
{ label: $t('dialog.conditionAND'), value: costanti.OP_ANDOR.OP_AND },
{ label: $t('dialog.conditionOR'), value: costanti.OP_ANDOR.OP_OR },
]"
emit-value
map-options
@update:model-value="changevalRec"
>
</q-select>
<span v-else>
<div class="text-subtitle2 text-primary text-weight-medium">
{{ $t('dialog.condition') }}
</div>
<q-chip
class="q-ma-md q-pa-sm"
:color="myvalue === costanti.OP_ANDOR.OP_AND ? 'red' : 'green'"
text-color="white"
:icon="myvalue === costanti.OP_ANDOR.OP_AND ? 'fas fa-filter' : 'fas fa-sliders-h'"
:label="myvalue === costanti.OP_ANDOR.OP_AND ? $t('dialog.conditionAND') : $t('dialog.conditionOR')"
></q-chip>
</span>
</div>
</div>
<div v-else-if="col.fieldtype === costanti.FieldType.string || col.fieldtype === costanti.FieldType.crypted">
<div
v-if="isInModif"
@@ -1072,6 +1102,22 @@
</q-checkbox>
<span v-html="visuValByType(myvalue, col, row)"></span>
</div>
<div v-else-if="col.fieldtype === costanti.FieldType.op_andor">
<q-select
v-model="scope.value"
:label="t('dialog.condition')"
:options="[
{ label: 'Filtra se Tutti i criteri sono veri (AND)', value: costanti.OP_ANDOR.OP_AND },
{ label: 'Filtra se almeno uno dei criteri è vero (OR)', value: costanti.OP_ANDOR.OP_OR },
]"
emit-value
map-options
:color="scope.value === costanti.OP_ANDOR.OP_AND ? 'red' : 'green'"
:icon="scope.value === costanti.OP_ANDOR.OP_AND ? 'fas fa-filter' : 'fas fa-sliders-h'"
@update:model-value="changevalRec"
>
</q-select>
</div>
<div
v-else-if="col.fieldtype === costanti.FieldType.string || col.fieldtype === costanti.FieldType.crypted"
>
@@ -1097,6 +1143,25 @@
</template>
</q-input>
</div>
<div v-else-if="col.fieldtype === costanti.FieldType.editor_nohtml">
<div
class="q-pa-md"
style="min-width: 600px;"
>
<CMyEditorAI
v-model:value="scope.value"
:title="col.visulabel ? t(col.label_trans) : visulabel ? addstrrequired + col.label : undefined"
@keyup.enter.stop
:showButtons="false"
:canModify="canModify"
:hideTools="true"
@update:value="changevalRec"
@showandsave="Savedb"
:maxlength="col.maxlength"
>
</CMyEditorAI>
</div>
</div>
<div v-else-if="col.fieldtype === costanti.FieldType.number">
<div v-if="visulabel">
<q-input

View File

@@ -133,7 +133,7 @@ export default defineComponent({
if (myrec.value.editore) {
for (const receditore of myrec.value.editore) {
const rectrovato: IPublisher = products.publishers.find((editore: IPublisher) => editore._id === receditore)
editorestr.value += rectrovato.name + ' '
editorestr.value += rectrovato?.name + ' '
}
}

View File

@@ -106,8 +106,8 @@ export default defineComponent({
// Colonne della tabella
const allColumns = [
{ name: "pos", label: "Pos", field: "pos", align: "left", style: "width: 50px" },
{ name: "drag", label: "Ordinam.", field: "", align: "left", style: "width: 50px", edit: true },
{ name: "pos", label: "Ind", field: "pos", align: "left", style: "width: 50px" },
{ name: "drag", label: "Ord", field: "", align: "left", style: "width: 50px", edit: true },
{ name: "image", label: "Foto", field: "image", align: "center" },
{ name: "name", label: "Titolo del Libro", field: "name", align: "left" },
{ name: "authors", label: "Autore", field: "authors", align: "left" },
@@ -125,11 +125,11 @@ export default defineComponent({
//{ name: "rank6M", label: "Class. 6M", field: "rank6M", align: "right", visu: costanti.VISUCAMPI.PER_EDITORE },
//{ name: "rank1Y", label: "Class. 1Y", field: "rank1Y", align: "right", visu: costanti.VISUCAMPI.PER_EDITORE },
{ name: "pagine", label: "Pag.", field: "pagine", align: "right" },
{ name: "totVen", label: "Venduti", field: "totVen", align: "right", visu: costanti.VISUCAMPI.PER_EDITORE },
{ name: "totFat", label: "Fattur.", field: "totFat", align: "right", visu: costanti.VISUCAMPI.PER_EDITORE },
{ name: "totVen", label: "Vend", field: "totVen", align: "right", visu: costanti.VISUCAMPI.PER_EDITORE },
{ name: "fatLast6M", label: "Fat 6M", field: "fatLast6M", align: "right", visu: costanti.VISUCAMPI.PER_EDITORE },
{ name: "fatLast1Y", label: "Fat Anno", field: "fatLast1Y", align: "right", visu: costanti.VISUCAMPI.PER_EDITORE },
{ name: "fatLast1Y", label: "Fat 1A", field: "fatLast1Y", align: "right", visu: costanti.VISUCAMPI.PER_EDITORE },
{ name: "fatLast2Y", label: "Fat 2A", field: "fatLast2Y", align: "right", visu: costanti.VISUCAMPI.PER_EDITORE },
{ name: "totFat", label: "Fat 5A", field: "totFat", align: "right", visu: costanti.VISUCAMPI.PER_EDITORE },
{ name: "ult_ord", label: "Ult. Ordine", field: "ult_ord", align: "left", visu: costanti.VISUCAMPI.PER_EDITORE },
{ name: "quantity", label: "Magazz.", field: "quantity", align: "right", visu: costanti.VISUCAMPI.PER_EDITORE },
{ name: "actions", label: "Azioni", field: "", align: "center", visu: costanti.VISUCAMPI.PER_EDITORE },
@@ -202,6 +202,9 @@ export default defineComponent({
case 'fatLast1Y':
return element.productInfo?.fatLast1Y;
case 'fatLast2Y':
return element.productInfo?.fatLast2Y;
case 'ult_ord':
return tools.getstrDate(element.productInfo?.dataUltimoOrdine);
@@ -254,6 +257,7 @@ export default defineComponent({
case 'totFat':
case 'fatLast6M':
case 'fatLast1Y':
case 'fatLast2Y':
default:
return '';
@@ -268,14 +272,12 @@ export default defineComponent({
height: '50px'
};
case 'rank3M':
case 'rank6M':
case 'rank1Y':
case 'pagine':
case 'totVen':
case 'totFat':
case 'fatLast6M':
case 'fatLast1Y':
case 'fatLast2Y':
case 'quantity':
return {
textAlign: 'right'
@@ -308,7 +310,15 @@ export default defineComponent({
// 3. Funzione per verificare se una colonna è visibile (isColumnVisible)
const isColumnVisible = (column) => {
const isColumnVisible = (column, real?: boolean) => {
if (column === 'actions' && !real) {
return false
}
if (internalProducts.value?.length > 1000) {
if (column === 'image') {
return false
}
}
const ok = allColumns.some((col) => col.name === column) && (!props.optcatalogo.showListaArgomenti || (props.optcatalogo.showListaArgomenti && !column.edit))
return selectedColumns.value.includes(column) && ok;
}
@@ -458,11 +468,6 @@ export default defineComponent({
case 'image':
return () => showProduct(element);
case 'name':
case 'authors':
case 'isbn':
return () => showProduct(element);
case 'stato':
return () => {
// esempio: mostra dettagli dello stato

View File

@@ -12,7 +12,7 @@
option-value="name"
option-label="label"
filled
style="max-width: 400px"
style="max-width: 300px"
/>
</div>
@@ -108,7 +108,7 @@
{{ getFieldValue(element, field) }}
</td>
<!-- Azioni -->
<td v-else-if="field.name === 'actions' && isColumnVisible('actions')">
<td v-else-if="field.name === 'actions' && isColumnVisible('actions', true)">
<q-btn-dropdown
label="Azioni"
color="primary"

View File

@@ -107,6 +107,26 @@ export default defineComponent({
debounce: "1000",
type: costanti.FieldType.number,
},
{
editOn: false,
label: "Fatturati ultimo Anno",
table: "productinfos",
id: myproduct.value.productInfo._id,
rec: myproduct.value.productInfo,
mykey: "fatLast1Y",
debounce: "1000",
type: costanti.FieldType.number,
},
{
editOn: false,
label: "Fatturati ultimi 2 Anni",
table: "productinfos",
id: myproduct.value.productInfo._id,
rec: myproduct.value.productInfo,
mykey: "fatLast2Y",
debounce: "1000",
type: costanti.FieldType.number,
},
{
editOn: false,
label: "Venduti",
@@ -142,13 +162,23 @@ export default defineComponent({
table: "productinfos",
id: myproduct.value.productInfo._id,
rec: myproduct.value.productInfo,
mykey: "vLastY",
mykey: "vLast1Y",
debounce: "1000",
type: costanti.FieldType.number,
},
{
editOn: false,
label: "Venduti Ultimi 2 Anni",
table: "productinfos",
id: myproduct.value.productInfo._id,
rec: myproduct.value.productInfo,
mykey: "vLast2Y",
debounce: "1000",
type: costanti.FieldType.number,
},
// SEZIONE RANKING (FATTURATI)
{
/*{
editOn: false,
label: "Ranking 3 Mesi",
table: "productinfos",
@@ -177,7 +207,7 @@ export default defineComponent({
mykey: "rank1Y",
debounce: "1000",
type: costanti.FieldType.number,
},
},*/
];
return arrlist
}
@@ -187,24 +217,27 @@ export default defineComponent({
{
editOn: true,
label: "Descrizione Trafiletto per Catalogo",
title: myproduct.value?.productInfo?.name,
table: "productinfos",
id: myproduct.value.productInfo._id, // ID dinamico, da sostituire con il valore reale
rec: myproduct.value.productInfo, // Oggetto dinamico, da sostituire con il valore reale
mykey: "descr_trafiletto_catalogo",
debounce: "1000",
type: costanti.FieldType.string,
type: costanti.FieldType.editor_nohtml,
dense: true,
showall: true,
},
{
editOn: true,
label: "Descrizione breve macro",
title: myproduct.value?.productInfo?.name,
table: "productinfos",
id: myproduct.value.productInfo._id, // ID dinamico, da sostituire con il valore reale
rec: myproduct.value.productInfo, // Oggetto dinamico, da sostituire con il valore reale
mykey: "descrizione_breve_macro",
maxlength: 650,
debounce: "1000",
type: costanti.FieldType.string,
type: costanti.FieldType.editor_nohtml,
dense: true,
showall: true,
},
@@ -295,7 +328,7 @@ export default defineComponent({
mykey: "idCatProds",
debounce: "1000",
type: costanti.FieldType.multiselect,
jointable: 'catprods',
jointable: 'catprtotali',
dense: true,
},
{

View File

@@ -223,7 +223,7 @@ export default defineComponent({
searchList.value = [
{
visible: true,
label: 'Ricerca',
label: 'Cerca un Titolo o un Autore',
table: 'products',
key: 'titolo',
type: costanti.FieldType.select_by_server,
@@ -233,6 +233,7 @@ export default defineComponent({
useinput: true,
filter: null,
tablesel: 'products',
dense: false,
},
]

View File

@@ -12,7 +12,7 @@
v-if="loadpage"
class="panel"
>
<div class="text-h6 text-bold text-blue text-center">Cerca un Titolo:</div>
<!--<div class="text-h6 text-bold text-blue text-center">Cerca un Titolo:</div>-->
<div
class="col"
v-for="(item, index) in searchList"
@@ -40,6 +40,7 @@
:filter="item.filter"
:filter_extra="item.filter_extra"
:useinput="item.useinput && item.type !== costanti.FieldType.select_by_server"
:dense="item.dense"
@searchOnGM="searchOnGM"
@clear="
item.value = '';

View File

@@ -14,6 +14,7 @@
<div class="table-cell value-cell">
<CMyValueDb
:editOn="myrec.editOn"
:title="myrec.title"
:table="myrec.table"
:id="myrec.id"
:rec="myrec.rec"