feat(setting): implémenter la suppression d'une ContentSource
- Ajoute DeleteContentSourceCommand + CommandHandler (CQRS)
- Expose DELETE /api/content-sources/{id} via API Platform (Resource, Provider, Processor)
- Ajoute 2 tests Feature (204 succès, 404 not found)
- Frontend : méthode delete() dans le repository, action deleteSource() dans le store
- Nouveau composant ContentSourceDeleteModal (modale de confirmation)
- Bouton Supprimer dans la toolbar de ScrapperEdit (visible en mode édition uniquement)
This commit is contained in:
parent
36f873aaca
commit
fc4ab68e8b
@@ -176,6 +176,15 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Delete Modal -->
|
||||
<ContentSourceDeleteModal
|
||||
:is-open="isDeleteModalOpen"
|
||||
:source="currentSource"
|
||||
:is-loading="isDeleting"
|
||||
:error="deleteError"
|
||||
@close="isDeleteModalOpen = false"
|
||||
@confirm="confirmDeleteSource" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -185,6 +194,7 @@ import {
|
||||
CheckCircleIcon,
|
||||
ExclamationTriangleIcon,
|
||||
PencilSquareIcon,
|
||||
TrashIcon,
|
||||
XCircleIcon,
|
||||
XMarkIcon
|
||||
} from '@heroicons/vue/24/outline';
|
||||
@@ -194,6 +204,7 @@ import { useRoute, useRouter } from 'vue-router';
|
||||
import Toolbar from '../../../../shared/components/ui/Toolbar.vue';
|
||||
import { useContentSourceStore } from '../../application/store/contentSourceStore';
|
||||
import { ApiContentSourceRepository } from '../../infrastructure/api/apiContentSourceRepository';
|
||||
import ContentSourceDeleteModal from '../components/ContentSourceDeleteModal.vue';
|
||||
import ContentSourceForm from '../components/ContentSourceForm.vue';
|
||||
|
||||
const route = useRoute();
|
||||
@@ -217,6 +228,9 @@ const showTestResults = ref(false);
|
||||
const showSuccessMessage = ref(false);
|
||||
const testResults = ref({});
|
||||
const testingConfiguration = ref(false);
|
||||
const isDeleteModalOpen = ref(false);
|
||||
const isDeleting = ref(false);
|
||||
const deleteError = ref(null);
|
||||
|
||||
const isEditing = computed(() => !!route.params.id);
|
||||
|
||||
@@ -238,6 +252,7 @@ const toolbarConfig = computed(() => ({
|
||||
{ type: 'label', text: isEditing.value ? 'Modifier la configuration' : 'Nouvelle configuration', class: 'text-sm font-medium' },
|
||||
],
|
||||
rightSection: [
|
||||
...(isEditing.value ? [{ type: 'button', icon: TrashIcon, label: 'Supprimer', onClick: () => { isDeleteModalOpen.value = true; }, class: 'text-red-600 hover:text-red-700' }, { type: 'divider' }] : []),
|
||||
{ type: 'button', icon: PencilSquareIcon, label: isEditing.value ? 'Mettre à jour' : 'Créer', onClick: () => formRef.value?.submitForm(), disabled: saving.value },
|
||||
],
|
||||
}));
|
||||
@@ -328,6 +343,21 @@ const handleImageLoad = (event) => {
|
||||
event.target.style.display = 'block';
|
||||
};
|
||||
|
||||
const confirmDeleteSource = async () => {
|
||||
isDeleting.value = true;
|
||||
deleteError.value = null;
|
||||
|
||||
try {
|
||||
await contentSourceStore.deleteSource(route.params.id);
|
||||
isDeleteModalOpen.value = false;
|
||||
await router.push({ name: 'scrapper-configurations' });
|
||||
} catch (error) {
|
||||
deleteError.value = error.message;
|
||||
} finally {
|
||||
isDeleting.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const formatErrorType = (type) => {
|
||||
const typeMap = {
|
||||
'selector_error': 'Erreur sélecteur',
|
||||
|
||||
Reference in New Issue
Block a user