mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-28 23:43:22 +00:00
feat: Suppression des templates docuseal [#22]
This commit is contained in:
@ -1,7 +1,8 @@
|
||||
from django.urls import path, re_path
|
||||
from .views import generate_jwt_token, clone_template
|
||||
from .views import generate_jwt_token, clone_template, remove_template
|
||||
|
||||
urlpatterns = [
|
||||
re_path(r'generateToken$', generate_jwt_token, name='generate_jwt_token'),
|
||||
re_path(r'cloneTemplate$', clone_template, name='clone_template'),
|
||||
re_path(r'removeTemplate/(?P<id>[0-9]+)$', remove_template, name='remove_template'),
|
||||
]
|
||||
|
||||
@ -71,7 +71,7 @@ def clone_template(request):
|
||||
'X-Auth-Token': settings.DOCUSEAL_JWT['API_KEY']
|
||||
})
|
||||
|
||||
if response.status_code != 200:
|
||||
if response.status_code != status.HTTP_200_OK:
|
||||
return Response({'error': 'Failed to clone template'}, status=response.status_code)
|
||||
|
||||
data = response.json()
|
||||
@ -79,3 +79,29 @@ def clone_template(request):
|
||||
|
||||
except requests.RequestException as e:
|
||||
return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
|
||||
@csrf_exempt
|
||||
@api_view(['DELETE'])
|
||||
def remove_template(request, id):
|
||||
# Vérifier la clé API
|
||||
api_key = request.headers.get('X-Auth-Token')
|
||||
if not api_key or api_key != settings.DOCUSEAL_JWT["API_KEY"]:
|
||||
return Response({'error': 'Invalid API key'}, status=status.HTTP_401_UNAUTHORIZED)
|
||||
|
||||
# URL de l'API de DocuSeal pour cloner le template
|
||||
clone_url = f'https://docuseal.com/api/templates/{id}'
|
||||
|
||||
# Faire la requête pour cloner le template
|
||||
try:
|
||||
response = requests.delete(clone_url, headers={
|
||||
'X-Auth-Token': settings.DOCUSEAL_JWT['API_KEY']
|
||||
})
|
||||
|
||||
if response.status_code != status.HTTP_200_OK:
|
||||
return Response({'error': 'Failed to remove template'}, status=response.status_code)
|
||||
|
||||
data = response.json()
|
||||
return Response(data, status=status.HTTP_200_OK)
|
||||
|
||||
except requests.RequestException as e:
|
||||
return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
@ -44,7 +44,7 @@ class RegistrationTemplateMasterSimpleView(APIView):
|
||||
}
|
||||
)
|
||||
def get(self, request, id):
|
||||
master = bdd.getObject(_objectName=RegistrationTemplateMaster, _columnName='id', _value=id)
|
||||
master = bdd.getObject(_objectName=RegistrationTemplateMaster, _columnName='template_id', _value=id)
|
||||
if master is None:
|
||||
return JsonResponse({"errorMessage":'Le master de template n\'a pas été trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND)
|
||||
serializer = RegistrationTemplateMasterSerializer(master)
|
||||
@ -60,7 +60,7 @@ class RegistrationTemplateMasterSimpleView(APIView):
|
||||
}
|
||||
)
|
||||
def put(self, request, id):
|
||||
master = bdd.getObject(_objectName=RegistrationTemplateMaster, _columnName='id', _value=id)
|
||||
master = bdd.getObject(_objectName=RegistrationTemplateMaster, _columnName='template_id', _value=id)
|
||||
if master is None:
|
||||
return JsonResponse({'erreur': 'Le master de template n\'a pas été trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND)
|
||||
serializer = RegistrationTemplateMasterSerializer(master, data=request.data)
|
||||
@ -77,7 +77,7 @@ class RegistrationTemplateMasterSimpleView(APIView):
|
||||
}
|
||||
)
|
||||
def delete(self, request, id):
|
||||
master = bdd.getObject(_objectName=RegistrationTemplateMaster, _columnName='id', _value=id)
|
||||
master = bdd.getObject(_objectName=RegistrationTemplateMaster, _columnName='template_id', _value=id)
|
||||
if master is not None:
|
||||
master.delete()
|
||||
return JsonResponse({'message': 'La suppression du master de template a été effectuée avec succès'}, safe=False, status=status.HTTP_204_NO_CONTENT)
|
||||
@ -118,7 +118,7 @@ class RegistrationTemplateSimpleView(APIView):
|
||||
}
|
||||
)
|
||||
def get(self, request, id):
|
||||
template = bdd.getObject(_objectName=RegistrationTemplate, _columnName='id', _value=id)
|
||||
template = bdd.getObject(_objectName=RegistrationTemplate, _columnName='template_id', _value=id)
|
||||
if template is None:
|
||||
return JsonResponse({"errorMessage":'Le template d\'inscription n\'a pas été trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND)
|
||||
serializer = RegistrationTemplateSerializer(template)
|
||||
@ -134,7 +134,7 @@ class RegistrationTemplateSimpleView(APIView):
|
||||
}
|
||||
)
|
||||
def put(self, request, id):
|
||||
template = bdd.getObject(_objectName=RegistrationTemplate, _columnName='id', _value=id)
|
||||
template = bdd.getObject(_objectName=RegistrationTemplate, _columnName='template_id', _value=id)
|
||||
if template is None:
|
||||
return JsonResponse({'erreur': 'Le template d\'inscription n\'a pas été trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND)
|
||||
serializer = RegistrationTemplateSerializer(template, data=request.data)
|
||||
@ -151,7 +151,7 @@ class RegistrationTemplateSimpleView(APIView):
|
||||
}
|
||||
)
|
||||
def delete(self, request, id):
|
||||
template = bdd.getObject(_objectName=RegistrationTemplate, _columnName='id', _value=id)
|
||||
template = bdd.getObject(_objectName=RegistrationTemplate, _columnName='template_id', _value=id)
|
||||
if template is not None:
|
||||
template.delete()
|
||||
return JsonResponse({'message': 'La suppression du template a été effectuée avec succès'}, safe=False, status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
@ -23,7 +23,9 @@ import { createDatas,
|
||||
fetchTuitionPaymentModes } from '@/app/actions/schoolAction';
|
||||
import SidebarTabs from '@/components/SidebarTabs';
|
||||
import FilesGroupsManagement from '@/components/Structure/Files/FilesGroupsManagement';
|
||||
import { fetchRegistrationTemplateMaster } from '@/app/actions/subscriptionAction';
|
||||
import {
|
||||
fetchRegistrationTemplateMaster
|
||||
} from "@/app/actions/registerFileGroupAction";
|
||||
import logger from '@/utils/logger';
|
||||
|
||||
|
||||
|
||||
@ -24,10 +24,13 @@ import {
|
||||
createRegisterForm,
|
||||
sendRegisterForm,
|
||||
archiveRegisterForm,
|
||||
fetchRegistrationTemplateMaster,
|
||||
fetchStudents,
|
||||
editRegisterForm } from "@/app/actions/subscriptionAction"
|
||||
|
||||
import {
|
||||
fetchRegistrationTemplateMaster
|
||||
} from "@/app/actions/registerFileGroupAction";
|
||||
|
||||
import {
|
||||
fetchClasses,
|
||||
fetchRegistrationDiscounts,
|
||||
|
||||
@ -1,4 +1,19 @@
|
||||
import { BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL } from '@/utils/Url';
|
||||
import { BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL,
|
||||
BE_SUBSCRIPTION_REGISTRATION_TEMPLATES_URL,
|
||||
BE_SUBSCRIPTION_REGISTRATION_TEMPLATE_MASTER_URL
|
||||
} from '@/utils/Url';
|
||||
|
||||
const requestResponseHandler = async (response) => {
|
||||
|
||||
const body = await response.json();
|
||||
if (response.ok) {
|
||||
return body;
|
||||
}
|
||||
// Throw an error with the JSON body containing the form errors
|
||||
const error = new Error('Form submission error');
|
||||
error.details = body;
|
||||
throw error;
|
||||
}
|
||||
|
||||
export async function fetchRegistrationFileGroups() {
|
||||
const response = await fetch(`${BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL}`, {
|
||||
@ -72,3 +87,110 @@ export const fetchRegistrationFileFromGroup = async (groupId) => {
|
||||
}
|
||||
return response.json();
|
||||
}
|
||||
|
||||
export const fetchRegistrationTemplates = (id = null) => {
|
||||
let url = `${BE_SUBSCRIPTION_REGISTRATION_TEMPLATES_URL}`
|
||||
if (id) {
|
||||
url = `${BE_SUBSCRIPTION_REGISTRATION_TEMPLATES_URL}/${id}`;
|
||||
}
|
||||
const request = new Request(
|
||||
`${url}`,
|
||||
{
|
||||
method:'GET',
|
||||
headers: {
|
||||
'Content-Type':'application/json'
|
||||
},
|
||||
}
|
||||
);
|
||||
return fetch(request).then(requestResponseHandler)
|
||||
};
|
||||
|
||||
export const editRegistrationTemplates = (fileId, data, csrfToken) => {
|
||||
return fetch(`${BE_SUBSCRIPTION_REGISTRATION_TEMPLATES_URL}/${fileId}`, {
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
headers: {
|
||||
'X-CSRFToken': csrfToken,
|
||||
},
|
||||
credentials: 'include',
|
||||
})
|
||||
.then(requestResponseHandler)
|
||||
}
|
||||
|
||||
export const createRegistrationTemplates = (data,csrfToken) => {
|
||||
|
||||
return fetch(`${BE_SUBSCRIPTION_REGISTRATION_TEMPLATES_URL}`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
headers: {
|
||||
'X-CSRFToken': csrfToken,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
credentials: 'include',
|
||||
})
|
||||
.then(requestResponseHandler)
|
||||
}
|
||||
|
||||
export const deleteRegistrationTemplates = (fileId,csrfToken) => {
|
||||
return fetch(`${BE_SUBSCRIPTION_REGISTRATION_TEMPLATES_URL}/${fileId}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'X-CSRFToken': csrfToken,
|
||||
},
|
||||
credentials: 'include',
|
||||
})
|
||||
}
|
||||
|
||||
export const fetchRegistrationTemplateMaster = (id = null) => {
|
||||
let url = `${BE_SUBSCRIPTION_REGISTRATION_TEMPLATE_MASTER_URL}`;
|
||||
if(id){
|
||||
url = `${BE_SUBSCRIPTION_REGISTRATION_TEMPLATE_MASTER_URL}/${id}`;
|
||||
}
|
||||
const request = new Request(
|
||||
`${url}`,
|
||||
{
|
||||
method:'GET',
|
||||
headers: {
|
||||
'Content-Type':'application/json'
|
||||
},
|
||||
}
|
||||
);
|
||||
return fetch(request).then(requestResponseHandler)
|
||||
};
|
||||
|
||||
export const createRegistrationTemplateMaster = (data,csrfToken) => {
|
||||
|
||||
return fetch(`${BE_SUBSCRIPTION_REGISTRATION_TEMPLATE_MASTER_URL}`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
headers: {
|
||||
'X-CSRFToken': csrfToken,
|
||||
'Content-Type':'application/json'
|
||||
},
|
||||
credentials: 'include',
|
||||
})
|
||||
.then(requestResponseHandler)
|
||||
}
|
||||
|
||||
export const deleteRegistrationTemplateMaster = (fileId,csrfToken) => {
|
||||
return fetch(`${BE_SUBSCRIPTION_REGISTRATION_TEMPLATE_MASTER_URL}/${fileId}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'X-CSRFToken': csrfToken,
|
||||
},
|
||||
credentials: 'include',
|
||||
})
|
||||
}
|
||||
|
||||
export const editRegistrationTemplateMaster = (fileId, data, csrfToken) => {
|
||||
return fetch(`${BE_SUBSCRIPTION_REGISTRATION_TEMPLATE_MASTER_URL}/${fileId}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(data),
|
||||
headers: {
|
||||
'X-CSRFToken': csrfToken,
|
||||
'Content-Type':'application/json'
|
||||
},
|
||||
credentials: 'include',
|
||||
})
|
||||
.then(requestResponseHandler)
|
||||
}
|
||||
@ -2,9 +2,7 @@ import {
|
||||
BE_SUBSCRIPTION_STUDENTS_URL,
|
||||
BE_SUBSCRIPTION_CHILDRENS_URL,
|
||||
BE_SUBSCRIPTION_REGISTERFORMS_URL,
|
||||
BE_SUBSCRIPTION_REGISTRATION_TEMPLATE_MASTER_URL,
|
||||
BE_SUBSCRIPTION_LAST_GUARDIAN_ID_URL,
|
||||
BE_SUBSCRIPTION_REGISTRATION_TEMPLATES_URL
|
||||
BE_SUBSCRIPTION_LAST_GUARDIAN_ID_URL
|
||||
} from '@/utils/Url';
|
||||
|
||||
export const PENDING = 'pending';
|
||||
@ -101,112 +99,6 @@ export const archiveRegisterForm = (id) => {
|
||||
}).then(requestResponseHandler)
|
||||
}
|
||||
|
||||
export const fetchRegistrationTemplates = (id = null) => {
|
||||
let url = `${BE_SUBSCRIPTION_REGISTRATION_TEMPLATES_URL}`
|
||||
if (id) {
|
||||
url = `${BE_SUBSCRIPTION_REGISTRATION_TEMPLATES_URL}/${id}`;
|
||||
}
|
||||
const request = new Request(
|
||||
`${url}`,
|
||||
{
|
||||
method:'GET',
|
||||
headers: {
|
||||
'Content-Type':'application/json'
|
||||
},
|
||||
}
|
||||
);
|
||||
return fetch(request).then(requestResponseHandler)
|
||||
};
|
||||
|
||||
export const editRegistrationTemplates= (fileId, data, csrfToken) => {
|
||||
return fetch(`${BE_SUBSCRIPTION_REGISTRATION_TEMPLATES_URL}/${fileId}`, {
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
headers: {
|
||||
'X-CSRFToken': csrfToken,
|
||||
},
|
||||
credentials: 'include',
|
||||
})
|
||||
.then(requestResponseHandler)
|
||||
}
|
||||
|
||||
export const createRegistrationTemplates = (data,csrfToken) => {
|
||||
|
||||
return fetch(`${BE_SUBSCRIPTION_REGISTRATION_TEMPLATES_URL}`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
headers: {
|
||||
'X-CSRFToken': csrfToken,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
credentials: 'include',
|
||||
})
|
||||
.then(requestResponseHandler)
|
||||
}
|
||||
|
||||
export const deleteRegistrationTemplates= (fileId,csrfToken) => {
|
||||
return fetch(`${BE_SUBSCRIPTION_REGISTRATION_TEMPLATES_URL}/${fileId}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'X-CSRFToken': csrfToken,
|
||||
},
|
||||
credentials: 'include',
|
||||
})
|
||||
}
|
||||
|
||||
export const fetchRegistrationTemplateMaster = (id = null) => {
|
||||
let url = `${BE_SUBSCRIPTION_REGISTRATION_TEMPLATE_MASTER_URL}`;
|
||||
if(id){
|
||||
url = `${BE_SUBSCRIPTION_REGISTRATION_TEMPLATE_MASTER_URL}/${id}`;
|
||||
}
|
||||
const request = new Request(
|
||||
`${url}`,
|
||||
{
|
||||
method:'GET',
|
||||
headers: {
|
||||
'Content-Type':'application/json'
|
||||
},
|
||||
}
|
||||
);
|
||||
return fetch(request).then(requestResponseHandler)
|
||||
};
|
||||
|
||||
export const createRegistrationTemplateMaster = (data,csrfToken) => {
|
||||
|
||||
return fetch(`${BE_SUBSCRIPTION_REGISTRATION_TEMPLATE_MASTER_URL}`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
headers: {
|
||||
'X-CSRFToken': csrfToken,
|
||||
'Content-Type':'application/json'
|
||||
},
|
||||
credentials: 'include',
|
||||
})
|
||||
.then(requestResponseHandler)
|
||||
}
|
||||
|
||||
export const deleteRegistrationTemplateMaster = (fileId,csrfToken) => {
|
||||
return fetch(`${BE_SUBSCRIPTION_REGISTRATION_TEMPLATE_MASTER_URL}/${fileId}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'X-CSRFToken': csrfToken,
|
||||
},
|
||||
credentials: 'include',
|
||||
})
|
||||
}
|
||||
|
||||
export const editRegistrationTemplateMaster = (fileId, data, csrfToken) => {
|
||||
return fetch(`${BE_SUBSCRIPTION_REGISTRATION_TEMPLATE_MASTER_URL}/${fileId}`, {
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
headers: {
|
||||
'X-CSRFToken': csrfToken,
|
||||
},
|
||||
credentials: 'include',
|
||||
})
|
||||
.then(requestResponseHandler)
|
||||
}
|
||||
|
||||
export const fetchStudents = (id) => {
|
||||
const url = (id)?`${BE_SUBSCRIPTION_STUDENTS_URL}/${id}`:`${BE_SUBSCRIPTION_STUDENTS_URL}`;
|
||||
const request = new Request(
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import ToggleSwitch from '@/components/ToggleSwitch'; // Import du composant ToggleSwitch
|
||||
import { fetchRegistrationFileGroups } from '@/app/actions/registerFileGroupAction';
|
||||
import DocusealBuilder from '@/components/DocusealBuilder'; // Import du composant wrapper
|
||||
import { DocusealBuilder } from '@docuseal/react';
|
||||
import logger from '@/utils/logger';
|
||||
import { BE_DOCUSEAL_GET_JWT, BASE_URL } from '@/utils/Url';
|
||||
import Button from '@/components/Button'; // Import du composant Button
|
||||
import MultiSelect from '@/components/MultiSelect'; // Import du composant MultiSelect
|
||||
import { createRegistrationTemplates } from '@/app/actions/subscriptionAction'; // Import de la fonction createRegistrationTemplates
|
||||
import { createRegistrationTemplates } from '@/app/actions/registerFileGroupAction';
|
||||
import { useCsrfToken } from '@/context/CsrfContext';
|
||||
|
||||
export default function FileUpload({ handleCreateTemplateMaster, fileToEdit = null }) {
|
||||
export default function FileUpload({ handleCreateTemplateMaster, handleEditTemplateMaster, fileToEdit = null, onSuccess }) {
|
||||
const [isRequired, setIsRequired] = useState(false); // État pour le toggle isRequired
|
||||
const [order, setOrder] = useState(0);
|
||||
const [groups, setGroups] = useState([]);
|
||||
@ -75,7 +75,12 @@ export default function FileUpload({ handleCreateTemplateMaster, fileToEdit = nu
|
||||
const handleLoad = (detail) => {
|
||||
const templateId = detail?.id;
|
||||
setTemplateMaster(detail);
|
||||
logger.debug('Master template created with ID:', templateId);
|
||||
if (fileToEdit) {
|
||||
logger.debug('Editing master ID :', templateId);
|
||||
}
|
||||
else {
|
||||
logger.debug('Opening master ID :', templateId);
|
||||
}
|
||||
}
|
||||
|
||||
const handleUpload = (detail) => {
|
||||
@ -84,41 +89,53 @@ export default function FileUpload({ handleCreateTemplateMaster, fileToEdit = nu
|
||||
};
|
||||
|
||||
const handleSubmit = () => {
|
||||
logger.debug('Création du template master:', templateMaster?.id);
|
||||
handleCreateTemplateMaster({
|
||||
name: uploadedFileName,
|
||||
group_ids: selectedGroups.map(group => group.id),
|
||||
template_id: templateMaster?.id
|
||||
});
|
||||
if (fileToEdit) {
|
||||
logger.debug('Modification du template master:', templateMaster?.id);
|
||||
handleEditTemplateMaster({
|
||||
name: uploadedFileName,
|
||||
group_ids: selectedGroups.map(group => group.id),
|
||||
template_id: templateMaster?.id
|
||||
});
|
||||
}
|
||||
else {
|
||||
logger.debug('Création du template master:', templateMaster?.id);
|
||||
handleCreateTemplateMaster({
|
||||
name: uploadedFileName,
|
||||
group_ids: selectedGroups.map(group => group.id),
|
||||
template_id: templateMaster?.id
|
||||
});
|
||||
|
||||
guardianEmails.forEach((email, index) => {
|
||||
cloneTemplate(templateMaster?.id, email)
|
||||
.then(clonedDocument => {
|
||||
guardianEmails.forEach((email, index) => {
|
||||
cloneTemplate(templateMaster?.id, email)
|
||||
.then(clonedDocument => {
|
||||
|
||||
// Sauvegarde des templates clonés dans la base de données
|
||||
const data = {
|
||||
name: `clone_${clonedDocument.id}`,
|
||||
template_id: clonedDocument.id,
|
||||
master: templateMaster?.id,
|
||||
registration_form: registrationFormIds[index]
|
||||
};
|
||||
// Sauvegarde des templates clonés dans la base de données
|
||||
const data = {
|
||||
name: `clone_${clonedDocument.id}`,
|
||||
template_id: clonedDocument.id,
|
||||
master: templateMaster?.id,
|
||||
registration_form: registrationFormIds[index]
|
||||
};
|
||||
|
||||
createRegistrationTemplates(data, csrfToken)
|
||||
.then(response => {
|
||||
logger.debug('Template enregistré avec succès:', response);
|
||||
})
|
||||
.catch(error => {
|
||||
logger.error('Erreur lors de l\'enregistrement du template:', error);
|
||||
});
|
||||
createRegistrationTemplates(data, csrfToken)
|
||||
.then(response => {
|
||||
logger.debug('Template enregistré avec succès:', response);
|
||||
onSuccess();
|
||||
})
|
||||
.catch(error => {
|
||||
logger.error('Erreur lors de l\'enregistrement du template:', error);
|
||||
});
|
||||
|
||||
|
||||
// Logique pour envoyer chaque template au submitter
|
||||
logger.debug('Sending template to:', email);
|
||||
})
|
||||
.catch(error => {
|
||||
logger.error('Error during cloning or sending:', error);
|
||||
});
|
||||
});
|
||||
// Logique pour envoyer chaque template au submitter
|
||||
logger.debug('Sending template to:', email);
|
||||
})
|
||||
.catch(error => {
|
||||
logger.error('Error during cloning or sending:', error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const cloneTemplate = (templateId, email) => {
|
||||
@ -161,7 +178,7 @@ export default function FileUpload({ handleCreateTemplateMaster, fileToEdit = nu
|
||||
errorMsg={null}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-7">
|
||||
<div className="col-span-8">
|
||||
{token && (
|
||||
<DocusealBuilder
|
||||
token={token}
|
||||
@ -169,11 +186,13 @@ export default function FileUpload({ handleCreateTemplateMaster, fileToEdit = nu
|
||||
'Authorization': `Bearer ${token}`
|
||||
}}
|
||||
withSendButton={false}
|
||||
withSaveButton={false}
|
||||
withSignYourselfButton={false}
|
||||
autosave={true}
|
||||
autosave={false}
|
||||
language={'fr'}
|
||||
onLoad={handleLoad}
|
||||
onUpload={handleUpload}
|
||||
onSave={handleSubmit}
|
||||
className="h-full overflow-auto" // Ajouter overflow-auto pour permettre le défilement
|
||||
style={{ maxHeight: '70vh' }} // Limiter la hauteur maximale du composant
|
||||
// Il faut auter l'host correspondant (une fois passé en HTTPS)
|
||||
@ -181,19 +200,6 @@ export default function FileUpload({ handleCreateTemplateMaster, fileToEdit = nu
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div className="col-span-1 flex justify-end">
|
||||
<Button
|
||||
text="Valider"
|
||||
onClick={handleSubmit}
|
||||
className={`px-4 py-2 rounded-md shadow-sm focus:outline-none ${
|
||||
(uploadedFileName === '' || selectedGroups.length === 0)
|
||||
? "bg-gray-300 text-gray-700 cursor-not-allowed"
|
||||
: "bg-emerald-500 text-white hover:bg-emerald-600"
|
||||
}`}
|
||||
primary
|
||||
disabled={uploadedFileName === '' || selectedGroups.length === 0}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -1,27 +1,26 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Plus, Download, Edit, Trash2, FolderPlus, Signature } from 'lucide-react';
|
||||
import { Plus, Download, Edit3, Trash2, FolderPlus, Signature } from 'lucide-react';
|
||||
import Modal from '@/components/Modal';
|
||||
import Table from '@/components/Table';
|
||||
import FileUpload from '@/components/Structure/Files/FileUpload';
|
||||
import { formatDate } from '@/utils/Date';
|
||||
import { BASE_URL } from '@/utils/Url';
|
||||
import {
|
||||
fetchRegistrationTemplateMaster,
|
||||
createRegistrationTemplateMaster,
|
||||
editRegistrationTemplateMaster,
|
||||
deleteRegistrationTemplateMaster,
|
||||
getRegisterFormFileTemplate
|
||||
} from '@/app/actions/subscriptionAction';
|
||||
import {
|
||||
fetchRegistrationFileGroups,
|
||||
createRegistrationFileGroup,
|
||||
deleteRegistrationFileGroup,
|
||||
editRegistrationFileGroup
|
||||
editRegistrationFileGroup,
|
||||
fetchRegistrationTemplateMaster,
|
||||
createRegistrationTemplateMaster,
|
||||
editRegistrationTemplateMaster,
|
||||
deleteRegistrationTemplateMaster,
|
||||
fetchRegistrationTemplates
|
||||
} from '@/app/actions/registerFileGroupAction';
|
||||
import RegistrationFileGroupForm from '@/components/Structure/Files/RegistrationFileGroupForm';
|
||||
import logger from '@/utils/logger';
|
||||
|
||||
export default function FilesGroupsManagement({ csrfToken }) {
|
||||
const [fichiers, setFichiers] = useState([]);
|
||||
const [templateMasters, setTemplateMasters] = useState([]);
|
||||
const [templates, setTemplates] = useState([]);
|
||||
const [groups, setGroups] = useState([]);
|
||||
const [selectedGroup, setSelectedGroup] = useState(null);
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
@ -29,6 +28,11 @@ export default function FilesGroupsManagement({ csrfToken }) {
|
||||
const [fileToEdit, setFileToEdit] = useState(null);
|
||||
const [isGroupModalOpen, setIsGroupModalOpen] = useState(false);
|
||||
const [groupToEdit, setGroupToEdit] = useState(null);
|
||||
const [reloadTemplates, setReloadTemplates] = useState(false);
|
||||
|
||||
const handleReloadTemplates = () => {
|
||||
setReloadTemplates(true);
|
||||
}
|
||||
|
||||
const transformFileData = (file, groups) => {
|
||||
const groupInfos = file.groups.map(groupId => groups.find(g => g.id === groupId) || { id: groupId, name: 'Groupe inconnu' });
|
||||
@ -41,38 +45,91 @@ export default function FilesGroupsManagement({ csrfToken }) {
|
||||
useEffect(() => {
|
||||
Promise.all([
|
||||
fetchRegistrationTemplateMaster(),
|
||||
fetchRegistrationFileGroups()
|
||||
]).then(([filesData, groupsData]) => {
|
||||
fetchRegistrationFileGroups(),
|
||||
fetchRegistrationTemplates()
|
||||
]).then(([filesTemplateMasters, groupsData, filesTemplates]) => {
|
||||
setGroups(groupsData);
|
||||
setTemplates(filesTemplates);
|
||||
console.log("coucou : ", filesTemplates)
|
||||
// Sélectionner automatiquement le premier groupe s'il existe
|
||||
if (groupsData.length > 0) {
|
||||
setSelectedGroup(groupsData[0].id.toString());
|
||||
}
|
||||
// Transformer chaque fichier pour inclure les informations complètes du groupe
|
||||
const transformedFiles = filesData.map(file => transformFileData(file, groupsData));
|
||||
setFichiers(transformedFiles);
|
||||
const transformedFiles = filesTemplateMasters.map(file => transformFileData(file, groupsData));
|
||||
setTemplateMasters(transformedFiles);
|
||||
}).catch(err => {
|
||||
console.log(err.message);
|
||||
}).finally(() => {
|
||||
setReloadTemplates(false);
|
||||
});
|
||||
}, []);
|
||||
}, [reloadTemplates]);
|
||||
|
||||
const handleFileDelete = (fileId) => {
|
||||
deleteRegistrationTemplateMaster(fileId, csrfToken)
|
||||
.then(response => {
|
||||
if (response.ok) {
|
||||
setFichiers(fichiers.filter(fichier => fichier.id !== fileId));
|
||||
alert('Fichier supprimé avec succès.');
|
||||
const deleteTemplateMaster = (templateMaster) => {
|
||||
// Supprimer les clones associés via l'API DocuSeal
|
||||
console.log(templates)
|
||||
const removeClonesPromises = templates
|
||||
.filter(template => template.master === templateMaster.template_id)
|
||||
.map(template => removeTemplate(template.template_id));
|
||||
|
||||
// Ajouter la suppression du master à la liste des promesses
|
||||
removeClonesPromises.push(removeTemplate(templateMaster.template_id));
|
||||
|
||||
// Attendre que toutes les suppressions dans DocuSeal soient terminées
|
||||
Promise.all(removeClonesPromises)
|
||||
.then(responses => {
|
||||
const allSuccessful = responses.every(response => response.ok);
|
||||
if (allSuccessful) {
|
||||
logger.debug('Master et clones supprimés avec succès de DocuSeal.');
|
||||
|
||||
// Supprimer le template master de la base de données
|
||||
deleteRegistrationTemplateMaster(templateMaster.template_id, csrfToken)
|
||||
.then(response => {
|
||||
if (response.ok) {
|
||||
setTemplateMasters(templateMasters.filter(fichier => fichier.template_id !== templateMaster.template_id));
|
||||
alert('Fichier supprimé avec succès.');
|
||||
} else {
|
||||
alert('Erreur lors de la suppression du fichier dans la base de données.');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error deleting file from database:', error);
|
||||
alert('Erreur lors de la suppression du fichier dans la base de données.');
|
||||
});
|
||||
} else {
|
||||
alert('Erreur lors de la suppression du fichier.');
|
||||
alert('Erreur lors de la suppression du master ou des clones dans DocuSeal.');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error deleting file:', error);
|
||||
alert('Erreur lors de la suppression du fichier.');
|
||||
console.error('Error removing template from DocuSeal:', error);
|
||||
alert('Erreur lors de la suppression du master ou des clones dans DocuSeal.');
|
||||
});
|
||||
};
|
||||
|
||||
const handleFileEdit = (file) => {
|
||||
const removeTemplate = (templateId) => {
|
||||
return fetch('/api/docuseal/removeTemplate/', {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRFToken': csrfToken
|
||||
},
|
||||
body: JSON.stringify({
|
||||
templateId
|
||||
})
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
return response.json().then(err => { throw new Error(err.message); });
|
||||
}
|
||||
return response;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error removing template:', error);
|
||||
throw error;
|
||||
});
|
||||
};
|
||||
|
||||
const editTemplateMaster = (file) => {
|
||||
setIsEditing(true);
|
||||
setFileToEdit(file);
|
||||
setIsModalOpen(true);
|
||||
@ -84,87 +141,40 @@ export default function FilesGroupsManagement({ csrfToken }) {
|
||||
template_id: template_id,
|
||||
groups: group_ids
|
||||
};
|
||||
console.log(data);
|
||||
logger.debug(data);
|
||||
|
||||
if (isEditing && fileToEdit) {
|
||||
editRegistrationTemplateMaster(fileToEdit.id, data, csrfToken)
|
||||
.then(data => {
|
||||
// Transformer le fichier mis à jour avec les informations du groupe
|
||||
const transformedFile = transformFileData(data, groups);
|
||||
setFichiers(prevFichiers =>
|
||||
prevFichiers.map(f => f.id === fileToEdit.id ? transformedFile : f)
|
||||
);
|
||||
setIsModalOpen(false);
|
||||
setFileToEdit(null);
|
||||
setIsEditing(false);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error editing file:', error);
|
||||
alert('Erreur lors de la modification du fichier');
|
||||
});
|
||||
} else {
|
||||
createRegistrationTemplateMaster(data, csrfToken)
|
||||
.then(data => {
|
||||
// Transformer le nouveau fichier avec les informations du groupe
|
||||
const transformedFile = transformFileData(data, groups);
|
||||
setFichiers(prevFiles => [...prevFiles, transformedFile]);
|
||||
setIsModalOpen(false);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error uploading file:', error);
|
||||
});
|
||||
}
|
||||
createRegistrationTemplateMaster(data, csrfToken)
|
||||
.then(data => {
|
||||
// Transformer le nouveau fichier avec les informations du groupe
|
||||
const transformedFile = transformFileData(data, groups);
|
||||
setTemplateMasters(prevFiles => [...prevFiles, transformedFile]);
|
||||
setIsModalOpen(false);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error uploading file:', error);
|
||||
});
|
||||
};
|
||||
|
||||
const handleTemplate = ({name, is_required, order, groupId, document_id}) => {
|
||||
if (!name) {
|
||||
alert('Veuillez entrer un nom de fichier.');
|
||||
return;
|
||||
}
|
||||
const handleEditTemplateMaster = ({name, group_ids, template_id}) => {
|
||||
const data = {
|
||||
name: name,
|
||||
template_id: template_id,
|
||||
groups: group_ids
|
||||
};
|
||||
logger.debug(data);
|
||||
|
||||
const formData = new FormData();
|
||||
if(file) {
|
||||
formData.append('file', file);
|
||||
}
|
||||
formData.append('name', name);
|
||||
formData.append('is_required', is_required);
|
||||
formData.append('order', order);
|
||||
formData.append('document_id', document_id);
|
||||
|
||||
// Modification ici : vérifier si groupId existe et n'est pas vide
|
||||
if (groupId && groupId !== '') {
|
||||
formData.append('group', groupId); // Notez que le nom du champ est 'group' et non 'group_id'
|
||||
}
|
||||
|
||||
|
||||
if (isEditing && fileToEdit) {
|
||||
editRegistrationTemplateMaster(fileToEdit.id, formData, csrfToken)
|
||||
.then(data => {
|
||||
// Transformer le fichier mis à jour avec les informations du groupe
|
||||
const transformedFile = transformFileData(data, groups);
|
||||
setFichiers(prevFichiers =>
|
||||
prevFichiers.map(f => f.id === fileToEdit.id ? transformedFile : f)
|
||||
);
|
||||
setIsModalOpen(false);
|
||||
setFileToEdit(null);
|
||||
setIsEditing(false);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error editing file:', error);
|
||||
alert('Erreur lors de la modification du fichier');
|
||||
});
|
||||
} else {
|
||||
createRegistrationTemplateMaster(formData, csrfToken)
|
||||
.then(data => {
|
||||
// Transformer le nouveau fichier avec les informations du groupe
|
||||
const transformedFile = transformFileData(data, groups);
|
||||
setFichiers(prevFiles => [...prevFiles, transformedFile]);
|
||||
setIsModalOpen(false);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error uploading file:', error);
|
||||
});
|
||||
}
|
||||
editRegistrationTemplateMaster(template_id, data, csrfToken)
|
||||
.then(data => {
|
||||
// Transformer le fichier mis à jour avec les informations du groupe
|
||||
const transformedFile = transformFileData(data, groups);
|
||||
setTemplateMasters(prevFichiers =>
|
||||
prevFichiers.map(f => f.id === template_id ? transformedFile : f)
|
||||
);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error editing file:', error);
|
||||
alert('Erreur lors de la modification du fichier');
|
||||
});
|
||||
};
|
||||
|
||||
const handleGroupSubmit = (groupData) => {
|
||||
@ -198,10 +208,10 @@ export default function FilesGroupsManagement({ csrfToken }) {
|
||||
};
|
||||
|
||||
const handleGroupDelete = (groupId) => {
|
||||
// Vérifier si des fichiers utilisent ce groupe
|
||||
const filesInGroup = fichiers.filter(file => file.group && file.group.id === groupId);
|
||||
// Vérifier si des templateMasters utilisent ce groupe
|
||||
const filesInGroup = templateMasters.filter(file => file.group && file.group.id === groupId);
|
||||
if (filesInGroup.length > 0) {
|
||||
alert('Impossible de supprimer ce groupe car il contient des fichiers. Veuillez d\'abord retirer tous les fichiers de ce groupe.');
|
||||
alert('Impossible de supprimer ce groupe car il contient des templateMasters. Veuillez d\'abord retirer tous les templateMasters de ce groupe.');
|
||||
return;
|
||||
}
|
||||
|
||||
@ -224,7 +234,7 @@ export default function FilesGroupsManagement({ csrfToken }) {
|
||||
}
|
||||
};
|
||||
|
||||
const filteredFiles = fichiers.filter(file => {
|
||||
const filteredFiles = templateMasters.filter(file => {
|
||||
if (!selectedGroup) return true;
|
||||
return file.groups && file.groups.some(group => group.id === parseInt(selectedGroup));
|
||||
});
|
||||
@ -236,14 +246,14 @@ export default function FilesGroupsManagement({ csrfToken }) {
|
||||
<div className="flex items-center justify-center gap-2">
|
||||
{row.file && (
|
||||
<a href={`${BASE_URL}${row.file}`} target='_blank' className="text-blue-500 hover:text-blue-700">
|
||||
<Download size={16} />
|
||||
<Download className="w-5 h-5" />
|
||||
</a>
|
||||
)}
|
||||
<button onClick={() => handleFileEdit(row)} className="text-blue-500 hover:text-blue-700">
|
||||
<Edit size={16} />
|
||||
<button onClick={() => editTemplateMaster(row)} className="text-blue-500 hover:text-blue-700">
|
||||
<Edit3 className="w-5 h-5" />
|
||||
</button>
|
||||
<button onClick={() => handleFileDelete(row.id)} className="text-red-500 hover:text-red-700">
|
||||
<Trash2 size={16} />
|
||||
<button onClick={() => deleteTemplateMaster(row)} className="text-red-500 hover:text-red-700">
|
||||
<Trash2 className="w-5 h-5" />
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
@ -255,10 +265,10 @@ export default function FilesGroupsManagement({ csrfToken }) {
|
||||
{ name: 'Actions', transform: (row) => (
|
||||
<div className="flex items-center justify-center gap-2">
|
||||
<button onClick={() => handleGroupEdit(row)} className="text-blue-500 hover:text-blue-700">
|
||||
<Edit size={16} />
|
||||
<Edit3 className="w-5 h-5" />
|
||||
</button>
|
||||
<button onClick={() => handleGroupDelete(row.id)} className="text-red-500 hover:text-red-700">
|
||||
<Trash2 size={16} />
|
||||
<Trash2 className="w-5 h-5" />
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
@ -278,7 +288,9 @@ export default function FilesGroupsManagement({ csrfToken }) {
|
||||
ContentComponent={() => (
|
||||
<FileUpload
|
||||
handleCreateTemplateMaster={handleCreateTemplateMaster}
|
||||
handleEditTemplateMaster={handleEditTemplateMaster}
|
||||
fileToEdit={fileToEdit}
|
||||
onSuccess={handleReloadTemplates}
|
||||
/>
|
||||
)}
|
||||
modalClassName='w-4/5 h-4/5'
|
||||
@ -286,7 +298,7 @@ export default function FilesGroupsManagement({ csrfToken }) {
|
||||
<Modal
|
||||
isOpen={isGroupModalOpen}
|
||||
setIsOpen={setIsGroupModalOpen}
|
||||
title={groupToEdit ? "Modifier le groupe" : "Ajouter un groupe de fichiers"}
|
||||
title={groupToEdit ? "Modifier le groupe" : "Ajouter un groupe de templateMasters"}
|
||||
ContentComponent={() => (
|
||||
<RegistrationFileGroupForm
|
||||
onSubmit={handleGroupSubmit}
|
||||
@ -296,7 +308,7 @@ export default function FilesGroupsManagement({ csrfToken }) {
|
||||
/>
|
||||
<div className="mt-8 mb-4">
|
||||
<div className="flex justify-between items-center mb-4">
|
||||
<h2 className="text-xl font-bold">Groupes de fichiers</h2>
|
||||
<h2 className="text-xl font-bold">Groupes de templateMasters</h2>
|
||||
<button
|
||||
onClick={() => setIsGroupModalOpen(true)}
|
||||
className="flex items-center bg-blue-600 text-white p-2 rounded-full shadow hover:bg-blue-900 transition duration-200"
|
||||
@ -315,7 +327,7 @@ export default function FilesGroupsManagement({ csrfToken }) {
|
||||
{groups.length > 0 && (
|
||||
<div className="mt-8">
|
||||
<div className="flex justify-between items-center mb-4">
|
||||
<h2 className="text-xl font-bold">Fichiers</h2>
|
||||
<h2 className="text-xl font-bold">templateMasters</h2>
|
||||
<div className="flex items-center gap-4">
|
||||
<select
|
||||
className="border rounded p-2"
|
||||
|
||||
31
Front-End/src/pages/api/docuseal/removeTemplate.js
Normal file
31
Front-End/src/pages/api/docuseal/removeTemplate.js
Normal file
@ -0,0 +1,31 @@
|
||||
import { BE_DOCUSEAL_REMOVE_TEMPLATE } from '@/utils/Url';
|
||||
|
||||
export default function handler(req, res) {
|
||||
if (req.method === 'DELETE') {
|
||||
const { templateId } = req.body;
|
||||
|
||||
fetch(`${BE_DOCUSEAL_REMOVE_TEMPLATE}/${templateId}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'X-Auth-Token': process.env.DOCUSEAL_API_KEY
|
||||
}
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
return response.json().then(err => { throw new Error(err.message); });
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
console.log('Template removed successfully:', data);
|
||||
res.status(200).json(data);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error removing template:', error);
|
||||
res.status(500).json({ error: 'Internal Server Error' });
|
||||
});
|
||||
} else {
|
||||
res.setHeader('Allow', ['DELETE']);
|
||||
res.status(405).end(`Method ${req.method} Not Allowed`);
|
||||
}
|
||||
}
|
||||
@ -7,6 +7,7 @@ export const BASE_URL = process.env.NEXT_PUBLIC_API_URL;
|
||||
// GESTION DocuSeal
|
||||
export const BE_DOCUSEAL_GET_JWT = `${BASE_URL}/DocuSeal/generateToken`
|
||||
export const BE_DOCUSEAL_CLONE_TEMPLATE = `${BASE_URL}/DocuSeal/cloneTemplate`
|
||||
export const BE_DOCUSEAL_REMOVE_TEMPLATE = `${BASE_URL}/DocuSeal/removeTemplate`
|
||||
|
||||
// GESTION LOGIN
|
||||
export const BE_AUTH_NEW_PASSWORD_URL = `${BASE_URL}/Auth/newPassword`
|
||||
|
||||
Reference in New Issue
Block a user