codevdesign 2.0.18 → 2.0.20

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.
@@ -1,206 +1,206 @@
1
- <template>
2
- <v-toolbar
3
- color="#095797"
4
- height="72px"
5
- elevation="1"
6
- >
7
- <v-row
8
- class="pl-6 pr-6 align-center"
9
- no-gutters
10
- >
11
- <!-- Première colonne : Logo -->
12
- <v-col cols="auto">
13
- <a
14
- :href="href"
15
- :target="cssUrlValide ? '_blank' : undefined"
16
- :rel="cssUrlValide ? 'noopener noreferrer' : undefined"
17
- >
18
- <!-- Placeholder (même taille) pendant la décision -->
19
- <div
20
- v-if="!ready"
21
- class="logo-placeholder"
22
- ></div>
23
- <!-- On ne rend l'image qu'une fois la source choisie -->
24
- <img
25
- v-else
26
- id="pivImage"
27
- class="logo-img"
28
- :src="currentSrc!"
29
- :alt="$t('csqc.pivFooter.logoAlt')"
30
- decoding="async"
31
- loading="eager"
32
- @error="ErreurLogo"
33
- />
34
- </a>
35
- </v-col>
36
-
37
- <!-- Colonne pour le nom de l'application (Pour le mode desktop) -->
38
- <v-col
39
- v-if="!estMobile"
40
- class="d-flex justify-center"
41
- >
42
- <v-app-bar-title
43
- class="pl-12 ml-12"
44
- style="font-size: 16px !important"
45
- >
46
- {{ formulaireNom }}
47
- </v-app-bar-title>
48
- </v-col>
49
-
50
- <!-- Colonne pour le bouton de langue et icône d'aide -->
51
- <v-col class="d-none d-flex justify-end">
52
- <!-- langue -->
53
- <v-btn
54
- v-if="props.estVisibleLangue"
55
- variant="text"
56
- @click="enregistrerLangue()"
57
- >{{ $t('csqc.pivEntete.langue') }}
58
- </v-btn>
59
-
60
- <!-- icône d'aide si dispo -->
61
- <v-btn
62
- v-if="aideUrl"
63
- icon="mdi-help-circle-outline"
64
- :href="aideUrl"
65
- target="_blank"
66
- rel="noopener noreferrer"
67
- style="margin-top: -6px"
68
- >
69
- </v-btn>
70
-
71
- <slot name="droite"></slot>
72
- </v-col>
73
-
74
- <!-- Colonne pour le nom de l'application (Pour le mode mobile) -->
75
- <v-col
76
- v-if="props.estMobile"
77
- cols="12"
78
- >
79
- <v-app-bar-title style="font-size: 16px !important">
80
- {{ formulaireNom }}
81
- </v-app-bar-title>
82
- </v-col>
83
- </v-row>
84
- </v-toolbar>
85
- </template>
86
-
87
- <script setup lang="ts">
88
- import { ref, watch, computed } from 'vue'
89
- import { useLocale } from 'vuetify'
90
- import { useI18n } from 'vue-i18n'
91
-
92
- const { current } = useLocale()
93
- const props = defineProps({
94
- estMobile: { type: Boolean, default: false },
95
- estVisibleLangue: { type: Boolean, default: true },
96
- urlBase: { type: String, required: true },
97
- aideUrl: { type: String, default: '' },
98
- cssUrl: { type: String, default: '' },
99
- logoUrl: { type: String, default: '' },
100
- lienLogo: { type: String, default: '' },
101
- formulaireId: { type: Number, default: 0 },
102
- formulaireNom: { type: String, default: '' },
103
- })
104
- const emit = defineEmits(['changementLangue'])
105
- const { t } = useI18n()
106
-
107
- const FALLBACK = '/portail/images/QUEBEC_blanc.svg'
108
- const currentSrc = ref<string | null>(null) // pas d'image tant que null
109
- const ready = ref(false)
110
-
111
- const formulaireNom = computed(() => {
112
- return props.formulaireNom || t('nom_application')
113
- })
114
-
115
- const href = computed(() => (props.cssUrl?.trim() ? props.cssUrl.trim() : '/'))
116
- const cssUrlValide = computed(() => /^https?:\/\//i.test(href.value))
117
-
118
- let loadToken = 0 // ← identifiant de “requête” pour annuler logiquement
119
-
120
- // Sur changement de l’URL du logo, on tente de le charger, sinon fallback apres 3.5 secs
121
- watch(
122
- () => props.logoUrl,
123
- async (nouvelle, ancienne) => {
124
- const url = (nouvelle ?? '').trim()
125
-
126
- // même URL → ne rien faire
127
- if (url === (ancienne ?? '').trim() && currentSrc.value !== null) return
128
-
129
- // pas d’URL → fallback immédiat
130
- if (!url) {
131
- currentSrc.value = FALLBACK
132
- ready.value = true
133
- return
134
- }
135
-
136
- // nouvelle tentative (avec “annulation logique”)
137
- const token = ++loadToken
138
- ready.value = false
139
- const ok = await loadWithTimeout(url, 3500)
140
- if (token !== loadToken) return // une nouvelle tentative a démarré entre-temps
141
-
142
- currentSrc.value = ok ? url : FALLBACK
143
- ready.value = true
144
- },
145
- { immediate: true },
146
- )
147
-
148
- // Charge une image avec un timeout
149
- function loadWithTimeout(url: string, timeoutMs: number): Promise<boolean> {
150
- return new Promise<boolean>(resolve => {
151
- const img = new Image()
152
- const timer = setTimeout(() => {
153
- // trop long → on abandonne
154
- img.src = '' // stoppe le chargement
155
- resolve(false)
156
- }, timeoutMs)
157
-
158
- img.onload = () => {
159
- clearTimeout(timer)
160
- resolve(true)
161
- }
162
- img.onerror = () => {
163
- clearTimeout(timer)
164
- resolve(false)
165
- }
166
- img.src = url
167
- })
168
- }
169
-
170
- // Si l'image choisie a un problème, switch sur le fallback
171
- function ErreurLogo() {
172
- if (currentSrc.value !== FALLBACK) currentSrc.value = FALLBACK
173
- }
174
-
175
- const enregistrerLangue = (): void => {
176
- const langueDispo: string = current.value === 'fr' ? 'en' : 'fr'
177
- let returnUrl = window.location.pathname + window.location.search
178
- if (import.meta.env.MODE === 'development') {
179
- returnUrl = '/'
180
- }
181
- window.location.href =
182
- props.urlBase + `/Traducteur/SetLanguage?culture=${langueDispo}&returnUrl=${encodeURIComponent(returnUrl)}`
183
- emit('changementLangue')
184
- }
185
- </script>
186
-
187
- <style scoped>
188
- .container {
189
- max-width: none !important;
190
- }
191
- .theme--light.v-app-bar.v-toolbar.v-sheet {
192
- background: rgb(var(--v-theme-primary));
193
-
194
- color: rgb(var(--v-theme-blanc));
195
- }
196
- .logo-placeholder {
197
- height: 72px;
198
- width: 180px;
199
- }
200
- .logo-img {
201
- display: block;
202
- height: 72px;
203
- opacity: 1;
204
- transition: opacity 0.15s;
205
- }
206
- </style>
1
+ <template>
2
+ <v-toolbar
3
+ color="#095797"
4
+ height="72px"
5
+ elevation="1"
6
+ >
7
+ <v-row
8
+ class="pl-6 pr-6 align-center"
9
+ no-gutters
10
+ >
11
+ <!-- Première colonne : Logo -->
12
+ <v-col cols="auto">
13
+ <a
14
+ :href="href"
15
+ :target="cssUrlValide ? '_blank' : undefined"
16
+ :rel="cssUrlValide ? 'noopener noreferrer' : undefined"
17
+ >
18
+ <!-- Placeholder (même taille) pendant la décision -->
19
+ <div
20
+ v-if="!ready"
21
+ class="logo-placeholder"
22
+ ></div>
23
+ <!-- On ne rend l'image qu'une fois la source choisie -->
24
+ <img
25
+ v-else
26
+ id="pivImage"
27
+ class="logo-img"
28
+ :src="currentSrc!"
29
+ :alt="$t('csqc.pivFooter.logoAlt')"
30
+ decoding="async"
31
+ loading="eager"
32
+ @error="ErreurLogo"
33
+ />
34
+ </a>
35
+ </v-col>
36
+
37
+ <!-- Colonne pour le nom de l'application (Pour le mode desktop) -->
38
+ <v-col
39
+ v-if="!estMobile"
40
+ class="d-flex justify-center"
41
+ >
42
+ <v-app-bar-title
43
+ class="pl-12 ml-12"
44
+ style="font-size: 16px !important"
45
+ >
46
+ {{ formulaireNom }}
47
+ </v-app-bar-title>
48
+ </v-col>
49
+
50
+ <!-- Colonne pour le bouton de langue et icône d'aide -->
51
+ <v-col class="d-none d-flex justify-end">
52
+ <!-- langue -->
53
+ <v-btn
54
+ v-if="props.estVisibleLangue"
55
+ variant="text"
56
+ @click="enregistrerLangue()"
57
+ >{{ $t('csqc.pivEntete.langue') }}
58
+ </v-btn>
59
+
60
+ <!-- icône d'aide si dispo -->
61
+ <v-btn
62
+ v-if="aideUrl"
63
+ icon="mdi-help-circle-outline"
64
+ :href="aideUrl"
65
+ target="_blank"
66
+ rel="noopener noreferrer"
67
+ style="margin-top: -6px"
68
+ >
69
+ </v-btn>
70
+
71
+ <slot name="droite"></slot>
72
+ </v-col>
73
+
74
+ <!-- Colonne pour le nom de l'application (Pour le mode mobile) -->
75
+ <v-col
76
+ v-if="props.estMobile"
77
+ cols="12"
78
+ >
79
+ <v-app-bar-title style="font-size: 16px !important">
80
+ {{ formulaireNom }}
81
+ </v-app-bar-title>
82
+ </v-col>
83
+ </v-row>
84
+ </v-toolbar>
85
+ </template>
86
+
87
+ <script setup lang="ts">
88
+ import { ref, watch, computed } from 'vue'
89
+ import { useLocale } from 'vuetify'
90
+ import { useI18n } from 'vue-i18n'
91
+
92
+ const { current } = useLocale()
93
+ const props = defineProps({
94
+ estMobile: { type: Boolean, default: false },
95
+ estVisibleLangue: { type: Boolean, default: true },
96
+ urlBase: { type: String, required: true },
97
+ aideUrl: { type: String, default: '' },
98
+ cssUrl: { type: String, default: '' },
99
+ logoUrl: { type: String, default: '' },
100
+ lienLogo: { type: String, default: '' },
101
+ formulaireId: { type: Number, default: 0 },
102
+ formulaireNom: { type: String, default: '' },
103
+ })
104
+ const emit = defineEmits(['changementLangue'])
105
+ const { t } = useI18n()
106
+
107
+ const FALLBACK = '/portail/images/QUEBEC_blanc.svg'
108
+ const currentSrc = ref<string | null>(null) // pas d'image tant que null
109
+ const ready = ref(false)
110
+
111
+ const formulaireNom = computed(() => {
112
+ return props.formulaireNom || t('nom_application')
113
+ })
114
+
115
+ const href = computed(() => (props.cssUrl?.trim() ? props.cssUrl.trim() : '/'))
116
+ const cssUrlValide = computed(() => /^https?:\/\//i.test(href.value))
117
+
118
+ let loadToken = 0 // ← identifiant de “requête” pour annuler logiquement
119
+
120
+ // Sur changement de l’URL du logo, on tente de le charger, sinon fallback apres 3.5 secs
121
+ watch(
122
+ () => props.logoUrl,
123
+ async (nouvelle, ancienne) => {
124
+ const url = (nouvelle ?? '').trim()
125
+
126
+ // même URL → ne rien faire
127
+ if (url === (ancienne ?? '').trim() && currentSrc.value !== null) return
128
+
129
+ // pas d’URL → fallback immédiat
130
+ if (!url) {
131
+ currentSrc.value = FALLBACK
132
+ ready.value = true
133
+ return
134
+ }
135
+
136
+ // nouvelle tentative (avec “annulation logique”)
137
+ const token = ++loadToken
138
+ ready.value = false
139
+ const ok = await loadWithTimeout(url, 3500)
140
+ if (token !== loadToken) return // une nouvelle tentative a démarré entre-temps
141
+
142
+ currentSrc.value = ok ? url : FALLBACK
143
+ ready.value = true
144
+ },
145
+ { immediate: true },
146
+ )
147
+
148
+ // Charge une image avec un timeout
149
+ function loadWithTimeout(url: string, timeoutMs: number): Promise<boolean> {
150
+ return new Promise<boolean>(resolve => {
151
+ const img = new Image()
152
+ const timer = setTimeout(() => {
153
+ // trop long → on abandonne
154
+ img.src = '' // stoppe le chargement
155
+ resolve(false)
156
+ }, timeoutMs)
157
+
158
+ img.onload = () => {
159
+ clearTimeout(timer)
160
+ resolve(true)
161
+ }
162
+ img.onerror = () => {
163
+ clearTimeout(timer)
164
+ resolve(false)
165
+ }
166
+ img.src = url
167
+ })
168
+ }
169
+
170
+ // Si l'image choisie a un problème, switch sur le fallback
171
+ function ErreurLogo() {
172
+ if (currentSrc.value !== FALLBACK) currentSrc.value = FALLBACK
173
+ }
174
+
175
+ const enregistrerLangue = (): void => {
176
+ const langueDispo: string = current.value === 'fr' ? 'en' : 'fr'
177
+ let returnUrl = window.location.pathname + window.location.search
178
+ if (import.meta.env.MODE === 'development') {
179
+ returnUrl = '/'
180
+ }
181
+ window.location.href =
182
+ props.urlBase + `/Traducteur/SetLanguage?culture=${langueDispo}&returnUrl=${encodeURIComponent(returnUrl)}`
183
+ emit('changementLangue')
184
+ }
185
+ </script>
186
+
187
+ <style scoped>
188
+ .container {
189
+ max-width: none !important;
190
+ }
191
+ .theme--light.v-app-bar.v-toolbar.v-sheet {
192
+ background: rgb(var(--v-theme-primary));
193
+
194
+ color: rgb(var(--v-theme-blanc));
195
+ }
196
+ .logo-placeholder {
197
+ height: 72px;
198
+ width: 180px;
199
+ }
200
+ .logo-img {
201
+ display: block;
202
+ height: 72px;
203
+ opacity: 1;
204
+ transition: opacity 0.15s;
205
+ }
206
+ </style>
@@ -1,95 +1,95 @@
1
- <template>
2
- <footer>
3
- <v-row>
4
- <!-- slot gauche -->
5
- <v-col cols="3">
6
- <slot name="gauche" />
7
- </v-col>
8
-
9
- <!-- colonne centrale pour logo Quebec et versions -->
10
- <v-col cols="6">
11
- <div class="footer-content">
12
- <a href="https://quebec.ca">
13
- <img
14
- id="logoFooter"
15
- alt="Gouvernement du Québec."
16
- src="/images/QUEBEC_couleur.svg"
17
- width="117"
18
- height="35"
19
- />
20
- </a>
21
- <div>
22
- <small>
23
- <a
24
- href="http://www.droitauteur.gouv.qc.ca/copyright.php"
25
- target="_blank"
26
- >© Gouvernement du Québec {{ anneeEnCours }}
27
- </a>
28
-
29
- <a
30
- v-if="props.version"
31
- :href="props.lien"
32
- target="_blank"
33
- ><br />
34
- version <span v-html="props.version"
35
- /></a>
36
- </small>
37
- </div>
38
- </div>
39
- </v-col>
40
-
41
- <!-- slot droite -->
42
- <v-col cols="3">
43
- <slot name="droite" />
44
- </v-col>
45
- </v-row>
46
- </footer>
47
- </template>
48
-
49
- <script setup lang="ts">
50
- import { computed } from 'vue'
51
- import { useTheme } from 'vuetify'
52
-
53
- const props = defineProps<{
54
- version?: string
55
- lien?: string
56
- }>()
57
-
58
- const theme = useTheme()
59
-
60
- // dark theme... trouble de lien en prod avec le computed
61
- /* const logoSrc = computed(
62
- () =>
63
- `${import.meta.env.BASE_URL}/images/${theme.global.current.value.dark ? 'QUEBEC_blanc.svg' : 'QUEBEC_couleur.svg'}`,
64
- )*/
65
-
66
- const anneeEnCours = computed<number>(() => {
67
- return new Date().getFullYear()
68
- })
69
- </script>
70
-
71
- <style scoped>
72
- footer {
73
- align-items: center; /* Centrer verticalement */
74
- display: flex;
75
- height: 100px; /* Ajuster la hauteur du footer */
76
- justify-content: center; /* Centrer horizontalement */
77
- text-align: center; /* Centrer le texte à l'intérieur des éléments */
78
- }
79
-
80
- .footer-content {
81
- align-items: center; /* Centrer horizontalement à l'intérieur de .footer-content */
82
- display: flex;
83
- flex-direction: column; /* Disposer les éléments les uns sous les autres */
84
- justify-content: center; /* Centrer verticalement à l'intérieur de .footer-content */
85
- }
86
-
87
- footer a {
88
- color: #095797;
89
- text-decoration: none;
90
- }
91
-
92
- footer small {
93
- margin-top: 10px; /* Ajouter de l'espace entre l'image et le texte */
94
- }
95
- </style>
1
+ <template>
2
+ <footer>
3
+ <v-row>
4
+ <!-- slot gauche -->
5
+ <v-col cols="3">
6
+ <slot name="gauche" />
7
+ </v-col>
8
+
9
+ <!-- colonne centrale pour logo Quebec et versions -->
10
+ <v-col cols="6">
11
+ <div class="footer-content">
12
+ <a href="https://quebec.ca">
13
+ <img
14
+ id="logoFooter"
15
+ alt="Gouvernement du Québec."
16
+ src="/images/QUEBEC_couleur.svg"
17
+ width="117"
18
+ height="35"
19
+ />
20
+ </a>
21
+ <div>
22
+ <small>
23
+ <a
24
+ href="http://www.droitauteur.gouv.qc.ca/copyright.php"
25
+ target="_blank"
26
+ >© Gouvernement du Québec {{ anneeEnCours }}
27
+ </a>
28
+
29
+ <a
30
+ v-if="props.version"
31
+ :href="props.lien"
32
+ target="_blank"
33
+ ><br />
34
+ version <span v-html="props.version"
35
+ /></a>
36
+ </small>
37
+ </div>
38
+ </div>
39
+ </v-col>
40
+
41
+ <!-- slot droite -->
42
+ <v-col cols="3">
43
+ <slot name="droite" />
44
+ </v-col>
45
+ </v-row>
46
+ </footer>
47
+ </template>
48
+
49
+ <script setup lang="ts">
50
+ import { computed } from 'vue'
51
+ import { useTheme } from 'vuetify'
52
+
53
+ const props = defineProps<{
54
+ version?: string
55
+ lien?: string
56
+ }>()
57
+
58
+ const theme = useTheme()
59
+
60
+ // dark theme... trouble de lien en prod avec le computed
61
+ /* const logoSrc = computed(
62
+ () =>
63
+ `${import.meta.env.BASE_URL}/images/${theme.global.current.value.dark ? 'QUEBEC_blanc.svg' : 'QUEBEC_couleur.svg'}`,
64
+ )*/
65
+
66
+ const anneeEnCours = computed<number>(() => {
67
+ return new Date().getFullYear()
68
+ })
69
+ </script>
70
+
71
+ <style scoped>
72
+ footer {
73
+ align-items: center; /* Centrer verticalement */
74
+ display: flex;
75
+ height: 100px; /* Ajuster la hauteur du footer */
76
+ justify-content: center; /* Centrer horizontalement */
77
+ text-align: center; /* Centrer le texte à l'intérieur des éléments */
78
+ }
79
+
80
+ .footer-content {
81
+ align-items: center; /* Centrer horizontalement à l'intérieur de .footer-content */
82
+ display: flex;
83
+ flex-direction: column; /* Disposer les éléments les uns sous les autres */
84
+ justify-content: center; /* Centrer verticalement à l'intérieur de .footer-content */
85
+ }
86
+
87
+ footer a {
88
+ color: #095797;
89
+ text-decoration: none;
90
+ }
91
+
92
+ footer small {
93
+ margin-top: 10px; /* Ajouter de l'espace entre l'image et le texte */
94
+ }
95
+ </style>
package/editeur.ts CHANGED
@@ -1 +1 @@
1
- export { default as csqcEditeurTexteRiche } from './composants/csqcEditeurTexteRiche.vue'
1
+ export { default as csqcEditeurTexteRiche } from './composants/csqcEditeurTexteRiche.vue'
package/importCSV.ts CHANGED
@@ -1 +1 @@
1
- export { default as csqcImportCSV } from './composants/csqcImportCSV.vue'
1
+ export { default as csqcImportCSV } from './composants/csqcImportCSV.vue'