@cnamts/synapse 1.0.11 → 1.0.12
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-QEfKOz0P.js → DateFilter-DoCcOfDW.js} +1 -1
- package/dist/{NumberFilter-C0h7gVzp.js → NumberFilter-9uR8uo6p.js} +1 -1
- package/dist/{PeriodFilter-8dVrKjju.js → PeriodFilter-CxN5ini7.js} +1 -1
- package/dist/{SelectFilter-BI3QGbqb.js → SelectFilter-bfxipgvt.js} +1 -1
- package/dist/{TextFilter-UOp1hcPp.js → TextFilter-yCnWcmW2.js} +1 -1
- package/dist/components/Amelipro/AmeliproAccordion/AmeliproAccordion.d.ts +6 -2
- package/dist/components/Amelipro/AmeliproAccordionList/AmeliproAccordionList.d.ts +2 -0
- package/dist/components/Amelipro/AmeliproAccordionResult/AmeliproAccordionResult.d.ts +6 -2
- package/dist/components/Amelipro/AmeliproAutoCompleteField/AmeliproAutoCompleteField.d.ts +6 -6
- package/dist/components/Amelipro/AmeliproSelect/AmeliproSelect.d.ts +6 -6
- package/dist/components/Amelipro/AmeliproTable/AmeliproTable.d.ts +4 -0
- package/dist/components/Amelipro/AmeliproTable/types.d.ts +11 -0
- package/dist/components/Amelipro/AmeliproTabs/AmeliproTabs.d.ts +6 -6
- package/dist/components/CookiesSelection/CookiesInformation/CookiesInformation.d.ts +14 -14
- package/dist/components/Customs/Selects/SySelect/SySelect.d.ts +3 -3
- package/dist/components/Customs/SyTextField/SyTextField.d.ts +1 -1
- package/dist/components/DatePicker/CalendarMode/DatePicker.d.ts +40 -4
- package/dist/components/DatePicker/ComplexDatePicker/ComplexDatePicker.d.ts +46 -4
- package/dist/components/DatePicker/DateTextInput/DateTextInput.d.ts +5 -10
- package/dist/components/DatePicker/composables/useDatePickerViewMode.d.ts +2 -1
- package/dist/components/DatePicker/tests/setup.d.ts +368 -8
- package/dist/components/HeaderToolbar/HeaderToolbar.d.ts +6 -6
- package/dist/components/NirField/NirField.d.ts +4 -2
- package/dist/components/PeriodField/PeriodField.d.ts +80 -0
- package/dist/components/SearchListField/SearchListField.d.ts +3 -3
- package/dist/components/Tables/SyServerTable/SyServerTable.d.ts +5 -8
- package/dist/components/Tables/SyTable/SyTable.d.ts +5 -8
- package/dist/components/Tables/common/SyTablePagination.d.ts +3 -3
- package/dist/components/Tables/common/types.d.ts +4 -0
- package/dist/components/Tables/common/usePagination.d.ts +3 -4
- package/dist/components/Tables/common/useTableCheckbox.d.ts +10 -6
- package/dist/design-system-v3.js +1 -1
- package/dist/design-system-v3.umd.cjs +127 -127
- package/dist/{main-DyEOPqqn.js → main-DMXtXK3y.js} +9984 -9855
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/assets/overrides/_forms.scss +2 -0
- package/src/components/Amelipro/AmeliproAccordion/AmeliproAccordion.stories.ts +7 -4
- package/src/components/Amelipro/AmeliproAccordion/AmeliproAccordion.vue +2 -0
- package/src/components/Amelipro/AmeliproAccordionFrieze/AmeliproAccordionFrieze.vue +1 -0
- package/src/components/Amelipro/AmeliproAccordionFrieze/__tests__/__snapshots__/AmeliproAccordionFrieze.spec.ts.snap +574 -112
- package/src/components/Amelipro/AmeliproAccordionList/AmeliproAccordionList.stories.ts +5 -2
- package/src/components/Amelipro/AmeliproAccordionList/AmeliproAccordionList.vue +2 -1
- package/src/components/Amelipro/AmeliproAccordionResult/AmeliproAccordionResult.stories.ts +6 -3
- package/src/components/Amelipro/AmeliproAccordionResult/AmeliproAccordionResult.vue +2 -0
- package/src/components/Amelipro/AmeliproAccordionResultList/AmeliproAccordionResultList.stories.ts +5 -2
- package/src/components/Amelipro/AmeliproAccordionResultList/AmeliproAccordionResultList.vue +2 -1
- package/src/components/Amelipro/AmeliproCheckbox/__tests__/AmeliproCheckbox.spec.ts +175 -0
- package/src/components/Amelipro/AmeliproCheckbox/__tests__/__snapshots__/AmeliproCheckbox.spec.ts.snap +88 -0
- package/src/components/Amelipro/AmeliproCheckboxGroup/__tests__/AmeliproCheckboxGroup.spec.ts +423 -0
- package/src/components/Amelipro/AmeliproCheckboxGroup/{tests → __tests__}/__snapshots__/AmeliproCheckboxGroup.spec.ts.snap +112 -78
- package/src/components/Amelipro/AmeliproChips/__tests__/AmeliproChips.spec.ts +92 -0
- package/src/components/Amelipro/AmeliproChips/__tests__/__snapshots__/AmeliproChips.spec.ts.snap +81 -0
- package/src/components/Amelipro/AmeliproDialog/__tests__/AmeliproDialog.spec.ts +257 -0
- package/src/components/Amelipro/AmeliproDialog/__tests__/__snapshots__/AmeliproDialog.spec.ts.snap +61 -0
- package/src/components/Amelipro/AmeliproDisclosure/__tests__/AmeliproDisclosure.spec.ts +79 -0
- package/src/components/Amelipro/AmeliproDisclosure/__tests__/__snapshots__/AmeliproDisclosure.spec.ts.snap +89 -0
- package/src/components/Amelipro/AmeliproTable/AmeliproTable.stories.ts +81 -9
- package/src/components/Amelipro/AmeliproTable/AmeliproTable.vue +139 -61
- package/src/components/Amelipro/AmeliproTable/__tests__/AmeliproTable.spec.ts +10 -0
- package/src/components/Amelipro/AmeliproTable/__tests__/__snapshots__/AmeliproTable.spec.ts.snap +361 -187
- package/src/components/Amelipro/AmeliproTable/types.d.ts +11 -0
- package/src/components/Customs/SyTextField/SyTextField.vue +27 -5
- package/src/components/DatePicker/CalendarMode/DatePicker.vue +31 -8
- package/src/components/DatePicker/ComplexDatePicker/ComplexDatePicker.vue +44 -12
- package/src/components/DatePicker/ComplexDatePicker/tests/ComplexDatePicker.spec.ts +2 -2
- package/src/components/DatePicker/DateTextInput/DateTextInput.vue +7 -1
- package/src/components/DatePicker/composables/tests/useDatePickerViewMode.spec.ts +107 -72
- package/src/components/DatePicker/composables/tests/useMonthButtonCustomization.spec.ts +6 -6
- package/src/components/DatePicker/composables/useDatePickerViewMode.ts +57 -7
- package/src/components/DatePicker/composables/useMonthButtonCustomization.ts +14 -14
- package/src/components/DatePicker/tests/navigation.regression.spec.ts +74 -0
- package/src/components/DatePicker/tests/navigation.simple.spec.ts +137 -0
- package/src/components/NirField/NirField.stories.ts +11 -2
- package/src/components/NirField/NirField.vue +21 -9
- package/src/components/RangeField/tests/RangeField.spec.ts +0 -3
- package/src/components/Tables/SyServerTable/SyServerTable.mdx +15 -0
- package/src/components/Tables/SyServerTable/SyServerTable.stories.ts +309 -0
- package/src/components/Tables/SyServerTable/SyServerTable.vue +18 -3
- package/src/components/Tables/SyServerTable/tests/SyServerTable.spec.ts +67 -0
- package/src/components/Tables/SyTable/SyTable.mdx +15 -0
- package/src/components/Tables/SyTable/SyTable.stories.ts +228 -0
- package/src/components/Tables/SyTable/SyTable.vue +18 -3
- package/src/components/Tables/SyTable/tests/SyTable.spec.ts +63 -0
- package/src/components/Tables/common/SyTablePagination.vue +10 -8
- package/src/components/Tables/common/types.ts +4 -0
- package/src/components/Tables/common/usePagination.ts +11 -20
- package/src/components/Tables/common/useTableCheckbox.ts +23 -11
- package/src/composables/validation/AvecVosComposants.mdx.old +1 -1
- package/src/composables/validation/FormValidation.stories.ts.old +5 -5
- package/src/stories/Accessibilite/Introduction.mdx +1 -1
- package/src/stories/Demarrer/EnrichirLeDesignSystem.mdx +43 -0
- package/src/stories/Demarrer/EnrichirLeDesignSystem.stories.ts +239 -0
- package/src/stories/Demarrer/SignalerUneAnomalie.mdx +39 -0
- package/src/stories/Demarrer/SignalerUneAnomalie.stories.ts +261 -0
- package/src/components/Amelipro/AmeliproCheckbox/tests/AmeliproCheckbox.spec.ts +0 -19
- package/src/components/Amelipro/AmeliproCheckbox/tests/__snapshots__/AmeliproCheckbox.spec.ts.snap +0 -40
- package/src/components/Amelipro/AmeliproCheckboxGroup/tests/AmeliproCheckboxGroup.spec.ts +0 -46
- package/src/components/Amelipro/AmeliproChips/tests/AmeliproChips.spec.ts +0 -16
- package/src/components/Amelipro/AmeliproChips/tests/__snapshots__/AmeliproChips.spec.ts.snap +0 -97
- package/src/components/Amelipro/AmeliproDialog/tests/AmeliproDialog.spec.ts +0 -24
- package/src/components/Amelipro/AmeliproDialog/tests/__snapshots__/AmeliproDialog.spec.ts.snap +0 -134
- package/src/components/Amelipro/AmeliproDisclosure/tests/AmeliproDisclosure.spec.ts +0 -19
- package/src/components/Amelipro/AmeliproDisclosure/tests/__snapshots__/AmeliproDisclosure.spec.ts.snap +0 -104
- package/src/components/BackBtn/tests/__snapshots__/BackBtn.spec.ts.snap +0 -45
- package/src/components/RangeField/tests/__snapshots__/RangeField.spec.ts.snap +0 -1270
- package/src/stories/Demarrer/CreerUneIssue.mdx +0 -67
- package/src/stories/Demarrer/components.stories.ts +0 -25
|
@@ -7,6 +7,8 @@ import type { VDataTable } from 'vuetify/components'
|
|
|
7
7
|
import dayjs from 'dayjs'
|
|
8
8
|
import { fn } from '@storybook/test'
|
|
9
9
|
|
|
10
|
+
import { mdiChevronDown, mdiChevronUp } from '@mdi/js'
|
|
11
|
+
|
|
10
12
|
interface User {
|
|
11
13
|
[key: string]: string
|
|
12
14
|
firstname: string
|
|
@@ -104,6 +106,13 @@ const meta = {
|
|
|
104
106
|
description: 'Texte de la légende du tableau',
|
|
105
107
|
control: { type: 'text' },
|
|
106
108
|
},
|
|
109
|
+
showExpand: {
|
|
110
|
+
description: 'Affiche une colonne permettant d\'étendre les lignes pour afficher du contenu supplémentaire',
|
|
111
|
+
control: { type: 'boolean' },
|
|
112
|
+
table: {
|
|
113
|
+
category: 'props',
|
|
114
|
+
},
|
|
115
|
+
},
|
|
107
116
|
resizableColumns: {
|
|
108
117
|
description: 'Permet de redimensionner les colonnes du tableau',
|
|
109
118
|
control: { type: 'boolean' },
|
|
@@ -153,6 +162,15 @@ const meta = {
|
|
|
153
162
|
type: { summary: 'boolean' },
|
|
154
163
|
},
|
|
155
164
|
},
|
|
165
|
+
selectionKey: {
|
|
166
|
+
description: 'Clé utilisée pour identifier chaque ligne lors de la sélection. Par défaut, utilise "id" si présent, sinon l\'objet complet.',
|
|
167
|
+
control: { type: 'text' },
|
|
168
|
+
table: {
|
|
169
|
+
category: 'props',
|
|
170
|
+
type: { summary: 'string' },
|
|
171
|
+
defaultValue: { summary: 'undefined (fallback: id | objet complet)' },
|
|
172
|
+
},
|
|
173
|
+
},
|
|
156
174
|
},
|
|
157
175
|
} satisfies Meta<typeof SyServerTable & typeof VDataTable>
|
|
158
176
|
|
|
@@ -4740,6 +4758,297 @@ export const ColumnControls: StoryObj<typeof SyServerTable> = {
|
|
|
4740
4758
|
},
|
|
4741
4759
|
}
|
|
4742
4760
|
|
|
4761
|
+
export const ExpandableRows: Story = {
|
|
4762
|
+
parameters: {
|
|
4763
|
+
sourceCode: [
|
|
4764
|
+
{
|
|
4765
|
+
name: 'Template',
|
|
4766
|
+
code: `
|
|
4767
|
+
<template>
|
|
4768
|
+
<SyServerTable
|
|
4769
|
+
v-model:options="options"
|
|
4770
|
+
:items="users"
|
|
4771
|
+
:headers="headers"
|
|
4772
|
+
:server-items-length="totalUsers"
|
|
4773
|
+
:loading="state === StateEnum.PENDING"
|
|
4774
|
+
show-expand
|
|
4775
|
+
caption="Tableau complexe"
|
|
4776
|
+
suffix="server-expandable"
|
|
4777
|
+
@update:options="fetchData"
|
|
4778
|
+
>
|
|
4779
|
+
<template #item.data-table-expand="{ internalItem, isExpanded, toggleExpand }">
|
|
4780
|
+
<v-btn
|
|
4781
|
+
:append-icon="isExpanded(internalItem) ? mdiChevronUp : mdiChevronDown"
|
|
4782
|
+
:text="isExpanded(internalItem) ? 'Fermer' : \`Plus d'info\`"
|
|
4783
|
+
class="text-none"
|
|
4784
|
+
color="medium-emphasis"
|
|
4785
|
+
size="small"
|
|
4786
|
+
variant="text"
|
|
4787
|
+
width="105"
|
|
4788
|
+
border
|
|
4789
|
+
slim
|
|
4790
|
+
@click="toggleExpand(internalItem)"
|
|
4791
|
+
/>
|
|
4792
|
+
</template>
|
|
4793
|
+
|
|
4794
|
+
<template #expanded-row="{ columns, item }">
|
|
4795
|
+
<tr>
|
|
4796
|
+
<td
|
|
4797
|
+
:colspan="columns.length"
|
|
4798
|
+
class="py-2"
|
|
4799
|
+
>
|
|
4800
|
+
<strong>Informations complémentaires :</strong>
|
|
4801
|
+
<p>Plus de détails pour {{ item.firstname }} {{ item.lastname }}.</p>
|
|
4802
|
+
</td>
|
|
4803
|
+
</tr>
|
|
4804
|
+
</template>
|
|
4805
|
+
</SyServerTable>
|
|
4806
|
+
</template>
|
|
4807
|
+
`,
|
|
4808
|
+
},
|
|
4809
|
+
{
|
|
4810
|
+
name: 'Script',
|
|
4811
|
+
code: `
|
|
4812
|
+
<script setup lang="ts">
|
|
4813
|
+
import { ref, watch } from 'vue'
|
|
4814
|
+
import { SyServerTable } from '@cnamts/synapse'
|
|
4815
|
+
import { StateEnum } from '@cnamts/synapse/src/components/Tables/common/constants/StateEnum'
|
|
4816
|
+
import type { DataOptions } from '@cnamts/synapse/src/components/Tables/common/types'
|
|
4817
|
+
import { mdiChevronDown, mdiChevronUp } from '@mdi/js'
|
|
4818
|
+
|
|
4819
|
+
interface User {
|
|
4820
|
+
[key: string]: string
|
|
4821
|
+
firstname: string
|
|
4822
|
+
lastname: string
|
|
4823
|
+
email: string
|
|
4824
|
+
}
|
|
4825
|
+
|
|
4826
|
+
interface DataObj {
|
|
4827
|
+
items: User[]
|
|
4828
|
+
total: number
|
|
4829
|
+
}
|
|
4830
|
+
|
|
4831
|
+
const totalUsers = ref(0)
|
|
4832
|
+
const users = ref<User[]>([])
|
|
4833
|
+
const state = ref(StateEnum.IDLE)
|
|
4834
|
+
|
|
4835
|
+
const options = ref({
|
|
4836
|
+
itemsPerPage: 5,
|
|
4837
|
+
sortBy: [{ key: 'lastname', order: 'asc' }],
|
|
4838
|
+
page: 1,
|
|
4839
|
+
})
|
|
4840
|
+
|
|
4841
|
+
const headers = [
|
|
4842
|
+
{ title: 'Nom', key: 'lastname' },
|
|
4843
|
+
{ title: 'Prénom', key: 'firstname' },
|
|
4844
|
+
{ title: 'Email', key: 'email' },
|
|
4845
|
+
]
|
|
4846
|
+
|
|
4847
|
+
const fetchData = async (): Promise<void> => {
|
|
4848
|
+
const { items, total } = await getDataFromApi(options.value)
|
|
4849
|
+
users.value = items
|
|
4850
|
+
totalUsers.value = total
|
|
4851
|
+
}
|
|
4852
|
+
|
|
4853
|
+
const wait = async (ms: number) => {
|
|
4854
|
+
return new Promise(resolve => setTimeout(resolve, ms))
|
|
4855
|
+
}
|
|
4856
|
+
|
|
4857
|
+
const getDataFromApi = async ({ sortBy, page, itemsPerPage, filters }: DataOptions): Promise<DataObj> => {
|
|
4858
|
+
state.value = StateEnum.PENDING
|
|
4859
|
+
await wait(1000)
|
|
4860
|
+
|
|
4861
|
+
return new Promise((resolve) => {
|
|
4862
|
+
let items: User[] = getUsers()
|
|
4863
|
+
const total = items.length
|
|
4864
|
+
|
|
4865
|
+
if (sortBy && sortBy.length > 0) {
|
|
4866
|
+
items = items.sort((a, b) => {
|
|
4867
|
+
const key = sortBy[0].key
|
|
4868
|
+
const order = sortBy[0].order === 'asc' ? 1 : -1
|
|
4869
|
+
|
|
4870
|
+
return a[key] > b[key] ? order : -order
|
|
4871
|
+
})
|
|
4872
|
+
}
|
|
4873
|
+
|
|
4874
|
+
if (itemsPerPage > 0) {
|
|
4875
|
+
items = items.slice((page - 1) * itemsPerPage, page * itemsPerPage)
|
|
4876
|
+
}
|
|
4877
|
+
|
|
4878
|
+
resolve({ items, total })
|
|
4879
|
+
state.value = StateEnum.RESOLVED
|
|
4880
|
+
})
|
|
4881
|
+
}
|
|
4882
|
+
|
|
4883
|
+
const getUsers = (): User[] => {
|
|
4884
|
+
return [
|
|
4885
|
+
{ firstname: 'Virginie', lastname: 'Beauchesne', email: 'virginie.beauchesne@example.com' },
|
|
4886
|
+
{ firstname: 'Simone', lastname: 'Bellefeuille', email: 'simone.bellefeuille@example.com' },
|
|
4887
|
+
{ firstname: 'Étienne', lastname: 'Salois', email: 'etienne.salois@example.com' },
|
|
4888
|
+
{ firstname: 'Bernadette', lastname: 'Langelier', email: 'bernadette.langelier@example.com' },
|
|
4889
|
+
{ firstname: 'Agate', lastname: 'Roy', email: 'agate.roy@example.com' },
|
|
4890
|
+
{ firstname: 'Louis', lastname: 'Denis', email: 'louis.denis@example.com' },
|
|
4891
|
+
{ firstname: 'Édith', lastname: 'Cartier', email: 'edith.cartier@example.com' },
|
|
4892
|
+
{ firstname: 'Alphonse', lastname: 'Bouvier', email: 'alphonse.bouvier@example.com' },
|
|
4893
|
+
{ firstname: 'Eustache', lastname: 'Dubois', email: 'eustache.dubois@example.com' },
|
|
4894
|
+
{ firstname: 'Rosemarie', lastname: 'Quessy', email: 'rosemarie.quessy@example.com' },
|
|
4895
|
+
{ firstname: 'Serge', lastname: 'Rivard', email: 'serge.rivard@example.com' },
|
|
4896
|
+
{ firstname: 'Jacques', lastname: 'Demers', email: 'jacques.demers@example.com' },
|
|
4897
|
+
{ firstname: 'Aimée', lastname: 'Josseaume', email: 'aimee.josseaume@example.com' },
|
|
4898
|
+
{ firstname: 'Delphine', lastname: 'Robillard', email: 'delphine.robillard@example.com' },
|
|
4899
|
+
{ firstname: 'Alexandre', lastname: 'Lazure', email: 'alexandre.lazure@example.com' },
|
|
4900
|
+
]
|
|
4901
|
+
}
|
|
4902
|
+
|
|
4903
|
+
// Initialize data
|
|
4904
|
+
fetchData()
|
|
4905
|
+
</script>
|
|
4906
|
+
`,
|
|
4907
|
+
},
|
|
4908
|
+
],
|
|
4909
|
+
},
|
|
4910
|
+
args: {
|
|
4911
|
+
'options': {
|
|
4912
|
+
itemsPerPage: 5,
|
|
4913
|
+
sortBy: [{ key: 'lastname', order: 'asc' }],
|
|
4914
|
+
page: 1,
|
|
4915
|
+
},
|
|
4916
|
+
'headers': [
|
|
4917
|
+
{ title: 'Nom', key: 'lastname' },
|
|
4918
|
+
{ title: 'Prénom', key: 'firstname' },
|
|
4919
|
+
{ title: 'Email', key: 'email' },
|
|
4920
|
+
],
|
|
4921
|
+
'caption': '',
|
|
4922
|
+
'serverItemsLength': 15,
|
|
4923
|
+
'showExpand': true,
|
|
4924
|
+
'suffix': 'server-expandable',
|
|
4925
|
+
'density': 'default',
|
|
4926
|
+
'striped': false,
|
|
4927
|
+
'onUpdate:options': fn(),
|
|
4928
|
+
},
|
|
4929
|
+
render: (args) => {
|
|
4930
|
+
return {
|
|
4931
|
+
components: { SyServerTable },
|
|
4932
|
+
setup() {
|
|
4933
|
+
const totalUsers = ref(0)
|
|
4934
|
+
const users = ref<User[]>([])
|
|
4935
|
+
const state = ref(StateEnum.IDLE)
|
|
4936
|
+
|
|
4937
|
+
const options = ref({ ...args.options })
|
|
4938
|
+
|
|
4939
|
+
watch(options, (newVal) => {
|
|
4940
|
+
if (args.options) {
|
|
4941
|
+
Object.assign(args.options, JSON.parse(JSON.stringify(newVal)))
|
|
4942
|
+
}
|
|
4943
|
+
}, { deep: true })
|
|
4944
|
+
|
|
4945
|
+
const fetchData = async (): Promise<void> => {
|
|
4946
|
+
const { items, total } = await getDataFromApi(options.value as DataOptions)
|
|
4947
|
+
users.value = items
|
|
4948
|
+
totalUsers.value = total
|
|
4949
|
+
}
|
|
4950
|
+
|
|
4951
|
+
const wait = async (ms: number) => {
|
|
4952
|
+
return new Promise(resolve => setTimeout(resolve, ms))
|
|
4953
|
+
}
|
|
4954
|
+
|
|
4955
|
+
const getDataFromApi = async ({ sortBy, page, itemsPerPage }: DataOptions): Promise<DataObj> => {
|
|
4956
|
+
state.value = StateEnum.PENDING
|
|
4957
|
+
await wait(1000)
|
|
4958
|
+
|
|
4959
|
+
return new Promise((resolve) => {
|
|
4960
|
+
let items: User[] = getUsers()
|
|
4961
|
+
const total = items.length
|
|
4962
|
+
|
|
4963
|
+
if (sortBy && sortBy.length > 0) {
|
|
4964
|
+
items = items.sort((a, b) => {
|
|
4965
|
+
const key = sortBy[0].key
|
|
4966
|
+
const order = sortBy[0].order === 'asc' ? 1 : -1
|
|
4967
|
+
|
|
4968
|
+
return a[key] > b[key] ? order : -order
|
|
4969
|
+
})
|
|
4970
|
+
}
|
|
4971
|
+
|
|
4972
|
+
if (itemsPerPage > 0) {
|
|
4973
|
+
items = items.slice((page - 1) * itemsPerPage, page * itemsPerPage)
|
|
4974
|
+
}
|
|
4975
|
+
|
|
4976
|
+
resolve({ items, total })
|
|
4977
|
+
state.value = StateEnum.RESOLVED
|
|
4978
|
+
})
|
|
4979
|
+
}
|
|
4980
|
+
|
|
4981
|
+
const getUsers = (): User[] => {
|
|
4982
|
+
return [
|
|
4983
|
+
{ firstname: 'Virginie', lastname: 'Beauchesne', email: 'virginie.beauchesne@example.com' },
|
|
4984
|
+
{ firstname: 'Simone', lastname: 'Bellefeuille', email: 'simone.bellefeuille@example.com' },
|
|
4985
|
+
{ firstname: 'Étienne', lastname: 'Salois', email: 'etienne.salois@example.com' },
|
|
4986
|
+
{ firstname: 'Bernadette', lastname: 'Langelier', email: 'bernadette.langelier@example.com' },
|
|
4987
|
+
{ firstname: 'Agate', lastname: 'Roy', email: 'agate.roy@example.com' },
|
|
4988
|
+
{ firstname: 'Louis', lastname: 'Denis', email: 'louis.denis@example.com' },
|
|
4989
|
+
{ firstname: 'Édith', lastname: 'Cartier', email: 'edith.cartier@example.com' },
|
|
4990
|
+
{ firstname: 'Alphonse', lastname: 'Bouvier', email: 'alphonse.bouvier@example.com' },
|
|
4991
|
+
{ firstname: 'Eustache', lastname: 'Dubois', email: 'eustache.dubois@example.com' },
|
|
4992
|
+
{ firstname: 'Rosemarie', lastname: 'Quessy', email: 'rosemarie.quessy@example.com' },
|
|
4993
|
+
{ firstname: 'Serge', lastname: 'Rivard', email: 'serge.rivard@example.com' },
|
|
4994
|
+
{ firstname: 'Jacques', lastname: 'Demers', email: 'jacques.demers@example.com' },
|
|
4995
|
+
{ firstname: 'Aimée', lastname: 'Josseaume', email: 'aimee.josseaume@example.com' },
|
|
4996
|
+
{ firstname: 'Delphine', lastname: 'Robillard', email: 'delphine.robillard@example.com' },
|
|
4997
|
+
{ firstname: 'Alexandre', lastname: 'Lazure', email: 'alexandre.lazure@example.com' },
|
|
4998
|
+
]
|
|
4999
|
+
}
|
|
5000
|
+
|
|
5001
|
+
// Initialize data
|
|
5002
|
+
fetchData()
|
|
5003
|
+
|
|
5004
|
+
return { args, users, state, fetchData, options, totalUsers, StateEnum, mdiChevronDown, mdiChevronUp }
|
|
5005
|
+
},
|
|
5006
|
+
template: `
|
|
5007
|
+
<div>
|
|
5008
|
+
<SyServerTable
|
|
5009
|
+
v-model:options="options"
|
|
5010
|
+
:items="users"
|
|
5011
|
+
:server-items-length="totalUsers"
|
|
5012
|
+
:loading="state === StateEnum.PENDING"
|
|
5013
|
+
v-bind="args"
|
|
5014
|
+
show-expand
|
|
5015
|
+
caption="Tableau complexe"
|
|
5016
|
+
suffix="server-expandable"
|
|
5017
|
+
@update:options="fetchData"
|
|
5018
|
+
>
|
|
5019
|
+
<template #item.data-table-expand="{ internalItem, isExpanded, toggleExpand }">
|
|
5020
|
+
<v-btn
|
|
5021
|
+
:append-icon="isExpanded(internalItem) ? mdiChevronUp : mdiChevronDown"
|
|
5022
|
+
:text="isExpanded(internalItem) ? 'Fermer' : \`Plus d'info\`"
|
|
5023
|
+
class="text-none"
|
|
5024
|
+
color="medium-emphasis"
|
|
5025
|
+
size="small"
|
|
5026
|
+
variant="text"
|
|
5027
|
+
width="105"
|
|
5028
|
+
border
|
|
5029
|
+
slim
|
|
5030
|
+
@click="toggleExpand(internalItem)"
|
|
5031
|
+
/>
|
|
5032
|
+
</template>
|
|
5033
|
+
|
|
5034
|
+
<template #expanded-row="{ columns, item }">
|
|
5035
|
+
<tr>
|
|
5036
|
+
<td
|
|
5037
|
+
:colspan="columns.length"
|
|
5038
|
+
class="py-2"
|
|
5039
|
+
>
|
|
5040
|
+
<strong>Informations complémentaires :</strong>
|
|
5041
|
+
<p>Plus de détails pour {{ item.firstname }} {{ item.lastname }}.</p>
|
|
5042
|
+
</td>
|
|
5043
|
+
</tr>
|
|
5044
|
+
</template>
|
|
5045
|
+
</SyServerTable>
|
|
5046
|
+
</div>
|
|
5047
|
+
`,
|
|
5048
|
+
}
|
|
5049
|
+
},
|
|
5050
|
+
}
|
|
5051
|
+
|
|
4743
5052
|
export const SlotItem: Story = {
|
|
4744
5053
|
parameters: {
|
|
4745
5054
|
sourceCode: [
|
|
@@ -91,12 +91,25 @@
|
|
|
91
91
|
|
|
92
92
|
// Use the pagination composable with displayedItemsLength (stable during refetch)
|
|
93
93
|
const itemsLength = computed(() => displayedItemsLength.value)
|
|
94
|
-
const { page, pageCount, itemsPerPageValue, updateItemsPerPage } = usePagination({
|
|
94
|
+
const { page, pageCount, itemsPerPageValue, updateItemsPerPage, isUpdatingItemsPerPage } = usePagination({
|
|
95
95
|
options,
|
|
96
96
|
itemsLength,
|
|
97
|
-
table,
|
|
98
97
|
})
|
|
99
98
|
|
|
99
|
+
// Defines a function to handle updating the data table options
|
|
100
|
+
function onUpdateOptions(newOptions: Partial<DataOptions>) {
|
|
101
|
+
if (isUpdatingItemsPerPage.value && typeof newOptions.itemsPerPage !== 'undefined') {
|
|
102
|
+
// Creates a copy of the received options
|
|
103
|
+
const rest = { ...newOptions }
|
|
104
|
+
delete (rest as Record<string, unknown>).itemsPerPage
|
|
105
|
+
// Updates the other options without modifying itemsPerPage
|
|
106
|
+
updateOptions(rest)
|
|
107
|
+
return
|
|
108
|
+
}
|
|
109
|
+
// In all other cases, simply updates the options with the new values
|
|
110
|
+
updateOptions(newOptions)
|
|
111
|
+
}
|
|
112
|
+
|
|
100
113
|
// Create a computed property for items to ensure reactivity
|
|
101
114
|
// Bind to displayedItems so it is always an array
|
|
102
115
|
const tableItems = computed<Record<string, unknown>[]>(() => displayedItems.value)
|
|
@@ -191,6 +204,7 @@
|
|
|
191
204
|
updateModelValue: (value) => {
|
|
192
205
|
model.value = value
|
|
193
206
|
},
|
|
207
|
+
selectionKey: toRef(props, 'selectionKey'),
|
|
194
208
|
})
|
|
195
209
|
|
|
196
210
|
// Use the ARIA accessibility composable
|
|
@@ -267,7 +281,8 @@
|
|
|
267
281
|
:item-value="getItemValue"
|
|
268
282
|
:multi-sort="props.multiSort"
|
|
269
283
|
:must-sort="props.mustSort"
|
|
270
|
-
|
|
284
|
+
:show-expand="props.showExpand"
|
|
285
|
+
@update:options="onUpdateOptions"
|
|
271
286
|
>
|
|
272
287
|
<template #top>
|
|
273
288
|
<caption
|
|
@@ -662,6 +662,73 @@ describe('SyServerTable', () => {
|
|
|
662
662
|
})
|
|
663
663
|
})
|
|
664
664
|
|
|
665
|
+
describe('SyServerTable Checkbox selectionKey', () => {
|
|
666
|
+
it('uses custom selectionKey when provided', async () => {
|
|
667
|
+
const items = [
|
|
668
|
+
{ id: 1, uuid: 's-1', name: 'A' },
|
|
669
|
+
{ id: 2, uuid: 's-2', name: 'B' },
|
|
670
|
+
]
|
|
671
|
+
|
|
672
|
+
const wrapper = mount(SyServerTable, {
|
|
673
|
+
props: {
|
|
674
|
+
headers,
|
|
675
|
+
items,
|
|
676
|
+
serverItemsLength: items.length,
|
|
677
|
+
showSelect: true,
|
|
678
|
+
selectionKey: 'uuid',
|
|
679
|
+
suffix: '',
|
|
680
|
+
},
|
|
681
|
+
})
|
|
682
|
+
|
|
683
|
+
const dataTable = wrapper.findComponent({ name: 'VDataTableServer' })
|
|
684
|
+
const itemValue = dataTable.props('itemValue') as (item: unknown) => unknown
|
|
685
|
+
|
|
686
|
+
expect(itemValue(items[0] as unknown as Record<string, unknown>)).toBe('s-1')
|
|
687
|
+
expect(itemValue(items[1] as unknown as Record<string, unknown>)).toBe('s-2')
|
|
688
|
+
})
|
|
689
|
+
|
|
690
|
+
it('falls back to id when selectionKey is missing on item', async () => {
|
|
691
|
+
const items = [{ id: 10, name: 'No UUID' }]
|
|
692
|
+
|
|
693
|
+
const wrapper = mount(SyServerTable, {
|
|
694
|
+
props: {
|
|
695
|
+
headers,
|
|
696
|
+
items,
|
|
697
|
+
serverItemsLength: items.length,
|
|
698
|
+
showSelect: true,
|
|
699
|
+
selectionKey: 'uuid',
|
|
700
|
+
suffix: '',
|
|
701
|
+
},
|
|
702
|
+
})
|
|
703
|
+
|
|
704
|
+
const dataTable = wrapper.findComponent({ name: 'VDataTableServer' })
|
|
705
|
+
const itemValue = dataTable.props('itemValue') as (item: unknown) => unknown
|
|
706
|
+
|
|
707
|
+
expect(itemValue(items[0] as unknown as Record<string, unknown>)).toBe(10)
|
|
708
|
+
})
|
|
709
|
+
|
|
710
|
+
it('falls back to full object when neither selectionKey nor id are present', async () => {
|
|
711
|
+
const item = { name: 'No keys' }
|
|
712
|
+
|
|
713
|
+
const wrapper = mount(SyServerTable, {
|
|
714
|
+
props: {
|
|
715
|
+
headers,
|
|
716
|
+
items: [item],
|
|
717
|
+
serverItemsLength: 1,
|
|
718
|
+
showSelect: true,
|
|
719
|
+
selectionKey: 'uuid',
|
|
720
|
+
suffix: '',
|
|
721
|
+
},
|
|
722
|
+
})
|
|
723
|
+
|
|
724
|
+
const dataTable = wrapper.findComponent({ name: 'VDataTableServer' })
|
|
725
|
+
const itemValue = dataTable.props('itemValue') as (item: unknown) => unknown
|
|
726
|
+
|
|
727
|
+
const result = itemValue(item as unknown as Record<string, unknown>)
|
|
728
|
+
expect(result).toBe(item)
|
|
729
|
+
})
|
|
730
|
+
})
|
|
731
|
+
|
|
665
732
|
describe('Column management', () => {
|
|
666
733
|
it('should hide a column when hideColumn is called', async () => {
|
|
667
734
|
// Create a mock for OrganizeColumns component
|
|
@@ -44,6 +44,21 @@ Le composant permet de cacher ou réorganiser l'ordre des colonnes en utilisant
|
|
|
44
44
|
|
|
45
45
|
Le composant permet de sélectionner des lignes individuellement ou en masse. Vous pouvez activer la sélection en utilisant la prop `show-select`.
|
|
46
46
|
|
|
47
|
+
Par défaut, la clé utilisée pour identifier chaque ligne lors de la sélection est `id`. Si vos éléments ne possèdent pas de propriété `id`, la valeur sélectionnée correspondra à l'objet complet de la ligne.
|
|
48
|
+
|
|
49
|
+
Vous pouvez personnaliser cette clé avec la prop `selection-key` pour indiquer quel champ utiliser (ex: `userId`).
|
|
50
|
+
|
|
51
|
+
Exemple d'utilisation :
|
|
52
|
+
<Source dark code={`
|
|
53
|
+
<SyTable
|
|
54
|
+
v-model="selected"
|
|
55
|
+
:items="items"
|
|
56
|
+
:headers="headers"
|
|
57
|
+
show-select
|
|
58
|
+
selection-key="userId"
|
|
59
|
+
/>
|
|
60
|
+
`}/>
|
|
61
|
+
|
|
47
62
|
### Slot item
|
|
48
63
|
Le composant permet de personnaliser l'affichage des contenus en utilisant le slot `item`. Vous pouvez définir la structure de chaque contenu en fonction de vos besoins.
|
|
49
64
|
|