Skip to content

Commit

Permalink
New form system and harvester form (#238)
Browse files Browse the repository at this point in the history
- Publication flow for harvesters
- Update an harvester
- Preview an harvester
- New form system (explanation in french below)
    - Gestion automatique de l'accordéon d'aide :
        - pas besoin de définir un ID
- ils sont présent à côté de l'input dans le code (donc ordonné
correctement, et plus facilement modifiable en même temps qu'un label
par exemple)
- gère automatiquement son state en fonction de son input (plus besoin
de la fonction `accordionState`)
    - Gestion automatique des erreurs / warnings
        - plus besoin de set `has-error` `has-warning` et `text-error`
- appelle automatique de la fonction `touch()` lors du changement de
focus
    - Simplification du HTML
        - abstraction des fieldset / legend qui étaient assez verbeux
- création d'une balise `form` au début pour utiliser le `@submit`
plutôt que le `@click` sur le bouton final
- Remove `BannerActionButton`. This component was a little simplistic
for its usage. Thanks to inject/provide we can now use the much more
complete component `BrandedButton` and inherit the correct styles for
the banner type.

TODO (maybe in another PR) :
- [x] improve label management for inputs without labels (a18n)
- [ ] Add `auto_archived` and `activated` toggles in harvesters forms
- [ ] Remove filters and configs if we change the type of implementation
to avoid validation errors
- [ ] Add tooltip to icons in
https://github.com/datagouv/front-end/pull/238/files#diff-74a4ae793ec28f9ce19aeac456d0c8b3cd8731ef88d19f367c3f1b1aad1ada53R25-R45
- [ ] Better message "(previews limit the number of items returned)"
- [ ] auto-refresh the table when clicking "Run" button
- [ ] auto-refresh of the items in the job page if the job is running
  • Loading branch information
ThibaudDauce authored Jan 9, 2025
1 parent 606c421 commit 64f449b
Show file tree
Hide file tree
Showing 38 changed files with 1,553 additions and 376 deletions.
12 changes: 5 additions & 7 deletions components/Accordion/Accordion.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
<h3 class="fr-accordion__title !mb-0">
<DisclosureButton
class="fr-accordion__btn !text-neutral-900"
:aria-expanded="expanded"
:aria-expanded="isOpen(accordionId)"
:aria-controls="accordionId"
@click="toggle"
@click="toggle(accordionId)"
>
<component
:is="icon"
Expand All @@ -21,7 +21,7 @@
</DisclosureButton>
</h3>
<DisclosurePanel
v-show="expanded"
v-show="isOpen(accordionId)"
:id="accordionId"
class="px-4 pt-4 pb-6"
static
Expand All @@ -46,9 +46,7 @@ const props = withDefaults(defineProps<{
state: 'default',
})
const register = inject(key) as AccordionRegister
const { expanded, toggle, unregister } = register()
const { isOpen, toggle, unregister } = inject(key) as AccordionRegister
const accordionId = props.id || useId()
const icon = computed(() => {
Expand Down Expand Up @@ -81,5 +79,5 @@ const iconColor = computed(() => {
return 'text-neutral-500'
}
})
onUnmounted(unregister)
onUnmounted(() => unregister(accordionId))
</script>
33 changes: 20 additions & 13 deletions components/Accordion/AccordionGroup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,30 @@ withDefaults(defineProps<{
as: 'div',
})
const opened = ref<symbol | null>(null)
const opened = ref<string | null>(null)
provide(key, () => {
const id = Symbol()
provide(key, {
isOpen(id: string) {
return opened.value === id
},
return {
expanded: computed(() => opened.value === id),
open(id: string) {
opened.value = id
},
toggle() {
toggle(id: string) {
if (opened.value === id) {
opened.value = null
}
else {
opened.value = id
},
}
},
unregister() {
if (opened.value === id) {
opened.value = null
}
},
}
unregister(id: string) {
if (opened.value === id) {
opened.value = null
}
},
})
</script>
9 changes: 5 additions & 4 deletions components/Accordion/injectionKey.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export type AccordionRegister = () => {
expanded: ComputedRef<boolean>
toggle: () => void
unregister: () => void
export type AccordionRegister = {
isOpen(id: string): boolean
toggle: (id: string) => void
open: (id: string) => void
unregister: (id: string) => void
}
export const key = Symbol() as InjectionKey<AccordionRegister>
2 changes: 1 addition & 1 deletion components/AdminPublishButton/AdminPublishButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const link = computed(() => {
case 'dataset':
return '/beta/admin/datasets/new'
case 'harvester':
return `/admin/harvester/new/`
return `/beta/admin/harvesters/new/`
case 'reuse':
return '/beta/admin/reuses/new'
case 'dataservice':
Expand Down
21 changes: 10 additions & 11 deletions components/AdminSidebar/AdminSidebarMenu/AdminSidebarMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
<Disclosure>
<li
class="fr-sidemenu__item"
:class="{ 'fr-sidemenu__item--active': expanded }"
:class="{ 'fr-sidemenu__item--active': isOpen(id) }"
>
<DisclosureButton
class="fr-sidemenu__btn"
:aria-current="expanded"
:aria-expanded="expanded"
@click="toggle"
:aria-current="isOpen(id)"
:aria-expanded="isOpen(id)"
@click="toggle(id)"
>
<template v-if="user">
<Avatar
Expand Down Expand Up @@ -41,7 +41,7 @@
</template>
</DisclosureButton>
<DisclosurePanel
v-show="expanded"
v-show="isOpen(id)"
static
>
<ul class="fr-sidemenu__list !mx-2 !my-3">
Expand Down Expand Up @@ -194,17 +194,16 @@ defineEmits<{
click: []
}>()
const register = inject(key) as AccordionRegister
const id = useId()
const { isOpen, open, toggle, unregister } = inject(key) as AccordionRegister
const { expanded, toggle, unregister } = register()
watchEffect(() => {
onMounted(() => {
if (props.defaultOpen) {
toggle()
open(id)
}
})
onUnmounted(unregister)
onUnmounted(() => unregister(id))
</script>

<style scoped>
Expand Down
8 changes: 7 additions & 1 deletion components/BannerAction.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,15 @@
</div>
</template>

<script lang="ts">
export const bannerActionTypeKey = Symbol() as InjectionKey<'primary' | 'danger' | 'warning'>
</script>

<script setup lang="ts">
defineProps<{
const props = defineProps<{
type: 'primary' | 'danger' | 'warning'
title: string
}>()
provide(bannerActionTypeKey, props.type)
</script>
29 changes: 0 additions & 29 deletions components/BannerActionButton.vue

This file was deleted.

44 changes: 33 additions & 11 deletions components/BrandedButton/BrandedButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
aria-disabled="isDisabled"
:role="href ? 'link' : ''"
:to="isDisabled ? undefined : href"
:target="newTab ? '_blank' : undefined"
>
<AdminLoader
v-if="loading"
Expand All @@ -31,49 +32,70 @@ import type {
Slot,
VNode,
} from 'vue'
import {
Comment,
Text,
} from 'vue'
import { bannerActionTypeKey } from '~/components/BannerAction.vue'
import { NuxtLinkLocale } from '#components'
type ColorType = 'primary' | 'primary-soft' | 'secondary' | 'warning' | 'danger'
const props = withDefaults(defineProps<{
size?: 'xs' | 'sm'
color?: 'primary' | 'secondary' | 'danger'
color?: ColorType
disabled?: boolean
loading?: boolean
icon?: Component
href?: string
newTab?: boolean
}>(), {
as: 'button',
color: 'primary',
size: 'sm',
level: 'primary',
newTab: false,
})
const slots = useSlots()
const size = computed(() => {
if (props.size) return props.size
if (bannerActionType) return 'xs'
return 'sm'
})
const color = computed<ColorType>(() => {
if (props.color) return props.color
if (bannerActionType) {
return {
primary: 'primary-soft' as ColorType,
warning: 'warning' as ColorType,
danger: 'danger' as ColorType,
}[bannerActionType]
}
return 'primary'
})
const hasText = computed(() => {
return hasSlotContent(slots.default)
})
const bannerActionType = inject(bannerActionTypeKey, null)
const isDisabled = computed(() => props.disabled || props.loading)
const colors = computed(() => {
return {
primary: `text-white bg-datagouv-dark !border-datagouv-dark ${!isDisabled.value ? 'hover:!bg-datagouv-hover hover:!border-datagouv-hover' : ''}`,
secondary: `text-gray-plain bg-white !border-gray-plain ${!isDisabled.value ? '[&&]:hover:!bg-gray-some' : ''}`,
danger: `!text-danger-dark bg-white !border-danger-dark ${!isDisabled.value ? '[&&]:hover:!bg-gray-some' : ''}`,
}[props.color]
'primary': `text-white bg-datagouv-dark !border-datagouv-dark ${!isDisabled.value ? 'hover:!bg-datagouv-hover hover:!border-datagouv-hover' : ''}`,
'primary-soft': `text-datagouv-dark bg-white !border-datagouv-dark ${!isDisabled.value ? '[&&]:hover:!bg-gray-some' : ''}`,
'secondary': `text-gray-plain bg-white !border-gray-plain ${!isDisabled.value ? '[&&]:hover:!bg-gray-some' : ''}`,
'warning': `text-warning-dark bg-white !border-warning-dark ${!isDisabled.value ? '[&&]:hover:!bg-gray-some' : ''}`,
'danger': `!text-danger-dark bg-white !border-danger-dark ${!isDisabled.value ? '[&&]:hover:!bg-gray-some' : ''}`,
}[color.value]
})
const sizes = computed(() => {
return {
sm: `text-sm leading-none ${hasText.value ? 'px-4 py-3' : 'p-2.5'}`,
xs: `text-xs leading-[0.875rem] ${hasText.value ? 'px-4 py-2' : 'p-2'}`,
}[props.size]
}[size.value]
})
function hasSlotContent(slot: Slot | undefined, slotProps = {}): boolean {
Expand Down
5 changes: 3 additions & 2 deletions components/Dataservices/AdminUpdateDataservicePage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@
{{ $t("An archived dataservice is no longer indexed but still accessible for users with the direct link.") }}

<template #button>
<BannerActionButton
<BrandedButton
:icon="RiArchiveLine"
type="button"
@click="archiveDataservice"
>
{{ dataservice.archived_at ? $t('Unarchive') : $t('Archive') }}
</BannerActionButton>
</BrandedButton>
</template>
</BannerAction>
<BannerAction
Expand Down Expand Up @@ -83,6 +83,7 @@
<script setup lang="ts">
import type { Dataservice } from '@datagouv/components'
import { RiArchiveLine, RiDeleteBin6Line } from '@remixicon/vue'
import BrandedButton from '../BrandedButton/BrandedButton.vue'
import DescribeDataservice from '~/components/Dataservices/DescribeDataservice.vue'
import type { ContactPoint, DataserviceForm, LinkToSubject } from '~/types/types'
import { toForm, toApi } from '~/utils/dataservices'
Expand Down
9 changes: 5 additions & 4 deletions components/Datasets/AdminUpdateDatasetPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@
{{ $t("An archived dataset is no longer indexed but still accessible for users with the direct link.") }}

<template #button>
<BannerActionButton
<BrandedButton
:icon="RiArchiveLine"
type="button"
@click="archiveDataset"
>
{{ dataset.archived ? $t('Unarchive') : $t('Archive') }}
</BannerActionButton>
</BrandedButton>
</template>
</BannerAction>
<BannerAction
Expand All @@ -41,13 +41,13 @@
size="lg"
>
<template #button="{ attrs, listeners }">
<BannerActionButton
<BrandedButton
:icon="RiDeleteBin6Line"
v-bind="attrs"
v-on="listeners"
>
{{ $t('Delete') }}
</BannerActionButton>
</BrandedButton>
</template>
<p class="fr-text--bold">
{{ $t("This action can't be reverse.") }}
Expand All @@ -74,6 +74,7 @@
<script setup lang="ts">
import type { Dataset, Frequency, License } from '@datagouv/components'
import { RiArchiveLine, RiDeleteBin6Line } from '@remixicon/vue'
import BrandedButton from '../BrandedButton/BrandedButton.vue'
import DescribeDataset from '~/components/Datasets/DescribeDataset.vue'
import type { DatasetForm, EnrichedLicense, SpatialGranularity } from '~/types/types'
import { toForm, toApi } from '~/utils/datasets'
Expand Down
4 changes: 2 additions & 2 deletions components/DesignSystem/BannerAction.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
Attention cette action est irréversible

<template #button>
<BannerActionButton :icon="RiSendPlaneLine">
<BrandedButton :icon="RiSendPlaneLine">
Transférer
</BannerActionButton>
</BrandedButton>
</template>
</BannerAction>
</div>
Expand Down
2 changes: 1 addition & 1 deletion components/DesignSystem/BrandedButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
class="space-y-5"
>
<div
v-for="color in ['primary', 'secondary', 'danger']"
v-for="color in ['primary', 'primary-soft', 'secondary', 'warning', 'danger']"
:key="color"
class="space-y-5"
>
Expand Down
Loading

0 comments on commit 64f449b

Please sign in to comment.