- aggiunto FeaturesSection all'editor HTML

This commit is contained in:
Surya Paolo
2025-09-17 01:21:40 +02:00
parent e40bf8b73d
commit 917cdaa754
17 changed files with 307 additions and 49 deletions

View File

@@ -347,7 +347,8 @@ export default defineConfig((ctx) => {
set plugins(value) {
this._plugins = value;
},
iconSet: 'fontawesome-v5',
// iconSet: 'fontawesome-v5',
iconSet: 'material-icons',
lang: 'it', // Quasar language
},

View File

@@ -132,6 +132,11 @@ export const shared_consts = {
CAROUSEL_IDISCIPLINE: 80,
CAROUSEL_HOME: 85,
CHECK_EMAIL: 100,
IMAGE_GALLERY: 101,
HEADING: 102,
LIST: 103,
CODE: 104,
DIVIDER: 105,
CAROUSEL_IMGS: 110,
OPENSTREETMAP: 120,
MAINVIEW: 130,
@@ -178,11 +183,7 @@ export const shared_consts = {
SECTION: 1000,
ROW: 1100,
COLUMN: 1200,
IMAGE_GALLERY: 101,
HEADING: 102,
LIST: 103,
CODE: 104,
DIVIDER: 105,
PAGE_SECTION: 1500,
},
QUERYTYPE_MYGROUP: 1,
@@ -2085,6 +2086,11 @@ export const shared_consts = {
label: 'Scheda (IMG + Testo)',
icon: 'fas fa-id-card',
},
{
value: 1500,
label: 'Sezione Pagina',
icon: 'fas fa-newspaper',
},
/*
Disattivato perchè attualmente non funziona bene
{

View File

@@ -260,7 +260,7 @@ export default defineComponent({
// @ts-ignore
label: page.title,
// @ts-ignore
value: page.idPage,
value: page.path,
};
arrPages.value.push(rec);
}
@@ -820,6 +820,19 @@ export default defineComponent({
colorPicker.value.openDialog();
}
function removeFeature(index: number) {
myel.value.features.splice(index, 1);
saveElem();
}
function addFeature() {
myel.value.features.push({
name: 'Titolo',
description: 'sottotitolo',
icon: 'fas fa-heading',});
saveElem();
}
onMounted(mounted);
return {
@@ -890,6 +903,8 @@ export default defineComponent({
AddedNewElem,
openColorPicker,
colorPicker,
removeFeature,
addFeature,
};
},
});

View File

@@ -2774,6 +2774,82 @@
<div></div>
</div>
</div>
<div v-else-if="myel.type === shared_consts.ELEMTYPE.PAGE_SECTION">
<!-- Edita i seguenti campi:
Title, subtitle, features {name, icon, description }-->
<q-toggle
v-model="myel.parambool2"
color="positive"
icon="fas fa-moon"
label="Dark"
@update:model-value="modifElem"
></q-toggle>
<q-input
dense
label="Sottotitolo Primario"
@update:model-value="modifElem"
v-model="myel.container3"
filled
v-on:keyup.enter="saveElem"
></q-input>
<q-input
dense
label="Titolo"
@update:model-value="modifElem"
v-model="myel.container"
filled
v-on:keyup.enter="saveElem"
></q-input>
<q-input
dense
label="Sottotitolo"
@update:model-value="modifElem"
v-model="myel.container2"
filled
v-on:keyup.enter="saveElem"
></q-input>
<div v-if="myel.features && myel.features.length > 0" class="q-mt-md">
<div v-for="(feature, index) in myel.features" :key="index">
<div class="bg-blue text-white">Testo {{index + 1}}:</div>
<q-input
dense
label="Nome"
@update:model-value="modifElem"
v-model="myel.features[index].name"
filled
v-on:keyup.enter="saveElem"
></q-input>
<q-input
dense
label="Icona"
@update:model-value="modifElem"
v-model="myel.features[index].icon"
filled
v-on:keyup.enter="saveElem"
></q-input>
<q-input
dense
label="Descrizione"
@update:model-value="modifElem"
v-model="myel.features[index].description"
filled
v-on:keyup.enter="saveElem"
></q-input>
<q-btn
icon="fas fa-times"
color="negative"
@click="removeFeature(index)"
></q-btn>
</div>
</div>
<q-btn
icon="fas fa-plus"
color="positive"
@click="addFeature()"
></q-btn>
</div>
</q-list>
</div>
<br /><br /><br />

View File

@@ -6,6 +6,7 @@ import { IMyCard, IMyPage, IOperators } from '@src/model';
import { useGlobalStore } from '@store/globalStore';
import { CImgTitle } from '../CImgTitle/index';
import { FeaturesSection } from '../FeaturesSection/index';
import { CImgPoster } from '@src/components/CImgPoster';
import CSection from '@src/components/CSection/CSection.vue';
import CRow from '@src/components/CRow/CRow.vue';
@@ -71,6 +72,7 @@ import { useRouter } from 'vue-router';
import { LatLng } from 'leaflet';
import { costanti } from '@costanti';
import objectId from 'app/src/js/objectId';
export default defineComponent({
name: 'CMyElem',
@@ -114,6 +116,7 @@ export default defineComponent({
CDashGroup,
CMovements,
CGridOriz,
FeaturesSection,
CQRCode,
CCatalogList,
CSearchProduct,
@@ -207,6 +210,18 @@ export default defineComponent({
groups.push(cards.slice(i, i + currentCardsPerSlide.value));
}
if (!groups.length) {
groups.push([
{
_id: objectId(),
imagefile: '',
alt: '',
description: '',
vers_img: 0,
} as IMyCard,
]);
}
return groups;
});
@@ -253,7 +268,7 @@ export default defineComponent({
$q,
t,
props.myelem,
{idPage: props.idPage, path: props.path},
{ idPage: props.idPage, path: props.path },
newtype.value
);
}
@@ -341,7 +356,6 @@ export default defineComponent({
shared_consts.MsgTeleg.SHARE_MSGREG,
true
);
}
// Classe per le colonne delle card
@@ -350,11 +364,11 @@ export default defineComponent({
return `col-${width}`;
}
function updateCatalogoEmit(updatedCatalogo?: IOptCatalogo) {
function updateCatalogoEmit(updatedCatalogo?: IOptCatalogo) {
if (!updatedCatalogo) return;
console.log('CMyElem: updateCatalogoEmit');
myel.value.catalogo = updatedCatalogo;
}
}
function naviga(path?: string): void {
if (path) {

View File

@@ -129,7 +129,7 @@
<div
class="img-container"
:style="`height: ${
myel.heightimg.replace('px', '') * 0.7
parseInt(myel?.heightimg?.replace('px', '')) * 0.7
}px; overflow: hidden;`"
>
<q-img
@@ -387,6 +387,9 @@
Pagina: {{ myel.container }}
</div>
</div>
<!--
<CMyPageElem v-if="myel.container" title="" :mypath="myel.container"> </CMyPageElem>
-->
</div>
<div v-else-if="myel.type === shared_consts.ELEMTYPE.PAGEINTRO">
<div
@@ -1149,6 +1152,19 @@
<div v-else-if="myel.type === shared_consts.ELEMTYPE.FOOTER">
<LandingFooter />
</div>
<div v-else-if="myel.type === shared_consts.ELEMTYPE.PAGE_SECTION">
<FeaturesSection
:title="myel.container"
:subtitle="myel.container2"
:description="myel.container3"
:features="myel.features"
:isDark="myel.parambool2"
>
</FeaturesSection>
</div>
<div v-if="editOn">
<div class="q-ma-md"></div>

View File

@@ -121,6 +121,7 @@ export default defineComponent({
let neword = 0; // Ordinamento dell'elemento da aggiungere
let recfound = null; // Variabile per conservare l'elemento trovato
if (elemsel) {
// Gestisci il movimento sopra o sotto
if (direz === -1) {
// Sopra: ottieni l'elemento precedente, mantenendo l'ordinamento
@@ -129,6 +130,7 @@ export default defineComponent({
// Sotto: ottieni l'elemento successivo, mantenendo l'ordinamento
recfound = globalStore.getMyElemNextThisElemId(props.idPage, elemsel._id);
}
}
// Se è stato trovato un elemento precedente o successivo
if (recfound) {

View File

@@ -167,13 +167,22 @@ export default defineComponent({
const addAtEnd = () => {
visuadd.value = true;
const last =
myelems.value.length > 0 ? myelems.value[myelems.value.length - 1] : null;
if (myelems.value === null) {
myElemSel.value = myelemVoid.value;
myElemParent.value = myelemVoid.value;
} else {
const last = myelems.value[myelems.value.length - 1];
if (last) {
myElemSel.value = last;
myElemParent.value = last;
} else {
myElemSel.value = myelemVoid.value;
myElemParent.value = myelemVoid.value;
}
}
};
const showOrder = ref(false)
const showOrder = ref(false);
const myelems = computed(() => {
if (myidPage.value) return globalStore.getMyElemsByIdPage(myidPage.value);
@@ -502,6 +511,7 @@ export default defineComponent({
function AddedNewElem(newrec: any) {
emit('selElemClick', newrec);
visuadd.value = false;
}
function getColClasses(col: any, rowOrCount?: any, idx = 0) {

View File

@@ -369,22 +369,6 @@
/>
</div>
<!-- Aggiungi elemento al fondo lista -->
<div
v-if="editOn"
class="text-center q-mt-sm"
>
<q-btn
dense
rounded
size="sm"
color="positive"
icon="add"
@click="addAtEnd()"
>
<q-tooltip>Aggiungi Elemento</q-tooltip>
</q-btn>
</div>
</div>
</transition>
</div>
@@ -401,6 +385,23 @@
@selElemClick="selElemClick"
/>
</div>
<!-- Aggiungi elemento al fondo lista -->
<div
v-if="editOn"
class="text-center q-mt-sm"
>
<q-btn
dense
rounded
size="sm"
color="positive"
icon="add"
@click="addAtEnd()"
>
<q-tooltip>Aggiungi Elemento</q-tooltip>
</q-btn>
</div>
</div>
<LandingFooter v-if="rec.showFooter" />

View File

@@ -3,10 +3,7 @@
<!-- Stato errore URL non valido -->
<div v-if="!videoId" class="cmy-yt__error">
<q-icon name="warning" class="q-mr-sm" />
Link YouTube non valido.
<div class="text-caption text-grey-7 q-mt-xs">
Esempi accettati: https://youtu.be/ID, https://www.youtube.com/watch?v=ID
</div>
Inserire un link YouTube valido
</div>
<!-- Modalità thumbnail -> click per avviare -->

View File

@@ -0,0 +1,43 @@
import { defineComponent } from 'vue';
// Importiamo icone da Quasar - esempio con quelle disponibili tramite Quasar Extras
// Assicurati di averle abilitate in quasar.config.js
import { IFeatSection } from 'app/src/model';
import { tools } from 'app/src/store/Modules/tools';
import { useQuasar } from 'quasar';
export default defineComponent({
name: 'FeaturesSection',
props: {
title: {
type: String,
required: true,
},
isDark: {
type: Boolean,
required: false,
default: false,
},
subtitle: {
type: String,
required: false,
default: '',
},
description: {
type: String,
required: false,
default: '',
},
features: {
type: Array as () => IFeatSection[],
required: true,
},
},
setup(props) {
return {
tools,
};
},
});

View File

@@ -0,0 +1,60 @@
<template>
<div :class="{'bg-dark': isDark}" class="q-py-xl">
<!-- Container principale -->
<div class="q-px-md sm:q-px-lg md:q-px-xl">
<div class="row justify-center">
<div class="col-12 col-md-10 col-lg-8 text-center q-pb-lg">
<div class="text-indigo-4 text-body2 text-weight-bold">{{ description }}</div>
<div :class="{'text-white': isDark}" class="text-h4 text-weight-bold q-mt-sm q-mb-md">
{{ title }}
</div>
<div :class="{'text-grey-4': isDark, 'text-grey-2': isDark}" class="text-subtitle1">
{{ subtitle }}
</div>
</div>
</div>
<!-- Griglia delle features -->
<div class="row justify-center q-mt-lg">
<div class="col-12 col-lg-10">
<div class="row q-col-gutter-xl">
<div
v-for="feature in features"
:key="feature.name"
class="col-12 col-sm-6"
>
<q-card flat class="bg-transparent">
<q-card-section horizontal>
<!-- Icona circolare -->
<div class="self-start q-mt-xs q-mr-md">
<q-avatar v-if="feature.icon" size="40px" color="indigo-5" text-color="white" rounded>
<q-icon :name="feature.icon" />
</q-avatar>
</div>
<div>
<q-card-section class="p-none">
<div :class="{'text-white': isDark}" class="text-subtitle2 text-weight-medium">
{{ feature.name }}
</div>
</q-card-section>
<q-card-section class="q-pt-none">
<div :class="{'text-grey-4': isDark, 'text-grey-2': isDark}" class="text-body2">
{{ feature.description }}
</div>
</q-card-section>
</div>
</q-card-section>
</q-card>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" src="./FeaturesSection.ts"></script>
<style lang="scss" scoped>
@import './FeaturesSection.scss';
</style>

View File

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

View File

@@ -262,7 +262,7 @@ h3 {
font-weight: 400;
line-height: 1.75rem;
letter-spacing: .00937em;
text-shadow: .25rem .25rem .5rem $grayshadow;
text-shadow: .0625rem .0625rem .125rem $grayshadow;
}
.text-subtitle3 {

View File

@@ -199,6 +199,13 @@ export interface IMyElem {
rows?: any[]
columns?: any[]
elems?: any[]
features?: IFeatSection[]
}
export interface IFeatSection {
name?: string
icon?: string
description?: string
}
export interface IElemText {

View File

@@ -3079,10 +3079,19 @@ export const useGlobalStore = defineStore('GlobalStore', {
newrec.catalogo = this.createRaccoltaCataloghiVuoto();
} else if (newrec.type === shared_consts.ELEMTYPE.TEXT) {
newrec.container = "Inserisci qui il testo"
newrec.align = shared_consts.ALIGNTYPE.CEHTER
} else if (newrec.type === shared_consts.ELEMTYPE.HTML) {
newrec.containerHtml = "Inserisci qui il testo"
newrec.align = shared_consts.ALIGNTYPE.CEHTER
} else if (newrec.type === shared_consts.ELEMTYPE.IMAGEUPLOAD) {
newrec.containerHtml
newrec.align = shared_consts.ALIGNTYPE.CEHTER
} else if (newrec.type === shared_consts.ELEMTYPE.BUTTON) {
newrec.container = "Bottone 1"
newrec.containerHtml = "primary"
newrec.container2 = "fas fa-home"
newrec.align = shared_consts.ALIGNTYPE.CEHTER
newrec.link = "https://www.pippo.it"
newrec.container3 = "_blank"
}
// Aggiungi il nuovo elemento alla struttura