codevdesign 1.0.77 → 1.0.79
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/csqc.css +28 -30
- package/composants/csqcAide.vue +1 -1
- package/composants/csqcAlerteErreur.vue +1 -1
- package/composants/csqcChaise/chaiseConteneur.vue +3 -3
- package/composants/csqcChaise/chaiseItem.vue +54 -54
- package/composants/csqcCodeBudgetaireGenerique.vue +254 -254
- package/composants/csqcConfirmation.vue +2 -1
- package/composants/csqcDate.vue +4 -1
- package/composants/csqcDialogue.vue +6 -4
- package/composants/csqcEditeurTexteRiche.vue +1 -1
- package/composants/csqcEntete.vue +17 -17
- package/composants/csqcImportCSV.vue +2 -2
- package/composants/csqcModaleSaisie.vue +1 -1
- package/composants/csqcRecherche.vue +7 -7
- package/composants/csqcRechercheUtilisateur.vue +1 -1
- package/composants/csqcSnackbar.vue +1 -1
- package/composants/csqcSwitch.vue +5 -5
- package/composants/csqcTable/csqcTable.vue +19 -14
- package/composants/csqcTable/csqcTableModaleChoixColonnes.vue +4 -4
- package/composants/csqcTable/sortableDataTable.ts +1 -1
- package/composants/csqcTexteBilingue.vue +175 -175
- package/composants/csqcTiroir.vue +7 -5
- package/composants/gabarit/csqcMenu.vue +4 -4
- package/composants/gabarit/pivEntete.vue +5 -3
- package/composants/gabarit/pivPiedPage.vue +44 -29
- package/composants/validateurs.ts +8 -2
- package/editeur.ts +1 -1
- package/importCSV.ts +1 -1
- package/index.ts +80 -80
- package/locales/en.json +1 -1
- package/locales/fr.json +3 -3
- package/modeles/assurancesAssuranceGeneraleGrics.ts +3 -3
- package/modeles/assurancesAssurancePersonnelleGrics.ts +6 -6
- package/modeles/assurancesContratGrics.ts +6 -6
- package/modeles/assurancesDetailsPrimeReguliereGrics.ts +4 -4
- package/modeles/assurancesDonneesAssureurGrics.ts +5 -5
- package/modeles/assurancesEmployeGrics.ts +4 -4
- package/modeles/assurancesGrics.ts +6 -6
- package/modeles/assurancesRegimeAssuranceGrics.ts +2 -2
- package/modeles/assurancesRegimeBaseEmployeurGrics.ts +2 -2
- package/modeles/assurancesRegimeBaseGrics.ts +2 -2
- package/modeles/composants/csqcMenuModele.ts +18 -18
- package/modeles/composants/datatableColonne.ts +19 -19
- package/modeles/employeAdresseGrics.ts +6 -6
- package/modeles/employeAdressesPersonnellesGrics.ts +4 -4
- package/modeles/employeAffectationCorpsEmploiGrics.ts +2 -2
- package/modeles/employeBanquesCongeBanqueGrics.ts +2 -2
- package/modeles/employeBanquesCongeGrics.ts +6 -6
- package/modeles/employeBanquesCongeRegimeAbsenceGrics.ts +2 -2
- package/modeles/employeCourrielsPersonnels.ts +2 -2
- package/modeles/employeCourrielsProfessionnels.ts +2 -2
- package/modeles/employeEmploisCategorieGrics.ts +2 -2
- package/modeles/employeEmploisClasseGrics.ts +2 -2
- package/modeles/employeEmploisCorpsEmploiGrics.ts +2 -2
- package/modeles/employeEmploisEtatEmploiGrics.ts +2 -2
- package/modeles/employeEmploisGrics.ts +29 -29
- package/modeles/employeEmploisGroupePaieGrics.ts +2 -2
- package/modeles/employeEmploisLieuTravailPrincipalGrics.ts +3 -3
- package/modeles/employeEmploisLieuxTravailSecondairesGrics.ts +3 -3
- package/modeles/employeEmploisRegimeAbsenceGrics.ts +2 -2
- package/modeles/employeEmploisSecteurGrics.ts +2 -2
- package/modeles/employeEmploisStatutEngagementGrics.ts +2 -2
- package/modeles/employeExperienceEmploiGrics.ts +2 -2
- package/modeles/employeExperienceEmployeGrics.ts +5 -5
- package/modeles/employeExperienceExperiencesGrics.ts +4 -4
- package/modeles/employeExperienceExperiencesTotalesGrics.ts +7 -7
- package/modeles/employeExperienceGrics.ts +9 -9
- package/modeles/employeGrics.ts +23 -23
- package/modeles/employeTelephoneGrics.ts +4 -4
- package/modeles/employeTelephonesPersonnelsGrics.ts +3 -3
- package/modeles/employeTelephonesProfessionnelsGrics.ts +3 -3
- package/modeles/groupeCE.ts +6 -6
- package/modeles/groupeCEIntervalle.ts +6 -6
- package/modeles/historiquesAbsenceBanqueGrics.ts +2 -2
- package/modeles/historiquesAbsenceGrics.ts +13 -13
- package/modeles/historiquesAbsenceLieuTravailGrics.ts +2 -2
- package/modeles/historiquesAbsenceSousBanqueGrics.ts +2 -2
- package/modeles/motifsAbsenceBanque.ts +2 -2
- package/modeles/motifsAbsenceGrics.ts +9 -9
- package/modeles/motifsAbsenceRegimeAbsence.ts +2 -2
- package/modeles/motifsAbsenceSousMotifs.ts +2 -2
- package/modeles/motifsAbsenceTraitementBanques.ts +3 -3
- package/modeles/syndicat.ts +18 -18
- package/modeles/syndicatGroupeCe.ts +3 -3
- package/modeles/syndicatResponsable.ts +8 -8
- package/modeles/syndicatUnite.ts +3 -3
- package/modeles/unite.ts +15 -15
- package/modeles/uniteTypeEnseignement.ts +4 -4
- package/modeles/utilisateur.ts +8 -8
- package/outils/appAxios.ts +16 -16
- package/outils/csqcOutils.ts +6 -5
- package/outils/csqcRafraichisseurTokenParent.ts +20 -4
- package/outils/rafraichisseurToken.ts +310 -310
- package/package.json +1 -1
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
@blur="sauvegarder"
|
|
22
22
|
@keydown.enter="sauvegarder"
|
|
23
23
|
@keydown="caractereAutorises"
|
|
24
|
-
@update:
|
|
24
|
+
@update:model-value="gererChangement"
|
|
25
25
|
@paste="gererPaste"
|
|
26
26
|
>
|
|
27
27
|
<template #item="{ props, item }">
|
|
@@ -37,294 +37,294 @@
|
|
|
37
37
|
</template>
|
|
38
38
|
|
|
39
39
|
<script setup lang="ts">
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const formValide = ref(false)
|
|
69
|
-
const form = ref<VForm | null>(null)
|
|
70
|
-
const codeBudgetaire = ref(props.modelValue ?? '')
|
|
71
|
-
const derniereValeurSauvegardee = ref<string | null>(null)
|
|
72
|
-
const format = props.format
|
|
73
|
-
const activerExtension = props.activerExtension
|
|
74
|
-
|
|
75
|
-
onMounted(() => {
|
|
76
|
-
derniereValeurSauvegardee.value = codeBudgetaire.value
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
const itemsCombobox = computed(() => {
|
|
80
|
-
return props.codeBudgetairesProp.map(item => {
|
|
81
|
-
if (typeof item === 'string') {
|
|
82
|
-
return {
|
|
83
|
-
code: item,
|
|
84
|
-
nom: '', // pas de nom
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const [code, nomBrut] = item
|
|
89
|
-
const nom = (nomBrut ?? '').toString().trim()
|
|
90
|
-
|
|
91
|
-
return { code, nom }
|
|
92
|
-
})
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
const placeholder = computed(() => {
|
|
96
|
-
const base = format.replace(/9/g, '0')
|
|
97
|
-
const extension = activerExtension ? '-XXX/XXX' : ''
|
|
98
|
-
return base + extension
|
|
99
|
-
})
|
|
100
|
-
|
|
101
|
-
const estValide = computed(() => {
|
|
102
|
-
const val = codeBudgetaire.value?.toUpperCase().trim() || ''
|
|
103
|
-
const base = val.slice(0, 15)
|
|
104
|
-
const extension = val.slice(15)
|
|
105
|
-
|
|
106
|
-
if (!/^\d{3}-\d{1}-\d{5}-\d{3}$/.test(base)) return false
|
|
107
|
-
|
|
108
|
-
if (!activerExtension) return val.length === 15
|
|
109
|
-
|
|
110
|
-
if (val.length === 15) return true
|
|
111
|
-
if (val.length !== 22) return false
|
|
112
|
-
if (extension.length !== 7) return false
|
|
113
|
-
|
|
114
|
-
if (extension[3] !== '/') return false
|
|
115
|
-
if (!/^[A-Z0-9/]$/i.test(extension[0]!)) return false
|
|
116
|
-
|
|
117
|
-
const alphanumAt = [1, 2, 4, 5, 6]
|
|
118
|
-
return alphanumAt.every(i => /^[A-Z0-9]$/i.test(extension[i]!))
|
|
119
|
-
})
|
|
40
|
+
import { ref, computed, onMounted, nextTick, watch } from 'vue'
|
|
41
|
+
import type { VForm } from 'vuetify/components'
|
|
42
|
+
|
|
43
|
+
const emit = defineEmits<{
|
|
44
|
+
'update:modelValue': [string | null]
|
|
45
|
+
'update:codeBudgetairesProp': [CodeBudgetaireItem[]]
|
|
46
|
+
'update:valide': [boolean]
|
|
47
|
+
}>()
|
|
48
|
+
type CodeBudgetaireItem = string | [string, string]
|
|
49
|
+
|
|
50
|
+
const props = withDefaults(
|
|
51
|
+
defineProps<{
|
|
52
|
+
codeBudgetairesProp: CodeBudgetaireItem[]
|
|
53
|
+
modelValue: string | null
|
|
54
|
+
afficherHint?: boolean
|
|
55
|
+
regleMessageErreur: string
|
|
56
|
+
format?: string
|
|
57
|
+
activerExtension?: boolean
|
|
58
|
+
reglesSupp?: ((v: string) => true | string)[]
|
|
59
|
+
}>(),
|
|
60
|
+
{
|
|
61
|
+
afficherHint: false,
|
|
62
|
+
format: '999-9-99999-999',
|
|
63
|
+
activerExtension: false,
|
|
64
|
+
reglesSupp: () => [],
|
|
65
|
+
},
|
|
66
|
+
)
|
|
120
67
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
return
|
|
136
|
-
|
|
68
|
+
const formValide = ref(false)
|
|
69
|
+
const form = ref<VForm | null>(null)
|
|
70
|
+
const codeBudgetaire = ref(props.modelValue ?? '')
|
|
71
|
+
const derniereValeurSauvegardee = ref<string | null>(null)
|
|
72
|
+
const format = props.format
|
|
73
|
+
const activerExtension = props.activerExtension
|
|
74
|
+
|
|
75
|
+
onMounted(() => {
|
|
76
|
+
derniereValeurSauvegardee.value = codeBudgetaire.value
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
const itemsCombobox = computed(() => {
|
|
80
|
+
return props.codeBudgetairesProp.map(item => {
|
|
81
|
+
if (typeof item === 'string') {
|
|
82
|
+
return {
|
|
83
|
+
code: item,
|
|
84
|
+
nom: '', // pas de nom
|
|
85
|
+
}
|
|
86
|
+
}
|
|
137
87
|
|
|
138
|
-
const
|
|
139
|
-
|
|
88
|
+
const [code, nomBrut] = item
|
|
89
|
+
const nom = (nomBrut ?? '').toString().trim()
|
|
140
90
|
|
|
141
|
-
|
|
142
|
-
|
|
91
|
+
return { code, nom }
|
|
92
|
+
})
|
|
93
|
+
})
|
|
143
94
|
|
|
144
|
-
|
|
145
|
-
|
|
95
|
+
const placeholder = computed(() => {
|
|
96
|
+
const base = format.replace(/9/g, '0')
|
|
97
|
+
const extension = activerExtension ? '-XXX/XXX' : ''
|
|
98
|
+
return base + extension
|
|
99
|
+
})
|
|
146
100
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
return
|
|
152
|
-
}
|
|
101
|
+
const estValide = computed(() => {
|
|
102
|
+
const val = codeBudgetaire.value?.toUpperCase().trim() || ''
|
|
103
|
+
const base = val.slice(0, 15)
|
|
104
|
+
const extension = val.slice(15)
|
|
153
105
|
|
|
154
|
-
|
|
155
|
-
e.preventDefault()
|
|
106
|
+
if (!/^\d{3}-\d{1}-\d{5}-\d{3}$/.test(base)) return false
|
|
156
107
|
|
|
157
|
-
|
|
158
|
-
const clean = value.slice(0, 12) + e.key
|
|
108
|
+
if (!activerExtension) return val.length === 15
|
|
159
109
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
if (clean.length > 4) formatted += '-' + clean.slice(4, 9)
|
|
164
|
-
if (clean.length > 9) formatted += '-' + clean.slice(9, 12)
|
|
110
|
+
if (val.length === 15) return true
|
|
111
|
+
if (val.length !== 22) return false
|
|
112
|
+
if (extension.length !== 7) return false
|
|
165
113
|
|
|
166
|
-
|
|
114
|
+
if (extension[3] !== '/') return false
|
|
115
|
+
if (!/^[A-Z0-9/]$/i.test(extension[0]!)) return false
|
|
167
116
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
})
|
|
117
|
+
const alphanumAt = [1, 2, 4, 5, 6]
|
|
118
|
+
return alphanumAt.every(i => /^[A-Z0-9]$/i.test(extension[i]!))
|
|
119
|
+
})
|
|
172
120
|
|
|
173
|
-
|
|
174
|
-
|
|
121
|
+
// Règles Vuetify combinées (interne + supplémentaires)
|
|
122
|
+
const reglesVuetify = computed(() => [
|
|
123
|
+
// règle interne
|
|
124
|
+
() => (estValide.value ? true : props.regleMessageErreur),
|
|
175
125
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
126
|
+
// règles supplémentaires venant du parent
|
|
127
|
+
...props.reglesSupp.map(rule => {
|
|
128
|
+
return () => rule(codeBudgetaire.value) // on passe la valeur formatée
|
|
129
|
+
}),
|
|
130
|
+
])
|
|
181
131
|
|
|
182
|
-
|
|
132
|
+
// Validité globale du composant (interne + toutes les règles supp)
|
|
133
|
+
const estValideComplet = computed(() => {
|
|
134
|
+
if (!estValide.value) return false
|
|
135
|
+
return props.reglesSupp.every(rule => rule(codeBudgetaire.value) === true)
|
|
136
|
+
})
|
|
183
137
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
if (!/^[A-Z0-9/]$/i.test(e.key)) {
|
|
187
|
-
e.preventDefault()
|
|
188
|
-
return
|
|
189
|
-
}
|
|
190
|
-
return
|
|
191
|
-
}
|
|
138
|
+
const caractereAutorises = (e: KeyboardEvent) => {
|
|
139
|
+
if (e.ctrlKey || e.metaKey) return
|
|
192
140
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
if (!/^[A-Z0-9]$/i.test(e.key)) {
|
|
196
|
-
e.preventDefault()
|
|
197
|
-
return
|
|
198
|
-
}
|
|
199
|
-
return
|
|
200
|
-
}
|
|
141
|
+
const touchesSpecifiques = ['Backspace', 'Delete', 'ArrowLeft', 'ArrowRight', 'Tab', 'Home', 'End']
|
|
142
|
+
if (touchesSpecifiques.includes(e.key)) return
|
|
201
143
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
e.preventDefault()
|
|
205
|
-
const before = codeBudgetaire.value.slice(0, position)
|
|
206
|
-
const after = codeBudgetaire.value.slice(position)
|
|
207
|
-
codeBudgetaire.value = before + '/' + after
|
|
208
|
-
nextTick(() => {
|
|
209
|
-
input.selectionStart = input.selectionEnd = position + 1
|
|
210
|
-
})
|
|
211
|
-
return
|
|
212
|
-
}
|
|
144
|
+
const input = e.target as HTMLInputElement
|
|
145
|
+
const position = input.selectionStart ?? 0
|
|
213
146
|
|
|
214
|
-
|
|
147
|
+
// Gestion de la partie de base (15 premiers caractères)
|
|
148
|
+
if (position < 15) {
|
|
149
|
+
if (!/^\d$/.test(e.key)) {
|
|
215
150
|
e.preventDefault()
|
|
151
|
+
return
|
|
216
152
|
}
|
|
217
153
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
const upper = valeur.toUpperCase().replace(/[^A-Z0-9/]/g, '')
|
|
222
|
-
const chiffres = upper.replace(/[^0-9]/g, '').slice(0, 12)
|
|
223
|
-
|
|
224
|
-
let base = ''
|
|
225
|
-
if (chiffres.length > 0) base += chiffres.slice(0, 3)
|
|
226
|
-
if (chiffres.length > 3) base += '-' + chiffres.slice(3, 4)
|
|
227
|
-
if (chiffres.length > 4) base += '-' + chiffres.slice(4, 9)
|
|
228
|
-
if (chiffres.length > 9) base += '-' + chiffres.slice(9, 12)
|
|
154
|
+
// Insérer chiffre et auto-ajout des tirets
|
|
155
|
+
e.preventDefault()
|
|
229
156
|
|
|
230
|
-
|
|
157
|
+
const value = codeBudgetaire.value.replace(/-/g, '')
|
|
158
|
+
const clean = value.slice(0, 12) + e.key
|
|
231
159
|
|
|
232
|
-
|
|
160
|
+
let formatted = ''
|
|
161
|
+
if (clean.length > 0) formatted += clean.slice(0, 3)
|
|
162
|
+
if (clean.length > 3) formatted += '-' + clean.slice(3, 4)
|
|
163
|
+
if (clean.length > 4) formatted += '-' + clean.slice(4, 9)
|
|
164
|
+
if (clean.length > 9) formatted += '-' + clean.slice(9, 12)
|
|
233
165
|
|
|
234
|
-
|
|
235
|
-
let ext = reste.slice(0, 7).split('')
|
|
166
|
+
codeBudgetaire.value = formatted.slice(0, 15)
|
|
236
167
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
})
|
|
242
|
-
|
|
243
|
-
// Enlever les slash non autorisés
|
|
244
|
-
ext = ext.map((c, i) => {
|
|
245
|
-
if (c === '/' && i !== 0 && i !== 3) return ''
|
|
246
|
-
if (c !== '/' && !/^[A-Z0-9]$/i.test(c)) return ''
|
|
247
|
-
return c
|
|
248
|
-
})
|
|
168
|
+
nextTick(() => {
|
|
169
|
+
const newPos = codeBudgetaire.value.length
|
|
170
|
+
input.selectionStart = input.selectionEnd = newPos
|
|
171
|
+
})
|
|
249
172
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
ext[3] = '/'
|
|
253
|
-
}
|
|
173
|
+
return
|
|
174
|
+
}
|
|
254
175
|
|
|
255
|
-
|
|
256
|
-
|
|
176
|
+
// --- Gestion de l'extension ---
|
|
177
|
+
if (!activerExtension || position >= 22 || codeBudgetaire.value.length >= 22) {
|
|
178
|
+
e.preventDefault()
|
|
179
|
+
return
|
|
180
|
+
}
|
|
257
181
|
|
|
258
|
-
|
|
259
|
-
}
|
|
182
|
+
const extensionPos = position - 15
|
|
260
183
|
|
|
261
|
-
|
|
184
|
+
// Règle 1 : extension[0] = alphanum ou /
|
|
185
|
+
if (extensionPos === 0) {
|
|
186
|
+
if (!/^[A-Z0-9/]$/i.test(e.key)) {
|
|
262
187
|
e.preventDefault()
|
|
263
|
-
|
|
264
|
-
if (!clipboardData) return
|
|
265
|
-
let pasted = clipboardData.getData('text') || ''
|
|
266
|
-
codeBudgetaire.value = formaterCodeBudgetaire(pasted)
|
|
267
|
-
|
|
268
|
-
setTimeout(() => {
|
|
269
|
-
const input = e.target as HTMLInputElement
|
|
270
|
-
input.selectionStart = input.selectionEnd = codeBudgetaire.value.length
|
|
271
|
-
}, 0)
|
|
188
|
+
return
|
|
272
189
|
}
|
|
190
|
+
return
|
|
191
|
+
}
|
|
273
192
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
const codeNormalise = codeBudgetaire.value.trim().toUpperCase()
|
|
281
|
-
|
|
282
|
-
const existe = props.codeBudgetairesProp.some(item => {
|
|
283
|
-
const code = typeof item === 'string' ? item : item[0]
|
|
284
|
-
return code.trim().toUpperCase() === codeNormalise
|
|
285
|
-
})
|
|
286
|
-
|
|
287
|
-
if (!existe) {
|
|
288
|
-
const nouvelleListe = [...props.codeBudgetairesProp, codeBudgetaire.value]
|
|
289
|
-
emit('update:codeBudgetairesProp', nouvelleListe)
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
derniereValeurSauvegardee.value = codeBudgetaire.value
|
|
293
|
-
emit('update:modelValue', codeBudgetaire.value)
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
const extraireCode = (val: unknown): string => {
|
|
297
|
-
if (val == null) return ''
|
|
298
|
-
if (typeof val === 'string') return val
|
|
299
|
-
|
|
300
|
-
// Cas où Vuetify enverrait { code, label }
|
|
301
|
-
if (typeof val === 'object' && 'code' in (val as Record<string, unknown>)) {
|
|
302
|
-
const obj = val as { code?: unknown }
|
|
303
|
-
return typeof obj.code === 'string' ? obj.code : String(obj.code ?? '')
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
return String(val)
|
|
193
|
+
// Règle 2 : extension[1,2,4,5,6] = alphanum
|
|
194
|
+
if ([1, 2, 4, 5, 6].includes(extensionPos)) {
|
|
195
|
+
if (!/^[A-Z0-9]$/i.test(e.key)) {
|
|
196
|
+
e.preventDefault()
|
|
197
|
+
return
|
|
307
198
|
}
|
|
199
|
+
return
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Règle 3 : slash automatique à position 3 (index 18)
|
|
203
|
+
if (extensionPos === 3) {
|
|
204
|
+
e.preventDefault()
|
|
205
|
+
const before = codeBudgetaire.value.slice(0, position)
|
|
206
|
+
const after = codeBudgetaire.value.slice(position)
|
|
207
|
+
codeBudgetaire.value = before + '/' + after
|
|
208
|
+
nextTick(() => {
|
|
209
|
+
input.selectionStart = input.selectionEnd = position + 1
|
|
210
|
+
})
|
|
211
|
+
return
|
|
212
|
+
}
|
|
308
213
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
const valeurFormatee = codeBudgetaire.value.trim().toUpperCase()
|
|
214
|
+
// Tout autre cas = bloqué
|
|
215
|
+
e.preventDefault()
|
|
216
|
+
}
|
|
314
217
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
return codeItem.trim().toUpperCase() === valeurFormatee
|
|
318
|
-
})
|
|
218
|
+
const formaterCodeBudgetaire = (valeur: string): string => {
|
|
219
|
+
if (!valeur) return ''
|
|
319
220
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
221
|
+
const upper = valeur.toUpperCase().replace(/[^A-Z0-9/]/g, '')
|
|
222
|
+
const chiffres = upper.replace(/[^0-9]/g, '').slice(0, 12)
|
|
223
|
+
|
|
224
|
+
let base = ''
|
|
225
|
+
if (chiffres.length > 0) base += chiffres.slice(0, 3)
|
|
226
|
+
if (chiffres.length > 3) base += '-' + chiffres.slice(3, 4)
|
|
227
|
+
if (chiffres.length > 4) base += '-' + chiffres.slice(4, 9)
|
|
228
|
+
if (chiffres.length > 9) base += '-' + chiffres.slice(9, 12)
|
|
229
|
+
|
|
230
|
+
if (!activerExtension || base.length < 15) return base
|
|
231
|
+
|
|
232
|
+
const reste = upper.slice(chiffres.length).replace(/[^A-Z0-9/]/gi, '')
|
|
233
|
+
|
|
234
|
+
// Extraire les 7 premiers caractères restants pour l’extension
|
|
235
|
+
let ext = reste.slice(0, 7).split('')
|
|
236
|
+
|
|
237
|
+
// Ne garder que le premier slash s’il est à l’index 0 ou 3
|
|
238
|
+
ext = ext.filter((c, i) => {
|
|
239
|
+
if (c !== '/') return true
|
|
240
|
+
return i === 0 || i === 3
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
// Enlever les slash non autorisés
|
|
244
|
+
ext = ext.map((c, i) => {
|
|
245
|
+
if (c === '/' && i !== 0 && i !== 3) return ''
|
|
246
|
+
if (c !== '/' && !/^[A-Z0-9]$/i.test(c)) return ''
|
|
247
|
+
return c
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
// Forcer le slash à la 4e position
|
|
251
|
+
if (ext.length > 3) {
|
|
252
|
+
ext[3] = '/'
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Réduire à 7 caractères
|
|
256
|
+
ext = ext.slice(0, 7)
|
|
257
|
+
|
|
258
|
+
return (base + ext.join('')).slice(0, 22)
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const gererPaste = (e: ClipboardEvent) => {
|
|
262
|
+
e.preventDefault()
|
|
263
|
+
const clipboardData = e.clipboardData
|
|
264
|
+
if (!clipboardData) return
|
|
265
|
+
const pasted = clipboardData.getData('text') || ''
|
|
266
|
+
codeBudgetaire.value = formaterCodeBudgetaire(pasted)
|
|
267
|
+
|
|
268
|
+
setTimeout(() => {
|
|
269
|
+
const input = e.target as HTMLInputElement
|
|
270
|
+
input.selectionStart = input.selectionEnd = codeBudgetaire.value.length
|
|
271
|
+
}, 0)
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const sauvegarder = () => {
|
|
275
|
+
codeBudgetaire.value = formaterCodeBudgetaire(codeBudgetaire.value)
|
|
276
|
+
|
|
277
|
+
if (!estValideComplet.value) return
|
|
278
|
+
if (codeBudgetaire.value === derniereValeurSauvegardee.value) return
|
|
279
|
+
|
|
280
|
+
const codeNormalise = codeBudgetaire.value.trim().toUpperCase()
|
|
281
|
+
|
|
282
|
+
const existe = props.codeBudgetairesProp.some(item => {
|
|
283
|
+
const code = typeof item === 'string' ? item : item[0]
|
|
284
|
+
return code.trim().toUpperCase() === codeNormalise
|
|
285
|
+
})
|
|
286
|
+
|
|
287
|
+
if (!existe) {
|
|
288
|
+
const nouvelleListe = [...props.codeBudgetairesProp, codeBudgetaire.value]
|
|
289
|
+
emit('update:codeBudgetairesProp', nouvelleListe)
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
derniereValeurSauvegardee.value = codeBudgetaire.value
|
|
293
|
+
emit('update:modelValue', codeBudgetaire.value)
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const extraireCode = (val: unknown): string => {
|
|
297
|
+
if (val == null) return ''
|
|
298
|
+
if (typeof val === 'string') return val
|
|
299
|
+
|
|
300
|
+
// Cas où Vuetify enverrait { code, label }
|
|
301
|
+
if (typeof val === 'object' && 'code' in (val as Record<string, unknown>)) {
|
|
302
|
+
const obj = val as { code?: unknown }
|
|
303
|
+
return typeof obj.code === 'string' ? obj.code : String(obj.code ?? '')
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return String(val)
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const gererChangement = (val: unknown) => {
|
|
310
|
+
const code = extraireCode(val)
|
|
311
|
+
codeBudgetaire.value = formaterCodeBudgetaire(code)
|
|
312
|
+
|
|
313
|
+
const valeurFormatee = codeBudgetaire.value.trim().toUpperCase()
|
|
314
|
+
|
|
315
|
+
const estDansListe = props.codeBudgetairesProp.some(item => {
|
|
316
|
+
const codeItem = typeof item === 'string' ? item : item[0]
|
|
317
|
+
return codeItem.trim().toUpperCase() === valeurFormatee
|
|
318
|
+
})
|
|
319
|
+
|
|
320
|
+
if (
|
|
321
|
+
estDansListe &&
|
|
322
|
+
valeurFormatee !== (derniereValeurSauvegardee.value ?? '').toUpperCase() &&
|
|
323
|
+
estValideComplet.value
|
|
324
|
+
) {
|
|
325
|
+
sauvegarder()
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
328
|
|
|
329
329
|
watch(
|
|
330
330
|
() => codeBudgetaire.value,
|
package/composants/csqcDate.vue
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<v-date-input
|
|
3
3
|
:model-value="dateInterne"
|
|
4
|
-
|
|
4
|
+
bg-color="white"
|
|
5
|
+
color="primary"
|
|
5
6
|
input-format="yyyy-MM-dd"
|
|
6
7
|
variant="outlined"
|
|
7
8
|
prepend-icon=""
|
|
8
9
|
prepend-inner-icon="$calendar"
|
|
9
10
|
density="comfortable"
|
|
11
|
+
:picker-props="{ color: 'accent' }"
|
|
12
|
+
v-bind="$attrs"
|
|
10
13
|
@update:model-value="choixUtilisateur"
|
|
11
14
|
/>
|
|
12
15
|
</template>
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<v-dialog
|
|
3
3
|
v-model="dialog"
|
|
4
|
-
v-bind="$attrs"
|
|
5
4
|
class="pa-0 ma-0"
|
|
6
5
|
:width="largeur"
|
|
7
6
|
:fullscreen="display.xs.value"
|
|
8
7
|
max-width="650"
|
|
9
8
|
:persistent="props.persistant"
|
|
9
|
+
v-bind="$attrs"
|
|
10
10
|
@keydown.esc="!persistant ? annuler : ''"
|
|
11
11
|
@click:outside="!persistant ? annuler : ''"
|
|
12
12
|
>
|
|
@@ -16,12 +16,13 @@
|
|
|
16
16
|
icon="mdi-close"
|
|
17
17
|
variant="text"
|
|
18
18
|
class="position-absolute iconeHover"
|
|
19
|
-
|
|
19
|
+
color="primary"
|
|
20
|
+
style="right: 5px; top: 5px"
|
|
20
21
|
@click="annuler"
|
|
21
22
|
></v-btn>
|
|
22
23
|
|
|
23
24
|
<v-card-title
|
|
24
|
-
class="pa-0 ma-0 pb-6"
|
|
25
|
+
class="pa-0 ma-0 pb-6 headline"
|
|
25
26
|
style="font-size: 24px; white-space: normal; word-break: break-word"
|
|
26
27
|
>
|
|
27
28
|
<slot name="titre"></slot>
|
|
@@ -49,7 +50,7 @@
|
|
|
49
50
|
<v-btn
|
|
50
51
|
v-if="btnOk"
|
|
51
52
|
class="Gouttiere"
|
|
52
|
-
color="primary"
|
|
53
|
+
:color="props.estDialogueAlerte ? 'rouge' : 'primary'"
|
|
53
54
|
:loading="operationEnCours"
|
|
54
55
|
:disabled="btnOkDesactiver"
|
|
55
56
|
variant="flat"
|
|
@@ -79,6 +80,7 @@
|
|
|
79
80
|
btnOkTexte: { type: String, default: '' },
|
|
80
81
|
titre: { type: String, default: '' },
|
|
81
82
|
btnOkDesactiver: { type: Boolean, default: false },
|
|
83
|
+
estDialogueAlerte: { type: Boolean, default: false },
|
|
82
84
|
})
|
|
83
85
|
|
|
84
86
|
// Déclaration des événements émis
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
<div class="editor">
|
|
3
3
|
<Editor
|
|
4
4
|
v-if="editorReady"
|
|
5
|
-
v-bind="$attrs"
|
|
6
5
|
v-model="editorValue"
|
|
7
6
|
:init="initOptions"
|
|
8
7
|
:disabled="desactiver"
|
|
9
8
|
license-key="gpl"
|
|
9
|
+
v-bind="$attrs"
|
|
10
10
|
@blur="onBlur"
|
|
11
11
|
@keydown="onUserActivity"
|
|
12
12
|
@change="onUserActivity"
|