@cnamts/synapse 1.0.20 → 1.0.21
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/dist/{DateFilter-XURUmpMl.js → DateFilter-uN8OURoP.js} +1 -1
- package/dist/{NumberFilter-BZc0O8wV.js → NumberFilter-sm1dQNQi.js} +1 -1
- package/dist/{PeriodFilter-ZNdXcl3p.js → PeriodFilter-Cklsxnh9.js} +1 -1
- package/dist/{SelectFilter-DshYU5OK.js → SelectFilter-CWefj27Z.js} +1 -1
- package/dist/{TextFilter-D_c5dRPl.js → TextFilter-Ddyj885L.js} +1 -1
- package/dist/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.d.ts +160 -0
- package/dist/components/Customs/SyCheckBoxGroup/locales.d.ts +3 -0
- package/dist/components/Customs/SyCheckBoxGroup/types.d.ts +10 -0
- package/dist/components/Customs/SyCheckbox/SyCheckbox.d.ts +1545 -2
- package/dist/components/Customs/SyRadioGroup/SyRadioGroup.d.ts +1495 -2
- package/dist/components/DeclarationAccessibilityPage/DeclarationAccessibilityPage.d.ts +60 -0
- package/dist/components/ErrorPage/ErrorPage.d.ts +1 -12
- package/dist/components/ErrorPage/locales.d.ts +18 -3
- package/dist/components/FileUpload/FileUpload.d.ts +2 -0
- package/dist/components/MaintenancePage/locales.d.ts +18 -2
- package/dist/components/NotFoundPage/locales.d.ts +20 -4
- package/dist/components/StatusPage/StatusPage.d.ts +39 -0
- package/dist/components/UploadWorkflow/UploadWorkflow.d.ts +13 -3
- package/dist/components/index.d.ts +3 -0
- package/dist/design-system-v3.js +126 -123
- package/dist/design-system-v3.umd.cjs +163 -163
- package/dist/{main-CuI6xaPq.js → main-CWniLr0s.js} +15191 -14668
- package/dist/style.css +1 -1
- package/dist/utils/theme/index.d.ts +6 -0
- package/package.json +7 -4
- package/src/components/ContextualMenu/ContextualMenu.stories.ts +0 -3
- package/src/components/ContextualMenu/accessibilite/Accessibility.mdx +67 -11
- package/src/components/CookieBanner/CookieBanner.stories.ts +11 -20
- package/src/components/CookieBanner/CookieBanner.vue +20 -5
- package/src/components/CookieBanner/accessibilite/Accessibility.mdx +67 -11
- package/src/components/CookieBanner/tests/CookieBanner.spec.ts +48 -4
- package/src/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.mdx +32 -0
- package/src/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.stories.ts +856 -0
- package/src/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.vue +334 -0
- package/src/components/Customs/SyCheckBoxGroup/accessibilite/Accessibility.mdx +243 -0
- package/src/components/Customs/SyCheckBoxGroup/locales.ts +3 -0
- package/src/components/Customs/SyCheckBoxGroup/tests/SyCheckBoxGroup.a11y.spec.ts +30 -0
- package/src/components/Customs/SyCheckBoxGroup/tests/SyCheckBoxGroup.spec.ts +152 -0
- package/src/components/Customs/SyCheckBoxGroup/types.ts +10 -0
- package/src/components/Customs/SyCheckbox/SyCheckbox.vue +16 -27
- package/src/components/Customs/SyCheckbox/accessibilite/Accessibility.mdx +1 -1
- package/src/components/Customs/SyForm/SyForm.a11y.spec.ts +1 -1
- package/src/components/Customs/SyRadioGroup/SyRadioGroup.vue +16 -43
- package/src/components/DatePicker/CalendarMode/DatePicker.vue +35 -11
- package/src/components/DatePicker/ComplexDatePicker/ComplexDatePicker.stories.ts +43 -2
- package/src/components/DatePicker/DateTextInput/DateTextInput.vue +48 -21
- package/src/components/DatePicker/DateTextInput/NoCalendar.stories.ts +98 -0
- package/src/components/DeclarationAccessibilityPage/DeclarationAccessibilityPage.mdx +83 -0
- package/src/components/DeclarationAccessibilityPage/DeclarationAccessibilityPage.stories.ts +502 -0
- package/src/components/DeclarationAccessibilityPage/DeclarationAccessibilityPage.vue +428 -0
- package/src/components/DeclarationAccessibilityPage/accessibilite/Accessibility.mdx +75 -0
- package/src/components/DeclarationAccessibilityPage/tests/DeclarationAccessibilityPage.a11y.spec.ts +53 -0
- package/src/components/DeclarationAccessibilityPage/tests/DeclarationAccessibilityPage.spec.ts +59 -0
- package/src/components/DiacriticPicker/DiacriticPicker.vue +20 -1
- package/src/components/ErrorPage/ErrorPage.mdx +6 -16
- package/src/components/ErrorPage/ErrorPage.stories.ts +16 -87
- package/src/components/ErrorPage/ErrorPage.vue +38 -125
- package/src/components/ErrorPage/accessibilite/Accessibility.mdx +68 -6
- package/src/components/ErrorPage/assets/error-ap.svg +1774 -0
- package/src/components/ErrorPage/locales.ts +21 -3
- package/src/components/ErrorPage/tests/ErrorPage.a11y.spec.ts +5 -13
- package/src/components/ErrorPage/tests/ErrorPage.spec.ts +2 -41
- package/src/components/ErrorPage/tests/__snapshots__/ErrorPage.spec.ts.snap +8 -266
- package/src/components/FileUpload/FileUpload.vue +5 -0
- package/src/components/FooterBar/FooterBar.stories.ts +18 -14
- package/src/components/FooterBar/defaultSocialMediaLinks.ts +6 -4
- package/src/components/MaintenancePage/MaintenancePage.mdx +1 -1
- package/src/components/MaintenancePage/MaintenancePage.vue +15 -7
- package/src/components/MaintenancePage/accessibilite/Accessibility.mdx +61 -6
- package/src/components/MaintenancePage/assets/maintenance-ap.svg +1718 -0
- package/src/components/MaintenancePage/locales.ts +24 -3
- package/src/components/MaintenancePage/tests/MaintenancePage.a11y.spec.ts +75 -3
- package/src/components/MaintenancePage/tests/MaintenancePage.spec.ts +42 -2
- package/src/components/MaintenancePage/tests/__snapshots__/MaintenancePage.spec.ts.snap +3 -2
- package/src/components/NotFoundPage/NotFoundPage.mdx +1 -1
- package/src/components/NotFoundPage/NotFoundPage.stories.ts +3 -3
- package/src/components/NotFoundPage/NotFoundPage.vue +16 -11
- package/src/components/NotFoundPage/accessibilite/Accessibility.mdx +78 -6
- package/src/components/NotFoundPage/assets/not-found-ap.svg +2061 -0
- package/src/components/NotFoundPage/locales.ts +24 -4
- package/src/components/NotFoundPage/tests/NotFoundPage.a11y.spec.ts +168 -4
- package/src/components/NotFoundPage/tests/NotFoundPage.spec.ts +100 -12
- package/src/components/NotFoundPage/tests/__snapshots__/NotFoundPage.spec.ts.snap +2 -2
- package/src/components/NotificationBar/NotificationBar.mdx +2 -2
- package/src/components/NotificationBar/accessibilite/Accessibility.mdx +68 -8
- package/src/components/PageContainer/tests/PageContainer.a11y.spec.ts +14 -7
- package/src/components/PhoneField/PhoneField.stories.ts +46 -38
- package/src/components/SocialMediaLinks/DefaultSocialMediaLinks.ts +6 -4
- package/src/components/SocialMediaLinks/SocialMediaLinks.mdx +7 -5
- package/src/components/SocialMediaLinks/SocialMediaLinks.stories.ts +17 -13
- package/src/components/SocialMediaLinks/SocialMediaLinks.vue +9 -1
- package/src/components/SocialMediaLinks/accessibilite/Accessibility.mdx +63 -11
- package/src/components/SocialMediaLinks/tests/DefaultSocialMediaLinks.spec.ts +5 -5
- package/src/components/SocialMediaLinks/tests/SocialMediaLinks.a11y.spec.ts +59 -0
- package/src/components/SocialMediaLinks/tests/SocialMediaLinks.spec.ts +9 -7
- package/src/components/StatusPage/StatusPage.mdx +22 -0
- package/src/components/StatusPage/StatusPage.stories.ts +193 -0
- package/src/components/StatusPage/StatusPage.vue +145 -0
- package/src/components/StatusPage/accessibilite/Accessibility.mdx +81 -0
- package/src/components/StatusPage/tests/StatusPage.a11y.spec.ts +29 -0
- package/src/components/StatusPage/tests/StatusPage.spec.ts +50 -0
- package/src/components/StatusPage/tests/__snapshots__/StatusPage.spec.ts.snap +270 -0
- package/src/components/TableToolbar/TableToolbar.stories.ts +6 -6
- package/src/components/TableToolbar/TableToolbar.vue +1 -1
- package/src/components/TableToolbar/tests/__snapshots__/TableToolbar.spec.ts.snap +0 -5
- package/src/components/UploadWorkflow/UploadWorkflow.mdx +11 -1
- package/src/components/UploadWorkflow/UploadWorkflow.stories.ts +107 -3
- package/src/components/UploadWorkflow/UploadWorkflow.vue +35 -24
- package/src/components/UploadWorkflow/tests/UploadWorkflow.spec.ts +48 -0
- package/src/components/UploadWorkflow/tests/__snapshots__/UploadWorkflow.spec.ts.snap +9 -5
- package/src/components/UploadWorkflow/useFileList.ts +7 -0
- package/src/components/index.ts +3 -0
- package/src/composables/rules/tests/useFieldValidation.spec.ts +39 -3
- package/src/composables/rules/useFieldValidation.ts +24 -9
- package/src/stories/Accessibilite/KitDePreAudit/Preaudit.mdx +7 -0
- package/src/utils/theme/index.ts +19 -0
- package/src/utils/theme/tests/useThemeLocales.spec.ts +245 -0
- package/dist/components/MaintenancePage/index.d.ts +0 -2
- package/src/components/Customs/SyPagination/tests/SyPagination.a11y.spec.ts +0 -27
- package/src/components/Customs/SyTabs/tests/SyTabs.a11y.spec.ts +0 -51
- package/src/components/DataListItem/tests/DataListItem.a11y.spec.ts +0 -31
- package/src/components/DatePicker/CalendarMode/tests/DatePicker.a11y.spec.ts +0 -27
- package/src/components/DatePicker/ComplexDatePicker/tests/ComplexDatePicker.a11y.spec.ts +0 -26
- package/src/components/DatePicker/DateTextInput/tests/DateTextInput.a11y.spec.ts +0 -27
- package/src/components/DownloadBtn/tests/DownloadBtn.a11y.spec.ts +0 -26
- package/src/components/ExternalLinks/tests/ExternalLinks.a11y.spec.ts +0 -39
- package/src/components/HeaderNavigationBar/tests/HeaderNavigationBar.a11y.spec.ts +0 -45
- package/src/components/HeaderToolbar/tests/HeaderToolbar.a11y.spec.ts +0 -25
- package/src/components/LunarCalendar/tests/LunarCalendar.a11y.spec.ts +0 -31
- package/src/components/MaintenancePage/index.ts +0 -3
- package/src/components/PageContainer/Accessibilite/AccessibilityGuide.mdx +0 -0
- package/src/components/PaginatedTable/tests/PaginatedTable.a11y.spec.ts +0 -43
- package/src/components/PhoneField/tests/PhoneField.a11y.spec.ts +0 -34
- /package/src/components/NotFoundPage/assets/{not-found.svg → not-found-cnam.svg} +0 -0
- /package/src/components/PageContainer/{Accessibilite → accessibilite}/Accessibility.mdx +0 -0
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
} from '@/composables/useCustomizableOptions'
|
|
5
5
|
import { useWidthable, type Widthable } from '@/composables/widthable'
|
|
6
6
|
import { isRequired } from '@/utils/rules/isRequired'
|
|
7
|
-
import { computed,
|
|
7
|
+
import { computed, ref, toRef } from 'vue'
|
|
8
8
|
import DialogBox from '../DialogBox/DialogBox.vue'
|
|
9
9
|
import FileList from '../FileList/FileList.vue'
|
|
10
10
|
import FilePreview from '../FilePreview/FilePreview.vue'
|
|
@@ -22,37 +22,35 @@
|
|
|
22
22
|
uploadList: UploadItem[]
|
|
23
23
|
sectionTitle?: string
|
|
24
24
|
showFilePreview?: boolean
|
|
25
|
+
infoText?: string
|
|
26
|
+
headingLevel?: number
|
|
25
27
|
locales?: typeof defaultLocales
|
|
26
28
|
}
|
|
27
29
|
>(),
|
|
28
30
|
{
|
|
29
31
|
sectionTitle: undefined,
|
|
30
32
|
showFilePreview: false,
|
|
33
|
+
infoText: '',
|
|
34
|
+
headingLevel: 4,
|
|
31
35
|
locales: () => defaultLocales,
|
|
32
36
|
},
|
|
33
37
|
)
|
|
34
38
|
|
|
35
39
|
const emits = defineEmits<{
|
|
36
40
|
(e: 'error', value: string[]): void
|
|
41
|
+
(e: 'preview', value: FileItem): void
|
|
37
42
|
(e: 'update:modelValue', value: SelectedFile[]): void
|
|
38
43
|
}>()
|
|
39
44
|
|
|
40
45
|
const selectedFiles = defineModel<SelectedFile[]>({
|
|
41
46
|
type: Array,
|
|
42
|
-
default:
|
|
47
|
+
default: () => [],
|
|
43
48
|
})
|
|
44
|
-
watch(
|
|
45
|
-
selectedFiles,
|
|
46
|
-
(value) => {
|
|
47
|
-
emits('update:modelValue', value)
|
|
48
|
-
},
|
|
49
|
-
{ deep: true },
|
|
50
|
-
)
|
|
51
49
|
|
|
52
50
|
const { widthStyles } = useWidthable(props)
|
|
53
51
|
const options = useCustomizableOptions(config, props)
|
|
54
52
|
|
|
55
|
-
const fileUpload = ref<typeof FileUpload
|
|
53
|
+
const fileUpload = ref<InstanceType<typeof FileUpload>>()
|
|
56
54
|
const { selectItems, selectedItem } = useFileUploadJourney(
|
|
57
55
|
toRef(props, 'uploadList'),
|
|
58
56
|
)
|
|
@@ -65,19 +63,21 @@
|
|
|
65
63
|
= useFileList(selectedFiles, toRef(props, 'uploadList'))
|
|
66
64
|
|
|
67
65
|
// handle FileList
|
|
68
|
-
|
|
66
|
+
const inlineSelectedItemId = ref<string | undefined>(undefined)
|
|
69
67
|
function uploadInline(item: FileItem) {
|
|
70
|
-
inlineSelectedItemId = item.id
|
|
68
|
+
inlineSelectedItemId.value = item.id
|
|
71
69
|
|
|
72
|
-
fileUpload.value
|
|
70
|
+
fileUpload.value?.openFileDialog()
|
|
73
71
|
}
|
|
74
72
|
function previewFile(file: FileItem & { file?: File }) {
|
|
73
|
+
emits('preview', file)
|
|
75
74
|
showPreviewDialog.value = true
|
|
76
75
|
fileToPreview.value = file.file
|
|
77
76
|
}
|
|
78
77
|
|
|
79
78
|
// handle FileUpload
|
|
80
79
|
const uploadedFiles = ref<File[]>([])
|
|
80
|
+
const uploadedFile = computed(() => uploadedFiles.value[0])
|
|
81
81
|
|
|
82
82
|
const showFileUpload = computed(
|
|
83
83
|
() => (
|
|
@@ -88,10 +88,10 @@
|
|
|
88
88
|
|
|
89
89
|
function fileSelected(files: File[]) {
|
|
90
90
|
const fileId
|
|
91
|
-
= inlineSelectedItemId ?? (props.uploadList.length === 1
|
|
91
|
+
= inlineSelectedItemId.value ?? (props.uploadList.length === 1
|
|
92
92
|
? props.uploadList[0]!.id
|
|
93
93
|
: undefined)
|
|
94
|
-
inlineSelectedItemId = undefined
|
|
94
|
+
inlineSelectedItemId.value = undefined
|
|
95
95
|
|
|
96
96
|
if (props.showFilePreview || fileId === undefined) {
|
|
97
97
|
showSelectDialog.value = true
|
|
@@ -105,22 +105,22 @@
|
|
|
105
105
|
|
|
106
106
|
function uploadError(errors: string[]) {
|
|
107
107
|
emits('error', errors)
|
|
108
|
-
if (!inlineSelectedItemId) {
|
|
108
|
+
if (!inlineSelectedItemId.value) {
|
|
109
109
|
return
|
|
110
110
|
}
|
|
111
|
-
setItemOnError(inlineSelectedItemId)
|
|
112
|
-
inlineSelectedItemId = undefined
|
|
111
|
+
setItemOnError(inlineSelectedItemId.value)
|
|
112
|
+
inlineSelectedItemId.value = undefined
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
// handle DialogBox
|
|
116
116
|
const showSelectDialog = ref(false)
|
|
117
117
|
|
|
118
118
|
function dialogConfirm() {
|
|
119
|
-
if (!selectedItem.value) {
|
|
119
|
+
if (!selectedItem.value || !uploadedFile.value) {
|
|
120
120
|
return
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
addOrReplaceFile(
|
|
123
|
+
addOrReplaceFile(uploadedFile.value, selectedItem.value)
|
|
124
124
|
|
|
125
125
|
showSelectDialog.value = false
|
|
126
126
|
selectedItem.value = undefined
|
|
@@ -137,9 +137,13 @@
|
|
|
137
137
|
class="sy-upload-workflow white"
|
|
138
138
|
>
|
|
139
139
|
<slot name="title">
|
|
140
|
-
<
|
|
140
|
+
<div
|
|
141
|
+
:aria-level="props.headingLevel"
|
|
142
|
+
role="heading"
|
|
143
|
+
class="text-h6 mb-2"
|
|
144
|
+
>
|
|
141
145
|
{{ title }}
|
|
142
|
-
</
|
|
146
|
+
</div>
|
|
143
147
|
</slot>
|
|
144
148
|
|
|
145
149
|
<FileList
|
|
@@ -159,7 +163,14 @@
|
|
|
159
163
|
v-model="uploadedFiles"
|
|
160
164
|
@error="uploadError"
|
|
161
165
|
@update:model-value="fileSelected"
|
|
162
|
-
|
|
166
|
+
>
|
|
167
|
+
<template
|
|
168
|
+
v-if="props.infoText"
|
|
169
|
+
#info-text
|
|
170
|
+
>
|
|
171
|
+
{{ props.infoText }}
|
|
172
|
+
</template>
|
|
173
|
+
</FileUpload>
|
|
163
174
|
</Transition>
|
|
164
175
|
|
|
165
176
|
<DialogBox
|
|
@@ -195,7 +206,7 @@
|
|
|
195
206
|
<FilePreview
|
|
196
207
|
v-if="showFilePreview"
|
|
197
208
|
:options="options.filePreview"
|
|
198
|
-
:file="
|
|
209
|
+
:file="uploadedFile"
|
|
199
210
|
/>
|
|
200
211
|
</DialogBox>
|
|
201
212
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { describe, it, expect, vi } from 'vitest'
|
|
2
2
|
import { mount } from '@vue/test-utils'
|
|
3
|
+
import { nextTick } from 'vue'
|
|
3
4
|
|
|
4
5
|
import UploadWorkflow from '../UploadWorkflow.vue'
|
|
5
6
|
import { locales as fileListLocales } from '@/components/FileList/UploadItem/locales'
|
|
@@ -34,6 +35,24 @@ describe('UploadWorkflow', () => {
|
|
|
34
35
|
expect(wrapper.find('.sy-file-upload').isVisible()).toBeTruthy()
|
|
35
36
|
})
|
|
36
37
|
|
|
38
|
+
it('renders default title with role heading and configured aria-level', () => {
|
|
39
|
+
const wrapper = mount(UploadWorkflow, {
|
|
40
|
+
props: {
|
|
41
|
+
uploadList: [
|
|
42
|
+
{
|
|
43
|
+
id: 'ID',
|
|
44
|
+
title: 'Carte d\'identité',
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
headingLevel: 2,
|
|
48
|
+
},
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
const title = wrapper.find('[role="heading"]')
|
|
52
|
+
expect(title.exists()).toBe(true)
|
|
53
|
+
expect(title.attributes('aria-level')).toBe('2')
|
|
54
|
+
})
|
|
55
|
+
|
|
37
56
|
it('shows the file in the list when set with the list button', async () => {
|
|
38
57
|
const wrapper = mount(UploadWorkflow, {
|
|
39
58
|
props: {
|
|
@@ -237,6 +256,35 @@ describe('UploadWorkflow', () => {
|
|
|
237
256
|
|
|
238
257
|
await wrapper.find('.file-item__action-preview').trigger('click')
|
|
239
258
|
|
|
259
|
+
expect(wrapper.emitted('preview')).toBeTruthy()
|
|
260
|
+
expect(wrapper.emitted('preview')?.[0]?.[0]).toMatchObject({
|
|
261
|
+
id: 'CERFA1',
|
|
262
|
+
title: 'CERFA 1',
|
|
263
|
+
showPreviewBtn: true,
|
|
264
|
+
})
|
|
265
|
+
|
|
240
266
|
expect(wrapper.find('.sy-file-preview img').exists()).toBeTruthy()
|
|
241
267
|
})
|
|
268
|
+
|
|
269
|
+
it('render custom infoText in FileUpload info-text slot', async () => {
|
|
270
|
+
const wrapper = mount(UploadWorkflow, {
|
|
271
|
+
props: {
|
|
272
|
+
modelValue: [],
|
|
273
|
+
uploadList: [
|
|
274
|
+
{
|
|
275
|
+
id: 'ID',
|
|
276
|
+
title: 'Carte d\'identité',
|
|
277
|
+
},
|
|
278
|
+
],
|
|
279
|
+
infoText: 'Texte personnalisé',
|
|
280
|
+
},
|
|
281
|
+
})
|
|
282
|
+
|
|
283
|
+
await nextTick()
|
|
284
|
+
|
|
285
|
+
const fileUpload = wrapper.find('.sy-file-upload')
|
|
286
|
+
expect(fileUpload.exists()).toBe(true)
|
|
287
|
+
|
|
288
|
+
expect(fileUpload.text()).toContain('Texte personnalisé')
|
|
289
|
+
})
|
|
242
290
|
})
|
|
@@ -8,12 +8,16 @@ exports[`UploadWorkflow > render the upload list 1`] = `
|
|
|
8
8
|
"
|
|
9
9
|
style="width: 100%;"
|
|
10
10
|
>
|
|
11
|
-
<
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
<div
|
|
12
|
+
aria-level="4"
|
|
13
|
+
class="
|
|
14
|
+
mb-2
|
|
15
|
+
text-h6
|
|
16
|
+
"
|
|
17
|
+
role="heading"
|
|
18
|
+
>
|
|
15
19
|
Documents à nous transmettre
|
|
16
|
-
</
|
|
20
|
+
</div>
|
|
17
21
|
<ul
|
|
18
22
|
class="upload-list"
|
|
19
23
|
style="width: 100%;"
|
|
@@ -8,6 +8,10 @@ export default function useFileList(
|
|
|
8
8
|
) {
|
|
9
9
|
const errorSelectedFiles = ref<string[]>([])
|
|
10
10
|
|
|
11
|
+
function notifySelectedFilesChanged() {
|
|
12
|
+
selectedFiles.value = selectedFiles.value.slice()
|
|
13
|
+
}
|
|
14
|
+
|
|
11
15
|
function removeFromErrorList(fileId: string) {
|
|
12
16
|
const errorIndex = errorSelectedFiles.value.findIndex(item => item === fileId)
|
|
13
17
|
if (errorIndex !== -1) {
|
|
@@ -22,12 +26,14 @@ export default function useFileList(
|
|
|
22
26
|
function resetFile(fileItem: FileListItem | SelectedFile) {
|
|
23
27
|
const itemIndex = selectedFiles.value.findIndex(item => item.id === fileItem.id)
|
|
24
28
|
selectedFiles.value.splice(itemIndex, 1)
|
|
29
|
+
notifySelectedFilesChanged()
|
|
25
30
|
}
|
|
26
31
|
|
|
27
32
|
function replaceFile(file: File, item: SelectedFile, state: FileState = 'success') {
|
|
28
33
|
item.file = file
|
|
29
34
|
item.fileName = file.name
|
|
30
35
|
item.state = state
|
|
36
|
+
notifySelectedFilesChanged()
|
|
31
37
|
}
|
|
32
38
|
|
|
33
39
|
function addOrReplaceFile(file: File, fileId: string, state: FileState = 'success') {
|
|
@@ -52,6 +58,7 @@ export default function useFileList(
|
|
|
52
58
|
fileName: file.name,
|
|
53
59
|
file,
|
|
54
60
|
})
|
|
61
|
+
notifySelectedFilesChanged()
|
|
55
62
|
removeFromErrorList(fileId)
|
|
56
63
|
}
|
|
57
64
|
}
|
package/src/components/index.ts
CHANGED
|
@@ -53,6 +53,7 @@ export { default as SySelect } from './Customs/Selects/SySelect/SySelect.vue'
|
|
|
53
53
|
export { default as SyAutocomplete } from './Customs/Selects/SyAutocomplete/SyAutocomplete.vue'
|
|
54
54
|
// export { default as SyBtnSelect } from './Customs/Selects/SyBtnSelect/SyBtnSelect.vue'
|
|
55
55
|
export { default as SyCheckbox } from './Customs/SyCheckbox/SyCheckbox.vue'
|
|
56
|
+
export { default as SyCheckBoxGroup } from './Customs/SyCheckBoxGroup/SyCheckBoxGroup.vue'
|
|
56
57
|
export { default as SyForm } from './Customs/SyForm/SyForm.vue'
|
|
57
58
|
export { default as SyRadioGroup } from './Customs/SyRadioGroup/SyRadioGroup.vue'
|
|
58
59
|
export { default as SyTextField } from './Customs/SyTextField/SyTextField.vue'
|
|
@@ -119,6 +120,8 @@ export { default as SyAlert } from './SyAlert/SyAlert.vue'
|
|
|
119
120
|
export { default as ErrorPage } from './ErrorPage/ErrorPage.vue'
|
|
120
121
|
export { default as MaintenancePage } from './MaintenancePage/MaintenancePage.vue'
|
|
121
122
|
export { default as NotFoundPage } from './NotFoundPage/NotFoundPage.vue'
|
|
123
|
+
export { default as StatusPage } from './StatusPage/StatusPage.vue'
|
|
124
|
+
export { default as DeclarationAccessibilityPage } from './DeclarationAccessibilityPage/DeclarationAccessibilityPage.vue'
|
|
122
125
|
|
|
123
126
|
// ===========================
|
|
124
127
|
// Amelipro
|
|
@@ -284,6 +284,18 @@ describe('useFieldValidation', () => {
|
|
|
284
284
|
}])[0]!
|
|
285
285
|
expect(ruleWithoutDate(new Date())).toEqual({ error: 'Configuration de la règle invalide' })
|
|
286
286
|
expect(rule('')).toEqual({}) // Empty string should be ignored
|
|
287
|
+
|
|
288
|
+
const ruleWithEmptyDate = generateRules([{
|
|
289
|
+
type: 'notBeforeDate',
|
|
290
|
+
options: { date: '', message: 'Date cannot be before reference date.' },
|
|
291
|
+
}])[0]!
|
|
292
|
+
expect(ruleWithEmptyDate(new Date())).toEqual({})
|
|
293
|
+
|
|
294
|
+
const ruleWithUndefinedDate = generateRules([{
|
|
295
|
+
type: 'notBeforeDate',
|
|
296
|
+
options: { date: undefined as unknown as string, message: 'Date cannot be before reference date.' },
|
|
297
|
+
}])[0]!
|
|
298
|
+
expect(ruleWithUndefinedDate(new Date())).toEqual({})
|
|
287
299
|
})
|
|
288
300
|
|
|
289
301
|
it('should throw when date reference is not a string in notBeforeDate rule', () => {
|
|
@@ -296,7 +308,7 @@ describe('useFieldValidation', () => {
|
|
|
296
308
|
},
|
|
297
309
|
}])[0]!
|
|
298
310
|
invalidRule(new Date())
|
|
299
|
-
}).toThrow('
|
|
311
|
+
}).toThrow('La date de référence doit être une chaîne au format DD/MM/YYYY')
|
|
300
312
|
})
|
|
301
313
|
|
|
302
314
|
it('should validate notAfterDate rule', () => {
|
|
@@ -324,6 +336,18 @@ describe('useFieldValidation', () => {
|
|
|
324
336
|
}])[0]!
|
|
325
337
|
expect(ruleWithoutDate(new Date())).toEqual({ error: 'Configuration de la règle invalide' })
|
|
326
338
|
expect(rule('')).toEqual({}) // Empty string should be ignored
|
|
339
|
+
|
|
340
|
+
const ruleWithEmptyDate = generateRules([{
|
|
341
|
+
type: 'notAfterDate',
|
|
342
|
+
options: { date: '', message: 'Date cannot be after reference date.' },
|
|
343
|
+
}])[0]!
|
|
344
|
+
expect(ruleWithEmptyDate(new Date())).toEqual({})
|
|
345
|
+
|
|
346
|
+
const ruleWithUndefinedDate = generateRules([{
|
|
347
|
+
type: 'notAfterDate',
|
|
348
|
+
options: { date: undefined as unknown as string, message: 'Date cannot be after reference date.' },
|
|
349
|
+
}])[0]!
|
|
350
|
+
expect(ruleWithUndefinedDate(new Date())).toEqual({})
|
|
327
351
|
})
|
|
328
352
|
|
|
329
353
|
it('should throw when date reference is not a string in notAfterDate rule', () => {
|
|
@@ -336,7 +360,7 @@ describe('useFieldValidation', () => {
|
|
|
336
360
|
},
|
|
337
361
|
}])[0]!
|
|
338
362
|
invalidRule(new Date())
|
|
339
|
-
}).toThrow('
|
|
363
|
+
}).toThrow('La date de référence doit être une chaîne au format DD/MM/YYYY')
|
|
340
364
|
})
|
|
341
365
|
|
|
342
366
|
it('should validate dateExact rule', () => {
|
|
@@ -364,6 +388,18 @@ describe('useFieldValidation', () => {
|
|
|
364
388
|
}])[0]!
|
|
365
389
|
expect(ruleWithoutDate(new Date())).toEqual({ error: 'Configuration de la règle invalide' })
|
|
366
390
|
expect(rule('')).toEqual({}) // Empty string should be ignored
|
|
391
|
+
|
|
392
|
+
const ruleWithEmptyDate = generateRules([{
|
|
393
|
+
type: 'dateExact',
|
|
394
|
+
options: { date: '', message: 'Date must be exactly the reference date.' },
|
|
395
|
+
}])[0]!
|
|
396
|
+
expect(ruleWithEmptyDate(new Date())).toEqual({})
|
|
397
|
+
|
|
398
|
+
const ruleWithUndefinedDate = generateRules([{
|
|
399
|
+
type: 'dateExact',
|
|
400
|
+
options: { date: undefined as unknown as string, message: 'Date must be exactly the reference date.' },
|
|
401
|
+
}])[0]!
|
|
402
|
+
expect(ruleWithUndefinedDate(new Date())).toEqual({})
|
|
367
403
|
})
|
|
368
404
|
|
|
369
405
|
it('should throw when date reference is not a string in dateExact rule', () => {
|
|
@@ -376,7 +412,7 @@ describe('useFieldValidation', () => {
|
|
|
376
412
|
},
|
|
377
413
|
}])[0]!
|
|
378
414
|
invalidRule(new Date())
|
|
379
|
-
}).toThrow('
|
|
415
|
+
}).toThrow('La date de référence doit être une chaîne au format DD/MM/YYYY')
|
|
380
416
|
})
|
|
381
417
|
|
|
382
418
|
it('should validate custom rule', () => {
|
|
@@ -233,14 +233,19 @@ export function useFieldValidation() {
|
|
|
233
233
|
}
|
|
234
234
|
|
|
235
235
|
case 'notBeforeDate': {
|
|
236
|
-
|
|
236
|
+
const hasDateOption = Object.prototype.hasOwnProperty.call(options, 'date')
|
|
237
|
+
if (!hasDateOption) {
|
|
237
238
|
return { error: 'Configuration de la règle invalide' }
|
|
238
239
|
}
|
|
239
240
|
// Si la valeur est null ou vide, ne pas valider (champ vide autorisé)
|
|
240
241
|
if (value === null || value === undefined || value === '') {
|
|
241
242
|
return {}
|
|
242
243
|
}
|
|
243
|
-
if (
|
|
244
|
+
if (
|
|
245
|
+
options.date === undefined
|
|
246
|
+
|| options.date === null
|
|
247
|
+
|| (typeof options.date === 'string' && options.date.trim() === '')
|
|
248
|
+
) {
|
|
244
249
|
return {}
|
|
245
250
|
}
|
|
246
251
|
const dateValue = parseDate(value)
|
|
@@ -250,7 +255,7 @@ export function useFieldValidation() {
|
|
|
250
255
|
|
|
251
256
|
// Check if options.date is a string and in DD/MM/YYYY format
|
|
252
257
|
if (typeof options.date !== 'string') {
|
|
253
|
-
throw new Error('
|
|
258
|
+
throw new Error('La date de référence doit être une chaîne au format DD/MM/YYYY')
|
|
254
259
|
}
|
|
255
260
|
|
|
256
261
|
const referenceDate = parseDate(options.date)
|
|
@@ -269,14 +274,19 @@ export function useFieldValidation() {
|
|
|
269
274
|
}
|
|
270
275
|
|
|
271
276
|
case 'notAfterDate': {
|
|
272
|
-
|
|
277
|
+
const hasDateOption = Object.prototype.hasOwnProperty.call(options, 'date')
|
|
278
|
+
if (!hasDateOption) {
|
|
273
279
|
return { error: 'Configuration de la règle invalide' }
|
|
274
280
|
}
|
|
275
281
|
// Si la valeur est null ou vide, ne pas valider (champ vide autorisé)
|
|
276
282
|
if (value === null || value === undefined || value === '') {
|
|
277
283
|
return {}
|
|
278
284
|
}
|
|
279
|
-
if (
|
|
285
|
+
if (
|
|
286
|
+
options.date === undefined
|
|
287
|
+
|| options.date === null
|
|
288
|
+
|| (typeof options.date === 'string' && options.date.trim() === '')
|
|
289
|
+
) {
|
|
280
290
|
return {}
|
|
281
291
|
}
|
|
282
292
|
const dateValue = parseDate(value)
|
|
@@ -286,7 +296,7 @@ export function useFieldValidation() {
|
|
|
286
296
|
|
|
287
297
|
// Check if options.date is a string and in DD/MM/YYYY format
|
|
288
298
|
if (typeof options.date !== 'string') {
|
|
289
|
-
throw new Error('
|
|
299
|
+
throw new Error('La date de référence doit être une chaîne au format DD/MM/YYYY')
|
|
290
300
|
}
|
|
291
301
|
|
|
292
302
|
const referenceDate = parseDate(options.date)
|
|
@@ -305,14 +315,19 @@ export function useFieldValidation() {
|
|
|
305
315
|
}
|
|
306
316
|
|
|
307
317
|
case 'dateExact': {
|
|
308
|
-
|
|
318
|
+
const hasDateOption = Object.prototype.hasOwnProperty.call(options, 'date')
|
|
319
|
+
if (!hasDateOption) {
|
|
309
320
|
return { error: 'Configuration de la règle invalide' }
|
|
310
321
|
}
|
|
311
322
|
// Si la valeur est null ou vide, ne pas valider (champ vide autorisé)
|
|
312
323
|
if (value === null || value === undefined || value === '') {
|
|
313
324
|
return {}
|
|
314
325
|
}
|
|
315
|
-
if (
|
|
326
|
+
if (
|
|
327
|
+
options.date === undefined
|
|
328
|
+
|| options.date === null
|
|
329
|
+
|| (typeof options.date === 'string' && options.date.trim() === '')
|
|
330
|
+
) {
|
|
316
331
|
return {}
|
|
317
332
|
}
|
|
318
333
|
const dateValue = parseDate(value)
|
|
@@ -321,7 +336,7 @@ export function useFieldValidation() {
|
|
|
321
336
|
}
|
|
322
337
|
|
|
323
338
|
if (typeof options.date !== 'string') {
|
|
324
|
-
throw new Error('
|
|
339
|
+
throw new Error('La date de référence doit être une chaîne au format DD/MM/YYYY')
|
|
325
340
|
}
|
|
326
341
|
|
|
327
342
|
const referenceDate = parseDate(options.date)
|
|
@@ -351,6 +351,9 @@ import '../../styles/shared.css';
|
|
|
351
351
|
|
|
352
352
|
<h4>Outil éventuel</h4>
|
|
353
353
|
<p>Utilisation du lecteur d'écran pour vérifier la navigation et l'accessibilité des formulaires, tel que l'indication du caractère obligatoire du champ, la liaison du champ aux aides à la saisie ainsi qu'aux messages d'erreurs, le comportement à la soumission du formulaire, etc.</p>
|
|
354
|
+
|
|
355
|
+
<h4>Ressources</h4>
|
|
356
|
+
<p><a href="https://bati-itao.github.io/learning/esdc-self-paced-web-accessibility-course/module6/forms-concepts-fr.html">Concepts des formulaires</a></p>
|
|
354
357
|
</div>
|
|
355
358
|
|
|
356
359
|
<div className="verification-card">
|
|
@@ -375,6 +378,8 @@ import '../../styles/shared.css';
|
|
|
375
378
|
<li>Les en-têtes de colonnes des tableaux utilisent des balises `th` avec l'attribut `scope="col"`.</li>
|
|
376
379
|
</ul>
|
|
377
380
|
</div>
|
|
381
|
+
<h4>Ressources</h4>
|
|
382
|
+
<p><a href="https://bati-itao.github.io/learning/esdc-self-paced-web-accessibility-course/module4/tables-concepts-fr.html">Concepts des tableaux</a></p>
|
|
378
383
|
</div>
|
|
379
384
|
|
|
380
385
|
<div className="verification-card">
|
|
@@ -432,6 +437,8 @@ import '../../styles/shared.css';
|
|
|
432
437
|
</ol>
|
|
433
438
|
<h4>Outil éventuel</h4>
|
|
434
439
|
<p>Aucun</p>
|
|
440
|
+
<h4>Ressources</h4>
|
|
441
|
+
<p><a href="https://bati-itao.github.io/learning/esdc-self-paced-web-accessibility-course/module9/introduction-fr.html">Concepts des contenus multimédia</a></p>
|
|
435
442
|
</div>
|
|
436
443
|
|
|
437
444
|
<div className="info-section">
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { computed } from 'vue'
|
|
2
|
+
import { useTheme } from 'vuetify'
|
|
3
|
+
import type { ComputedRef } from 'vue'
|
|
4
|
+
|
|
5
|
+
export function useThemeLocales<
|
|
6
|
+
T extends Record<string, unknown> & { default: unknown },
|
|
7
|
+
>(locales: T): {
|
|
8
|
+
themeLocales: ComputedRef<T[keyof T]>
|
|
9
|
+
} {
|
|
10
|
+
const vuetifyTheme = useTheme()
|
|
11
|
+
|
|
12
|
+
const themeLocales = computed((): T[keyof T] => {
|
|
13
|
+
return (locales[vuetifyTheme.name.value as keyof T] ?? locales.default) as T[keyof T]
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
themeLocales,
|
|
18
|
+
}
|
|
19
|
+
}
|