feat(front) : tags multiselect — couleur des sites + limite d'affichage
- Sites : les tags du multiselect prennent la couleur de fond du site (champ color, groupe site:read) avec texte blanc, en saisie comme en consultation (clients, fournisseurs, prestataires, produits). - Autres multiselects : 3 tags affichés au maximum (surplus condensé en « +N »). - Bump @malio/layer-ui 1.7.15 → 1.7.17 (support color/textColor et maxTags sur les options).
This commit is contained in:
@@ -53,6 +53,7 @@
|
||||
v-if="!hideEmpty || isFilled(model.contactIris)"
|
||||
:model-value="model.contactIris"
|
||||
:options="contactOptions"
|
||||
:max-tags="3"
|
||||
:label="t('commercial.clients.form.address.contacts')"
|
||||
:display-tag="true"
|
||||
:readonly="readonly"
|
||||
@@ -97,6 +98,7 @@
|
||||
<MalioSelectCheckbox
|
||||
:model-value="model.categoryIris"
|
||||
:options="categoryOptions"
|
||||
:max-tags="3"
|
||||
:label="t('commercial.clients.form.address.categories')"
|
||||
:display-tag="true"
|
||||
:readonly="readonly"
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
v-if="!hideEmpty || isFilled(model.contactIris)"
|
||||
:model-value="model.contactIris"
|
||||
:options="contactOptions"
|
||||
:max-tags="3"
|
||||
:label="t('commercial.suppliers.form.address.contacts')"
|
||||
:display-tag="true"
|
||||
:readonly="readonly"
|
||||
@@ -67,6 +68,7 @@
|
||||
<MalioSelectCheckbox
|
||||
:model-value="model.categoryIris"
|
||||
:options="categoryOptions"
|
||||
:max-tags="3"
|
||||
:label="t('commercial.suppliers.form.address.categories')"
|
||||
:display-tag="true"
|
||||
:readonly="readonly"
|
||||
|
||||
@@ -45,7 +45,7 @@ describe('useClientReferentials.loadCommon (resilience ERP-102)', () => {
|
||||
|
||||
// Resilience : les referentiels OK sont peuples malgre l'echec de /categories.
|
||||
// Le libelle d'un site est son numero de departement (2 premiers chiffres du code postal).
|
||||
expect(refs.sites.value).toEqual([{ value: '/api/sites/1', label: '86' }])
|
||||
expect(refs.sites.value).toEqual([{ value: '/api/sites/1', label: '86', textColor: '#FFFFFF' }])
|
||||
expect(refs.tvaModes.value).toEqual([{ value: '/api/x/1', label: 'Libelle X' }])
|
||||
expect(refs.banks.value).toEqual([{ value: '/api/x/1', label: 'Libelle X' }])
|
||||
// Pays : value = nom du pays (et non l'IRI).
|
||||
@@ -63,7 +63,7 @@ describe('useClientReferentials.loadCommon (resilience ERP-102)', () => {
|
||||
})
|
||||
}
|
||||
if (url === '/sites') {
|
||||
return Promise.resolve({ member: [{ '@id': '/api/sites/1', name: 'Chatellerault', postalCode: '86100' }] })
|
||||
return Promise.resolve({ member: [{ '@id': '/api/sites/1', name: 'Chatellerault', postalCode: '86100', color: '#FF0000' }] })
|
||||
}
|
||||
return Promise.resolve({ member: [] })
|
||||
})
|
||||
@@ -74,8 +74,9 @@ describe('useClientReferentials.loadCommon (resilience ERP-102)', () => {
|
||||
expect(refs.categories.value).toEqual([
|
||||
{ value: '/api/categories/1', label: 'Secteur', code: 'SECTEUR' },
|
||||
])
|
||||
// Le libelle d'un site est son numero de departement (2 premiers chiffres du code postal).
|
||||
expect(refs.sites.value).toEqual([{ value: '/api/sites/1', label: '86' }])
|
||||
// Le libelle d'un site est son numero de departement (2 premiers chiffres du
|
||||
// code postal) ; la couleur du site est reportee (fond) avec un texte blanc.
|
||||
expect(refs.sites.value).toEqual([{ value: '/api/sites/1', label: '86', color: '#FF0000', textColor: '#FFFFFF' }])
|
||||
})
|
||||
|
||||
it('separe les categories CLIENT (formulaire) des categories ADRESSE (blocs adresse)', async () => {
|
||||
|
||||
@@ -19,6 +19,13 @@ import { ref } from 'vue'
|
||||
export interface RefOption {
|
||||
value: string
|
||||
label: string
|
||||
// Couleur de fond optionnelle de l'option (hex #RRGGBB). Aujourd'hui
|
||||
// alimentee par le referentiel sites (couleur d'identification du site,
|
||||
// affichee sur les tags selectionnes du multiselect).
|
||||
color?: string
|
||||
// Couleur de texte optionnelle (hex). Sites : blanc, pour rester lisible
|
||||
// sur le fond colore du tag.
|
||||
textColor?: string
|
||||
}
|
||||
|
||||
/** Option de type de reglement enrichie de son code stable (RG-1.12 / RG-1.13). */
|
||||
@@ -46,6 +53,7 @@ interface CategoryMember extends HydraMember {
|
||||
interface SiteMember extends HydraMember {
|
||||
name: string
|
||||
postalCode: string
|
||||
color?: string
|
||||
}
|
||||
|
||||
interface ReferentialMember extends HydraMember {
|
||||
@@ -119,7 +127,7 @@ export function useClientReferentials() {
|
||||
// Libelle = numero de departement (2 premiers chiffres du code
|
||||
// postal du site), ex: 86100 -> « 86 ». Le code postal est deja
|
||||
// expose par /sites (groupe site:read) — aucune colonne a ajouter.
|
||||
.then((sitesList) => { sites.value = sitesList.map(s => ({ value: s['@id'], label: (s.postalCode ?? '').slice(0, 2) })) }),
|
||||
.then((sitesList) => { sites.value = sitesList.map(s => ({ value: s['@id'], label: (s.postalCode ?? '').slice(0, 2), color: s.color, textColor: '#FFFFFF' })) }),
|
||||
fetchAll<ReferentialMember>('/tva_modes')
|
||||
.then((tva) => { tvaModes.value = tva.map(t => ({ value: t['@id'], label: t.label })) }),
|
||||
fetchAll<ReferentialMember>('/payment_delays')
|
||||
|
||||
@@ -20,6 +20,13 @@ import { ref } from 'vue'
|
||||
export interface RefOption {
|
||||
value: string
|
||||
label: string
|
||||
// Couleur de fond optionnelle de l'option (hex #RRGGBB). Alimentee par le
|
||||
// referentiel sites (couleur d'identification du site, affichee sur les tags
|
||||
// selectionnes du multiselect).
|
||||
color?: string
|
||||
// Couleur de texte optionnelle (hex). Sites : blanc, pour rester lisible
|
||||
// sur le fond colore du tag.
|
||||
textColor?: string
|
||||
}
|
||||
|
||||
/** Option de type de reglement enrichie de son code stable (RG-2.07 / RG-2.08). */
|
||||
@@ -44,6 +51,7 @@ interface CategoryMember extends HydraMember {
|
||||
interface SiteMember extends HydraMember {
|
||||
name: string
|
||||
postalCode: string
|
||||
color?: string
|
||||
}
|
||||
|
||||
interface ReferentialMember extends HydraMember {
|
||||
@@ -106,7 +114,7 @@ export function useSupplierReferentials() {
|
||||
fetchAll<SiteMember>('/sites')
|
||||
// Libelle = numero de departement (2 premiers chiffres du code
|
||||
// postal du site), ex: 86100 -> « 86 ».
|
||||
.then((sitesList) => { sites.value = sitesList.map(s => ({ value: s['@id'], label: (s.postalCode ?? '').slice(0, 2) })) }),
|
||||
.then((sitesList) => { sites.value = sitesList.map(s => ({ value: s['@id'], label: (s.postalCode ?? '').slice(0, 2), color: s.color, textColor: '#FFFFFF' })) }),
|
||||
fetchAll<ReferentialMember>('/tva_modes')
|
||||
.then((tva) => { tvaModes.value = tva.map(t => ({ value: t['@id'], label: t.label })) }),
|
||||
fetchAll<ReferentialMember>('/payment_delays')
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
<MalioSelectCheckbox
|
||||
:model-value="main.categoryIris"
|
||||
:options="mainCategoryOptions"
|
||||
:max-tags="3"
|
||||
:label="t('commercial.clients.form.main.categories')"
|
||||
:display-tag="true"
|
||||
:disabled="businessReadonly"
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
v-if="isFilled(categoryIris)"
|
||||
:model-value="categoryIris"
|
||||
:options="mainCategoryOptions"
|
||||
:max-tags="3"
|
||||
:label="t('commercial.clients.form.main.categories')"
|
||||
:display-tag="true"
|
||||
disabled
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
<MalioSelectCheckbox
|
||||
:model-value="main.categoryIris"
|
||||
:options="referentials.categories.value"
|
||||
:max-tags="3"
|
||||
:label="t('commercial.clients.form.main.categories')"
|
||||
:display-tag="true"
|
||||
:disabled="mainLocked"
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
<MalioSelectCheckbox
|
||||
:model-value="main.categoryIris"
|
||||
:options="mainCategoryOptions"
|
||||
:max-tags="3"
|
||||
:label="t('commercial.suppliers.form.main.categories')"
|
||||
:display-tag="true"
|
||||
:disabled="businessReadonly"
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
v-if="isFilled(categoryIris)"
|
||||
:model-value="categoryIris"
|
||||
:options="mainCategoryOptions"
|
||||
:max-tags="3"
|
||||
:label="t('commercial.suppliers.form.main.categories')"
|
||||
:display-tag="true"
|
||||
disabled
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
<MalioSelectCheckbox
|
||||
:model-value="main.categoryIris"
|
||||
:options="referentials.categories.value"
|
||||
:max-tags="3"
|
||||
:label="t('commercial.suppliers.form.main.categories')"
|
||||
:display-tag="true"
|
||||
:disabled="mainLocked"
|
||||
|
||||
@@ -168,9 +168,9 @@ describe('options construites depuis l\'embed (role-independantes)', () => {
|
||||
])
|
||||
})
|
||||
|
||||
it('siteOptionsOf expose value=IRI, label=nom', () => {
|
||||
it('siteOptionsOf expose value=IRI, label=nom, color, textColor', () => {
|
||||
expect(siteOptionsOf([{ '@id': '/api/sites/4', name: 'Chatellerault', color: '#000' }])).toEqual([
|
||||
{ value: '/api/sites/4', label: 'Chatellerault' },
|
||||
{ value: '/api/sites/4', label: 'Chatellerault', color: '#000', textColor: '#FFFFFF' },
|
||||
])
|
||||
})
|
||||
|
||||
@@ -201,7 +201,7 @@ describe('options construites depuis l\'embed (role-independantes)', () => {
|
||||
categories: [{ '@id': '/api/categories/3', name: 'Secteur', code: 'SECTEUR' }],
|
||||
})
|
||||
expect(view.draft.id).toBe(18)
|
||||
expect(view.siteOptions).toEqual([{ value: '/api/sites/4', label: 'Chatellerault' }])
|
||||
expect(view.siteOptions).toEqual([{ value: '/api/sites/4', label: 'Chatellerault', textColor: '#FFFFFF' }])
|
||||
expect(view.categoryOptions).toEqual([{ value: '/api/categories/3', label: 'Secteur', code: 'SECTEUR' }])
|
||||
})
|
||||
})
|
||||
|
||||
@@ -155,9 +155,9 @@ describe('options construites depuis l\'embed (role-independantes)', () => {
|
||||
])
|
||||
})
|
||||
|
||||
it('siteOptionsOf expose value=IRI, label=nom', () => {
|
||||
it('siteOptionsOf expose value=IRI, label=nom, color, textColor', () => {
|
||||
expect(siteOptionsOf([{ '@id': '/api/sites/87', name: 'Chatellerault', color: '#000' }])).toEqual([
|
||||
{ value: '/api/sites/87', label: 'Chatellerault' },
|
||||
{ value: '/api/sites/87', label: 'Chatellerault', color: '#000', textColor: '#FFFFFF' },
|
||||
])
|
||||
})
|
||||
|
||||
@@ -190,7 +190,7 @@ describe('options construites depuis l\'embed (role-independantes)', () => {
|
||||
})
|
||||
expect(view.draft.id).toBe(33)
|
||||
expect(view.draft.addressType).toBe('RENDU')
|
||||
expect(view.siteOptions).toEqual([{ value: '/api/sites/87', label: 'Chatellerault' }])
|
||||
expect(view.siteOptions).toEqual([{ value: '/api/sites/87', label: 'Chatellerault', textColor: '#FFFFFF' }])
|
||||
expect(view.categoryOptions).toEqual([{ value: '/api/categories/2279', label: 'Negociant', code: 'NEGOCIANT' }])
|
||||
})
|
||||
})
|
||||
|
||||
@@ -143,6 +143,12 @@ export interface ClientRelation {
|
||||
export interface SelectOption {
|
||||
value: string
|
||||
label: string
|
||||
// Couleur de fond optionnelle (hex #RRGGBB), reportee pour les sites afin
|
||||
// de colorer les tags selectionnes en consultation comme en edition.
|
||||
color?: string
|
||||
// Couleur de texte optionnelle (hex). Sites : blanc, pour rester lisible
|
||||
// sur le fond colore du tag.
|
||||
textColor?: string
|
||||
}
|
||||
|
||||
/** Option de categorie enrichie de son code (compatible CategoryOption des blocs). */
|
||||
@@ -266,7 +272,7 @@ export function categoryOptionsOf(categories: CategoryRead[] | undefined): Categ
|
||||
|
||||
/** Options de sites (value=IRI, label=nom) construites depuis l'embed d'une adresse. */
|
||||
export function siteOptionsOf(sites: SiteRead[] | undefined): SelectOption[] {
|
||||
return (sites ?? []).map(s => ({ value: s['@id'], label: s.name ?? s['@id'] }))
|
||||
return (sites ?? []).map(s => ({ value: s['@id'], label: s.name ?? s['@id'], color: s.color, textColor: '#FFFFFF' }))
|
||||
}
|
||||
|
||||
/** Options de contacts (value=IRI, label=nom complet ou email) depuis l'embed client. */
|
||||
|
||||
@@ -138,6 +138,12 @@ export interface AccountingDraft {
|
||||
export interface SelectOption {
|
||||
value: string
|
||||
label: string
|
||||
// Couleur de fond optionnelle (hex #RRGGBB), reportee pour les sites afin
|
||||
// de colorer les tags selectionnes en consultation comme en edition.
|
||||
color?: string
|
||||
// Couleur de texte optionnelle (hex). Sites : blanc, pour rester lisible
|
||||
// sur le fond colore du tag.
|
||||
textColor?: string
|
||||
}
|
||||
|
||||
/** Option de categorie enrichie de son code (compatible CategoryOption des blocs). */
|
||||
@@ -241,7 +247,7 @@ export function categoryOptionsOf(categories: CategoryRead[] | undefined): Categ
|
||||
|
||||
/** Options de sites (value=IRI, label=nom) construites depuis l'embed d'une adresse. */
|
||||
export function siteOptionsOf(sites: SiteRead[] | undefined): SelectOption[] {
|
||||
return (sites ?? []).map(s => ({ value: s['@id'], label: s.name ?? s['@id'] }))
|
||||
return (sites ?? []).map(s => ({ value: s['@id'], label: s.name ?? s['@id'], color: s.color, textColor: '#FFFFFF' }))
|
||||
}
|
||||
|
||||
/** Options de contacts (value=IRI, label=nom complet ou email) depuis l'embed fournisseur. */
|
||||
|
||||
Reference in New Issue
Block a user