Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 158 additions & 0 deletions components/Admin/AdminDeleteModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
<template>
<ModalWithButton
v-model="isOpen"
:title
size="lg"
>
<template #button="{ attrs, listeners }">
<slot
name="button"
:attrs="attrs"
:listeners="listeners"
/>
</template>

<template v-if="!deleted">
<slot />

<div
v-if="isMeAdmin()"
class="mt-6 pt-4 border-t border-default-grey"
>
<RadioButtons
v-model="mailOption"
:label="$t('Notification par email')"
:options="mailOptions"
/>
</div>
</template>

<template v-else-if="mailOption === 'custom'">
<div class="flex flex-col items-center gap-4 py-6">
<div class="flex items-center gap-2 text-success-dark">
<RiCheckLine class="size-6" />
<span class="font-bold">{{ $t('Suppression effectuée') }}</span>
</div>
<p class="text-center text-mention-grey">
{{ $t("Vous pouvez maintenant envoyer un mail personnalisé au propriétaire.") }}
</p>
<a
:href="mailtoLink"
class="fr-btn fr-btn--secondary"
target="_blank"
>
{{ $t('Envoyer le mail personnalisé') }}
</a>
</div>
</template>

<template #footer="{ close: closeModal }">
<div class="w-full flex justify-end gap-4">
<BrandedButton
v-if="!deleted"
color="secondary"
:disabled="loading"
@click="closeModal"
>
{{ $t('Annuler') }}
</BrandedButton>
<BrandedButton
v-if="!deleted"
color="danger"
:loading
:disabled="isMeAdmin() && !mailOption"
@click="() => handleDelete(closeModal)"
>
{{ deleteButtonLabel }}
</BrandedButton>
<BrandedButton
v-else
@click="handleClose(closeModal)"
>
{{ $t('Fermer') }}
</BrandedButton>
</div>
</template>
</ModalWithButton>
</template>

<script setup lang="ts">
import { BrandedButton } from '@datagouv/components-next'
import { RiCheckLine } from '@remixicon/vue'
import { isMeAdmin } from '~/utils/auth'
import { useDeleteMailto } from '~/composables/useDeleteMailto'
import RadioButtons from '~/components/RadioButtons.vue'

type MailOption = 'auto' | 'custom'
type ObjectType = 'dataset' | 'reuse' | 'dataservice' | 'organization' | 'user' | 'discussion' | 'comment'

const props = withDefaults(defineProps<{
title: string
deleteUrl: string
deleteButtonLabel?: string
recipientEmail?: string | null
objectType: ObjectType
objectTitle?: string
}>(), {
recipientEmail: null,
})

const emit = defineEmits<{
deleted: []
}>()

const { t } = useTranslation()
const { $api } = useNuxtApp()
const { generateMailtoLink } = useDeleteMailto()

const isOpen = ref(false)
const loading = ref(false)
const deleted = ref(false)
const mailOption = ref<MailOption | null>(null)

const mailOptions = computed(() => [
{ value: 'auto' as const, label: t('Envoyer un mail automatique (voies de recours)') },
{ value: 'custom' as const, label: t('Envoyer un mail personnalisé') },
])

const mailtoLink = computed(() => {
return generateMailtoLink(props.recipientEmail || '', props.objectType, props.objectTitle)
})

const deleteButtonLabel = computed(() => props.deleteButtonLabel || t('Supprimer'))

watch(isOpen, (newVal) => {
if (!newVal) {
deleted.value = false
mailOption.value = null
}
})

async function handleDelete(closeModal: () => void) {
loading.value = true
try {
let url = props.deleteUrl
if (isMeAdmin() && mailOption.value === 'auto') {
url += url.includes('?') ? '&send_legal_notice=true' : '?send_legal_notice=true'
}

await $api(url, { method: 'DELETE' })

if (isMeAdmin() && mailOption.value === 'custom') {
deleted.value = true
}
else {
closeModal()
}

emit('deleted')
}
finally {
loading.value = false
}
}

function handleClose(closeModal: () => void) {
closeModal()
}
</script>
41 changes: 14 additions & 27 deletions components/Dataservices/AdminUpdateDataservicePage.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<LoadingBlock
v-slot="{ data: dataservice }"

Check warning on line 3 in components/Dataservices/AdminUpdateDataservicePage.vue

View workflow job for this annotation

GitHub Actions / check-cdata-quality

Variable 'dataservice' is already declared in the upper scope
:status
:data="dataservice"
>
Expand Down Expand Up @@ -101,9 +101,14 @@
>
{{ $t("Attention, cette action ne peut pas être annulée.") }}
<template #button>
<ModalWithButton
<AdminDeleteModal
:title="$t('Êtes-vous sûr de vouloir supprimer cette API ?')"
size="lg"
:delete-url="`/api/1/dataservices/${route.params.id}`"
:delete-button-label="$t(`Supprimer l'API`)"
:recipient-email="getOwnerEmail(dataservice)"
object-type="dataservice"
:object-title="dataservice.title"
@deleted="onDataserviceDeleted"
>
<template #button="{ attrs, listeners }">
<BrandedButton
Expand All @@ -119,18 +124,7 @@
<p class="fr-text--bold">
{{ $t("Cette action est irréversible.") }}
</p>
<template #footer>
<div class="flex-1 flex justify-end">
<BrandedButton
color="danger"
:loading="isLoading"
@click="deleteDataservice"
>
{{ $t("Supprimer l'API") }}
</BrandedButton>
</div>
</template>
</ModalWithButton>
</AdminDeleteModal>
</template>
</BannerAction>
</div>
Expand All @@ -143,7 +137,9 @@
import type { Dataservice } from '@datagouv/components-next'
import { RiArchiveLine, RiArrowGoBackLine, RiDeleteBin6Line } from '@remixicon/vue'
import DescribeDataservice from '~/components/Dataservices/DescribeDataservice.vue'
import AdminDeleteModal from '~/components/Admin/AdminDeleteModal.vue'
import type { DataserviceForm } from '~/types/types'
import { getOwnerEmail } from '~/utils/owner'

const { t } = useTranslation()
const { $api } = useNuxtApp()
Expand Down Expand Up @@ -251,19 +247,10 @@
}
}

async function deleteDataservice() {
start()
try {
await $api(`/api/1/dataservices/${route.params.id}`, {
method: 'DELETE',
})
refresh()
toast.success(t('API supprimée !'))
window.scrollTo({ top: 0, left: 0, behavior: 'smooth' })
}
finally {
finish()
}
function onDataserviceDeleted() {
refresh()
toast.success(t('API supprimée !'))
window.scrollTo({ top: 0, left: 0, behavior: 'smooth' })
}

async function feature() {
Expand Down
41 changes: 14 additions & 27 deletions components/Datasets/AdminUpdateDatasetPage.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<LoadingBlock
v-slot="{ data: dataset }"

Check warning on line 3 in components/Datasets/AdminUpdateDatasetPage.vue

View workflow job for this annotation

GitHub Actions / check-cdata-quality

Variable 'dataset' is already declared in the upper scope
:status
:data="dataset"
>
Expand Down Expand Up @@ -95,9 +95,14 @@
{{ $t("Attention, cette action ne peut pas être annulée.") }}

<template #button>
<ModalWithButton
<AdminDeleteModal
:title="$t('Êtes-vous sûr de vouloir supprimer ce jeu de données ?')"
size="lg"
:delete-url="`/api/1/datasets/${route.params.id}`"
:delete-button-label="$t('Supprimer le jeu de données')"
:recipient-email="getOwnerEmail(dataset)"
object-type="dataset"
:object-title="dataset.title"
@deleted="onDatasetDeleted"
>
<template #button="{ attrs, listeners }">
<BrandedButton
Expand All @@ -112,18 +117,7 @@
<p class="fr-text--bold">
{{ $t("Cette action est irréversible.") }}
</p>
<template #footer>
<div class="flex-1 flex justify-end">
<BrandedButton
color="danger"
:loading="isLoading"
@click="deleteDataset"
>
{{ $t("Supprimer le jeu de données") }}
</BrandedButton>
</div>
</template>
</ModalWithButton>
</AdminDeleteModal>
</template>
</BannerAction>
</div>
Expand All @@ -136,7 +130,9 @@
import type { DatasetV2WithFullObject } from '@datagouv/components-next'
import { RiArchiveLine, RiArrowGoBackLine, RiDeleteBin6Line } from '@remixicon/vue'
import DescribeDataset from '~/components/Datasets/DescribeDataset.vue'
import AdminDeleteModal from '~/components/Admin/AdminDeleteModal.vue'
import type { DatasetForm } from '~/types/types'
import { getOwnerEmail } from '~/utils/owner'

const { t } = useTranslation()
const { $api } = useNuxtApp()
Expand Down Expand Up @@ -191,19 +187,10 @@
}
}

async function deleteDataset() {
start()
try {
await $api(`/api/1/datasets/${route.params.id}`, {
method: 'DELETE',
})
refresh()
toast.success(t('Jeu de données supprimé !'))
window.scrollTo({ top: 0, left: 0, behavior: 'smooth' })
}
finally {
finish()
}
function onDatasetDeleted() {
refresh()
toast.success(t('Jeu de données supprimé !'))
window.scrollTo({ top: 0, left: 0, behavior: 'smooth' })
}

async function switchDatasetPrivate() {
Expand Down
Loading
Loading