Skip to content

Commit

Permalink
Merge pull request #586 from dnum-mi/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
laruiss authored Aug 22, 2023
2 parents fdce331 + 990977f commit 37c7c85
Show file tree
Hide file tree
Showing 3 changed files with 272 additions and 11 deletions.
2 changes: 1 addition & 1 deletion src/components/DsfrSelect/DsfrSelect.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const props = withDefaults(defineProps<{
description?: string
modelValue?: string | number
label?: string
options?:(string | number | { value: string | number, text: string, disabled: boolean })[]
options?:(string | number | { value: string | number, text: string, disabled?: boolean })[]
successMessage?: string
errorMessage?: string
defaultUnselectedText?: string
Expand Down
181 changes: 173 additions & 8 deletions src/components/DsfrTable/DsfrTable.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ export default {
control: 'boolean',
description: 'Indique si la balise caption doit être visible (`false`, défaut) ou cachée (`true`)',
},
pagination: {
control: 'boolean',
description: 'Intègre une pagination au tableau',
},
headers: {
control: 'object',
description: 'Liste des en-têtes du tableau (tableau de string). Il existe un slot nommé `headers` pour gérer les en-têtes avec d’autres composants. C’est la même props attendue par <a href="/?path=/docs/composants-tableau-en-t%C3%AAtes-de-tableau-dsfrtableheaders--en-tetes-de-tableau">DsfrTableHeaders</a>',
Expand All @@ -40,6 +44,14 @@ export default {
action: 'clicked on row',
description: 'Fonction pour montrer le clic sur une ligne (Ici seulement la 2e ligne)',
},
defaultCurrentPage: {
control: 'number',
description: 'Le numéro de la page dans la pagination',
},
defaultOptionSelected: {
control: 'number',
description: 'La sélection du nombre d\'enregistrements par page',
},
},
}

Expand All @@ -49,9 +61,9 @@ const rows = [
[
'EGAUD',
'Pierre-Louis',
'pierre.egaud@ninja.com',
'01 02 03 04 05',
'06 01 02 03 04',
'pierre.egaud@castor.fr',
'02 04 06 08 10',
'06 05 04 03 02',
{
component: 'DsfrTag',
label: 'Erreur',
Expand All @@ -66,9 +78,9 @@ const rows = [
rowData: [
'DEBROIZE',
'Clément',
'clement.debroize@ninja.com',
'01 02 03 04 05',
'06 01 02 03 04',
'clement.debroize@exile.com',
'02 44 66 55 99',
'07 88 77 22 33',
{
component: 'DsfrTag',
label: 'Succès',
Expand All @@ -81,21 +93,168 @@ const rows = [
'Stan',
'[email protected]',
{
text: '01 02 03 04 05',
text: '02 77 00 00 77',
cellAttrs: {
class: 'pointer',
onClick: () => {}, // eslint-disable-line @typescript-eslint/no-empty-function
},
},
'06 01 02 03 04',
'06 08 07 09 08',
{
component: 'DsfrTag',
label: 'Info',
class: 'info',
},
],
[
'MONTANA',
'Tony',
'[email protected]',
'02 07 03 19 84',
'06 07 03 19 84',
{
component: 'DsfrTag',
label: 'Erreur',
class: 'error',
},
],
[
'BOND',
'James',
'[email protected]',
'02 00 07 19 62',
'06 00 07 19 62',
{
component: 'DsfrTag',
label: 'Succès',
class: 'success',
},
],
[
'RAMBO',
'John',
'[email protected]',
'02 00 00 19 82',
'06 00 00 19 82',
{
component: 'DsfrTag',
label: 'Info',
class: 'info',
},
],
[
'CONNOR',
'Sarah',
'[email protected]',
'02 00 00 19 84',
'06 00 00 19 84',
{
component: 'DsfrTag',
label: 'Erreur',
class: 'error',
},
],
[
'KENOBI',
'Obiwan',
'[email protected]',
'02 00 00 19 77',
'06 00 00 19 77',
{
component: 'DsfrTag',
label: 'Succès',
class: 'success',
},
],
[
'KRUEGER',
'Freddy',
'[email protected]',
'02 00 00 19 84',
'06 00 00 19 84',
{
component: 'DsfrTag',
label: 'Info',
class: 'info',
},
],
[
'LEGRIS',
'Gandalf',
'[email protected]',
'02 00 00 20 01',
'06 00 00 20 01',
{
component: 'DsfrTag',
label: 'Erreur',
class: 'error',
},
],
[
'SÖZE',
'Keyser',
'[email protected]',
'02 00 00 19 95',
'06 00 00 19 95',
{
component: 'DsfrTag',
label: 'Info',
class: 'info',
},
],
[
'HUNT',
'Ethan',
'[email protected]',
'02 00 00 19 96',
'06 00 00 19 96',
{
component: 'DsfrTag',
label: 'Erreur',
class: 'error',
},
],
[
'HOLMES',
'Sherlock',
'[email protected]',
'02 00 00 18 87',
'06 00 00 18 87',
{
component: 'DsfrTag',
label: 'Succès',
class: 'success',
},
],
[
'JONES',
'Indiana',
'[email protected]',
'02 00 00 19 81',
'06 00 00 19 81',
{
component: 'DsfrTag',
label: 'Info',
class: 'info',
},
],
[
'WAYNE',
'Bruce',
'[email protected]',
'02 00 00 19 89',
'06 00 00 19 89',
{
component: 'DsfrTag',
label: 'Erreur',
class: 'error',
},
],
]
const noCaption = false
const pagination = true
const defaultCurrentPage = 2
const defaultOptionSelected = 5

export const TableauEntier = (args) => ({
components: {
Expand All @@ -120,6 +279,9 @@ export const TableauEntier = (args) => ({
:headers="headers"
:rows="rows"
:no-caption="noCaption"
:pagination="pagination"
:defaultCurrentPage="defaultCurrentPage"
:defaultOptionSelected="defaultOptionSelected"
/>
`,

Expand All @@ -129,4 +291,7 @@ TableauEntier.args = {
headers,
rows,
noCaption,
pagination,
defaultCurrentPage,
defaultOptionSelected,
}
100 changes: 98 additions & 2 deletions src/components/DsfrTable/DsfrTable.vue
Original file line number Diff line number Diff line change
@@ -1,23 +1,60 @@
<script lang="ts" setup>
import { ref, watch } from 'vue'
import DsfrTableRow, { type DsfrTableRowProps } from './DsfrTableRow.vue'
import DsfrTableHeaders from './DsfrTableHeaders.vue'
import { type DsfrTableHeaderProps } from './DsfrTableHeader.vue'
withDefaults(defineProps<{
const props = withDefaults(defineProps<{
title?: string
headers?:(DsfrTableHeaderProps | string)[]
rows?: (DsfrTableRowProps | string)[]
noCaption?: boolean
pagination?: boolean
defaultCurrentPage?: number
defaultOptionSelected?: number
}>(), {
title: undefined,
headers: () => [],
rows: () => [],
defaultCurrentPage: 1,
defaultOptionSelected: 10,
})
const getRowData = (row: (DsfrTableRowProps | string | ({component: string} & Record<string, any>))) => {
// @ts-ignore TODO: find a way to improve types here
return row.rowData || row
}
const currentPage = ref(props.defaultCurrentPage)
const optionSelected = ref(props.defaultOptionSelected)
const pageCount = ref(props.rows.length > optionSelected.value ? Math.ceil(props.rows.length / optionSelected.value) : 1)
const paginationOptions = [5, 10, 25, 50, 100]
const returnLowestLimit = () => currentPage.value * optionSelected.value - optionSelected.value
const returnHighestLimit = () => currentPage.value * optionSelected.value
let truncatedResults = props.rows.slice(returnLowestLimit(), returnHighestLimit())
watch(() => optionSelected.value, (newVal, OldVal) => {
props.rows.length > optionSelected.value ? pageCount.value = Math.ceil(props.rows.length / newVal) : pageCount.value = 1
truncatedResults = props.rows.slice(returnLowestLimit(), returnHighestLimit())
})
watch(() => currentPage.value, (newVal, OldVal) => {
truncatedResults = props.rows.slice(returnLowestLimit(), returnHighestLimit())
})
const goFirstPage = () => { currentPage.value = 1 }
const goPreviousPage = () => {
if (currentPage.value > 1) {
currentPage.value -= 1
}
}
const goNextPage = () => {
if (currentPage.value < pageCount.value) {
currentPage.value += 1
}
}
const goLastPage = () => { currentPage.value = pageCount.value }
</script>

<template>
Expand Down Expand Up @@ -45,13 +82,72 @@ const getRowData = (row: (DsfrTableRowProps | string | ({component: string} & Re
<slot />
<template v-if="rows && rows.length">
<DsfrTableRow
v-for="(row, i) of rows"
v-for="(row, i) of truncatedResults"
:key="i"
:row-data="getRowData(row)"
:row-attrs="typeof row === 'string' ? {} : row.rowAttrs"
/>
</template>
<tr v-if="pagination">
<td :colspan="headers.length">
<div class="flex justify-right">
<div class="self-center">
<span>Résultats par page : </span>
<select
v-model="optionSelected"
>
<option
v-for="(option, idx) in paginationOptions"
:key="idx"
:value="option"
>
{{ option }}
</option>
</select>
</div>
<div class="flex ml-1">
<span class="self-center">Page {{ currentPage }} sur {{ pageCount }}</span>
</div>
<div class="flex ml-1">
<button
class="fr-icon-arrow-left-s-first-line"
@click="goFirstPage()"
/>
<button
class="fr-icon-arrow-left-s-line-double"
@click="goPreviousPage()"
/>
<button
class="fr-icon-arrow-right-s-line-double"
@click="goNextPage()"
/>
<button
class="fr-icon-arrow-right-s-last-line"
@click="goLastPage()"
/>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</template>

<style scoped>
.flex {
display: flex;
}
.justify-right {
justify-content: right;
}
.ml-1 {
margin-left: 1rem;
}
.self-center {
align-self: center;
}
</style>

0 comments on commit 37c7c85

Please sign in to comment.