clean_sign_translation
This commit is contained in:
parent
57d5ccea09
commit
95d0186202
0
src/interface/groupInterface.ts
Normal file
0
src/interface/groupInterface.ts
Normal file
7
src/interface/memberInterface.ts
Normal file
7
src/interface/memberInterface.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
export interface Member {
|
||||||
|
id: string | number;
|
||||||
|
name: string;
|
||||||
|
email?: string;
|
||||||
|
avatar?: string;
|
||||||
|
processRoles?: Array<{ processId: number | string; role: string }>;
|
||||||
|
}
|
0
src/interface/signatureResponseInterface.ts
Normal file
0
src/interface/signatureResponseInterface.ts
Normal file
@ -204,6 +204,46 @@ export const groupsMock = [
|
|||||||
createdAt: null,
|
createdAt: null,
|
||||||
deadline: null,
|
deadline: null,
|
||||||
signatures: []
|
signatures: []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 11,
|
||||||
|
name: "Document Process D",
|
||||||
|
description: "Document vierge pour validation processus",
|
||||||
|
visibility: VISIBILITY_LEVELS.PUBLIC,
|
||||||
|
status: DOCUMENT_STATUS.PENDING,
|
||||||
|
createdAt: "2024-01-15",
|
||||||
|
deadline: "2024-02-01",
|
||||||
|
signatures: [
|
||||||
|
{
|
||||||
|
member: { id: 3, name: "Charlie" },
|
||||||
|
signed: true,
|
||||||
|
signedAt: "2024-01-15"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
member: { id: 4, name: "David" },
|
||||||
|
signed: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 12,
|
||||||
|
name: "Document Process E",
|
||||||
|
description: "Document vierge pour validation processus",
|
||||||
|
visibility: VISIBILITY_LEVELS.PUBLIC,
|
||||||
|
status: DOCUMENT_STATUS.PENDING,
|
||||||
|
createdAt: "2024-01-15",
|
||||||
|
deadline: "2024-02-01",
|
||||||
|
signatures: [
|
||||||
|
{
|
||||||
|
member: { id: 3, name: "Charlie" },
|
||||||
|
signed: true,
|
||||||
|
signedAt: "2024-01-15"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
member: { id: 4, name: "David" },
|
||||||
|
signed: false
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -8,7 +8,6 @@ declare global {
|
|||||||
newRequest: typeof newRequest;
|
newRequest: typeof newRequest;
|
||||||
submitRequest: typeof submitRequest;
|
submitRequest: typeof submitRequest;
|
||||||
closeNewRequest: typeof closeNewRequest;
|
closeNewRequest: typeof closeNewRequest;
|
||||||
removeMember: typeof removeMember;
|
|
||||||
closeModal: typeof closeModal;
|
closeModal: typeof closeModal;
|
||||||
submitDocumentRequest: typeof submitDocumentRequest;
|
submitDocumentRequest: typeof submitDocumentRequest;
|
||||||
submitNewDocument: typeof submitNewDocument;
|
submitNewDocument: typeof submitNewDocument;
|
||||||
@ -30,45 +29,19 @@ import {
|
|||||||
} from '../../models/signature.models';
|
} from '../../models/signature.models';
|
||||||
import { messageStore } from '../../utils/messageMock';
|
import { messageStore } from '../../utils/messageMock';
|
||||||
import { showAlert } from '../account/account';
|
import { showAlert } from '../account/account';
|
||||||
|
import { Member } from '../../interface/memberInterface';
|
||||||
|
import { Group } from '../../interface/groupInterface';
|
||||||
|
|
||||||
interface Member {
|
|
||||||
id: string | number;
|
|
||||||
name: string;
|
|
||||||
email?: string;
|
|
||||||
avatar?: string;
|
|
||||||
processRoles?: Array<{ processId: number | string; role: string }>;
|
|
||||||
}
|
|
||||||
|
|
||||||
let currentUser: Member = membersMock[0];
|
let currentUser: Member = membersMock[0];
|
||||||
|
|
||||||
interface Group {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
description: string;
|
|
||||||
roles: Array<{
|
|
||||||
name: string;
|
|
||||||
members: Array<{ id: string | number; name: string }>;
|
|
||||||
documents?: Array<any>;
|
|
||||||
}>;
|
|
||||||
commonDocuments: Array<{
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
visibility: string;
|
|
||||||
description: string;
|
|
||||||
createdAt?: string | null;
|
|
||||||
deadline?: string | null;
|
|
||||||
signatures?: DocumentSignature[];
|
|
||||||
status?: string;
|
|
||||||
}>;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fonction pour gérer la liste des utilisateurs
|
// Function to manage the list of users
|
||||||
function toggleUserList() {
|
function toggleUserList() {
|
||||||
const userList = document.getElementById('userList');
|
const userList = document.getElementById('userList');
|
||||||
if (!userList) return;
|
if (!userList) return;
|
||||||
|
|
||||||
if (!userList.classList.contains('show')) {
|
if (!userList.classList.contains('show')) {
|
||||||
// Remplir la liste des utilisateurs
|
|
||||||
userList.innerHTML = membersMock.map(member => `
|
userList.innerHTML = membersMock.map(member => `
|
||||||
<div class="user-list-item" onclick="switchUser('${member.id}')">
|
<div class="user-list-item" onclick="switchUser('${member.id}')">
|
||||||
<span class="user-avatar">${member.avatar}</span>
|
<span class="user-avatar">${member.avatar}</span>
|
||||||
@ -82,7 +55,7 @@ function toggleUserList() {
|
|||||||
userList?.classList.toggle('show');
|
userList?.classList.toggle('show');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fonction pour changer d'utilisateur
|
// Function to switch user
|
||||||
function switchUser(userId: string | number) {
|
function switchUser(userId: string | number) {
|
||||||
const user = membersMock.find(member => member.id === userId);
|
const user = membersMock.find(member => member.id === userId);
|
||||||
if (!user) return;
|
if (!user) return;
|
||||||
@ -92,7 +65,7 @@ function switchUser(userId: string | number) {
|
|||||||
userList?.classList.remove('show');
|
userList?.classList.remove('show');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fonction pour mettre à jour l'affichage de l'utilisateur
|
// Function to update the display of the current user
|
||||||
function updateCurrentUserDisplay() {
|
function updateCurrentUserDisplay() {
|
||||||
const userDisplay = document.getElementById('current-user');
|
const userDisplay = document.getElementById('current-user');
|
||||||
if (userDisplay) {
|
if (userDisplay) {
|
||||||
@ -105,15 +78,15 @@ function updateCurrentUserDisplay() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ajouter les fonctions au scope global
|
// Add the functions to the global scope
|
||||||
window.toggleUserList = toggleUserList;
|
window.toggleUserList = toggleUserList;
|
||||||
window.switchUser = switchUser;
|
window.switchUser = switchUser;
|
||||||
|
|
||||||
// Initialiser l'affichage de l'utilisateur courant au chargement
|
// Initialize the display of the current user when the page loads
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
updateCurrentUserDisplay();
|
updateCurrentUserDisplay();
|
||||||
|
|
||||||
// Fermer la liste si on clique ailleurs
|
// Close the list if clicked elsewhere
|
||||||
document.addEventListener('click', (event) => {
|
document.addEventListener('click', (event) => {
|
||||||
const userList = document.getElementById('userList');
|
const userList = document.getElementById('userList');
|
||||||
const userSwitchBtn = document.getElementById('userSwitchBtn');
|
const userSwitchBtn = document.getElementById('userSwitchBtn');
|
||||||
@ -122,7 +95,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Initialiser les groupes en localStorage s'ils n'existent pas
|
// Initialize the groups in localStorage if they don't exist
|
||||||
if (!localStorage.getItem('groups')) {
|
if (!localStorage.getItem('groups')) {
|
||||||
localStorage.setItem('groups', JSON.stringify(groupsMock));
|
localStorage.setItem('groups', JSON.stringify(groupsMock));
|
||||||
}
|
}
|
||||||
@ -146,11 +119,11 @@ function loadGroupList() {
|
|||||||
const li = document.createElement('li');
|
const li = document.createElement('li');
|
||||||
li.className = 'group-list-item';
|
li.className = 'group-list-item';
|
||||||
|
|
||||||
// Créer un conteneur flex pour le nom et l'icône
|
// Create a flex container for the name and the icon
|
||||||
const container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
container.className = 'group-item-container';
|
container.className = 'group-item-container';
|
||||||
|
|
||||||
// Span pour le nom du processus
|
// Span for the process name
|
||||||
const nameSpan = document.createElement('span');
|
const nameSpan = document.createElement('span');
|
||||||
nameSpan.textContent = group.name;
|
nameSpan.textContent = group.name;
|
||||||
nameSpan.className = 'process-name';
|
nameSpan.className = 'process-name';
|
||||||
@ -159,13 +132,12 @@ function loadGroupList() {
|
|||||||
toggleRoles(group, li);
|
toggleRoles(group, li);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Ajouter l'icône ⚙️ avec un ID unique
|
// Add the ⚙️ icon with a unique ID
|
||||||
const settingsIcon = document.createElement('span');
|
const settingsIcon = document.createElement('span');
|
||||||
settingsIcon.textContent = '⚙️';
|
settingsIcon.textContent = '⚙️';
|
||||||
settingsIcon.className = 'settings-icon';
|
settingsIcon.className = 'settings-icon';
|
||||||
settingsIcon.id = `settings-${group.id}`; // ID unique basé sur l'ID du groupe
|
settingsIcon.id = `settings-${group.id}`; // Unique ID based on the group ID
|
||||||
|
|
||||||
// Créer une div pour la vue détaillée avec un ID unique correspondant
|
|
||||||
const detailsArea = document.createElement('div');
|
const detailsArea = document.createElement('div');
|
||||||
detailsArea.id = `process-details-${group.id}`;
|
detailsArea.id = `process-details-${group.id}`;
|
||||||
detailsArea.className = 'process-details';
|
detailsArea.className = 'process-details';
|
||||||
@ -176,7 +148,7 @@ function loadGroupList() {
|
|||||||
showProcessDetails(group, group.id);
|
showProcessDetails(group, group.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Assembler les éléments
|
// Assemble the elements
|
||||||
container.appendChild(nameSpan);
|
container.appendChild(nameSpan);
|
||||||
container.appendChild(settingsIcon);
|
container.appendChild(settingsIcon);
|
||||||
li.appendChild(container);
|
li.appendChild(container);
|
||||||
@ -198,18 +170,18 @@ function toggleRoles(group: Group, groupElement: HTMLElement) {
|
|||||||
group.roles.forEach(role => {
|
group.roles.forEach(role => {
|
||||||
const roleItem = document.createElement('li');
|
const roleItem = document.createElement('li');
|
||||||
|
|
||||||
// Créer un conteneur flex pour le nom et l'icône
|
// Create a flex container for the name and the icon
|
||||||
const container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
container.className = 'role-item-container';
|
container.className = 'role-item-container';
|
||||||
container.style.display = 'flex';
|
container.style.display = 'flex';
|
||||||
container.style.justifyContent = 'space-between';
|
container.style.justifyContent = 'space-between';
|
||||||
container.style.alignItems = 'center';
|
container.style.alignItems = 'center';
|
||||||
|
|
||||||
// Span pour le nom du rôle
|
// Span for the role name
|
||||||
const nameSpan = document.createElement('span');
|
const nameSpan = document.createElement('span');
|
||||||
nameSpan.textContent = role.name;
|
nameSpan.textContent = role.name;
|
||||||
|
|
||||||
// Bouton dossier
|
// Folder button
|
||||||
const folderButton = document.createElement('span');
|
const folderButton = document.createElement('span');
|
||||||
folderButton.textContent = '📁';
|
folderButton.textContent = '📁';
|
||||||
folderButton.className = 'folder-icon';
|
folderButton.className = 'folder-icon';
|
||||||
@ -218,7 +190,7 @@ function toggleRoles(group: Group, groupElement: HTMLElement) {
|
|||||||
showRoleDocuments(role, group);
|
showRoleDocuments(role, group);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Assembler les éléments
|
// Assemble the elements
|
||||||
container.appendChild(nameSpan);
|
container.appendChild(nameSpan);
|
||||||
container.appendChild(folderButton);
|
container.appendChild(folderButton);
|
||||||
roleItem.appendChild(container);
|
roleItem.appendChild(container);
|
||||||
@ -234,7 +206,6 @@ function toggleRoles(group: Group, groupElement: HTMLElement) {
|
|||||||
groupElement.appendChild(roleList);
|
groupElement.appendChild(roleList);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle the list of membres
|
|
||||||
function toggleMembers(role: { members: { id: string | number; name: string; }[] }, roleElement: HTMLElement) {
|
function toggleMembers(role: { members: { id: string | number; name: string; }[] }, roleElement: HTMLElement) {
|
||||||
let memberList = roleElement.querySelector('.member-list');
|
let memberList = roleElement.querySelector('.member-list');
|
||||||
if (memberList) {
|
if (memberList) {
|
||||||
@ -261,12 +232,12 @@ function toggleMembers(role: { members: { id: string | number; name: string; }[]
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Load the list of members
|
// Load the list of members
|
||||||
function loadMemberChat(memberId: string | number) {
|
function loadMemberChat(memberId: string | number) {
|
||||||
selectedMemberId = String(memberId);
|
selectedMemberId = String(memberId);
|
||||||
const memberMessages = messagesMock.find(m => String(m.memberId) === String(memberId));
|
const memberMessages = messagesMock.find(m => String(m.memberId) === String(memberId));
|
||||||
|
|
||||||
// Trouver le processus et le rôle du membre
|
// Find the process and the role of the member
|
||||||
let memberInfo = { processName: '', roleName: '', memberName: '' };
|
let memberInfo = { processName: '', roleName: '', memberName: '' };
|
||||||
groupsMock.forEach(process => {
|
groupsMock.forEach(process => {
|
||||||
process.roles.forEach(role => {
|
process.roles.forEach(role => {
|
||||||
@ -349,15 +320,15 @@ function sendMessage() {
|
|||||||
type: 'text' as const
|
type: 'text' as const
|
||||||
};
|
};
|
||||||
|
|
||||||
// Ajouter et afficher le message immédiatement
|
// Add and display the message immediately
|
||||||
messageStore.addMessage(selectedMemberId, newMessage);
|
messageStore.addMessage(selectedMemberId, newMessage);
|
||||||
messagesMock = messageStore.getMessages();
|
messagesMock = messageStore.getMessages();
|
||||||
loadMemberChat(selectedMemberId);
|
loadMemberChat(selectedMemberId);
|
||||||
|
|
||||||
// Réinitialiser l'input
|
// Reset the input
|
||||||
messageInput.value = '';
|
messageInput.value = '';
|
||||||
|
|
||||||
// Réponse automatique après 2 secondes
|
// Automatic response after 2 seconds
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (selectedMemberId) {
|
if (selectedMemberId) {
|
||||||
const autoReply = generateAutoReply(`Member ${selectedMemberId}`);
|
const autoReply = generateAutoReply(`Member ${selectedMemberId}`);
|
||||||
@ -509,11 +480,11 @@ document.addEventListener('click', (event) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// ------------------ PROCESS DETAILS ------------------
|
// ------------------ PROCESS DETAILS ------------------
|
||||||
// Fonction pour afficher les détails du processus
|
// Function to display the process details
|
||||||
function showProcessDetails(group: Group, groupId: number) {
|
function showProcessDetails(group: Group, groupId: number) {
|
||||||
console.log('Showing details for group:', groupId);
|
console.log('Showing details for group:', groupId);
|
||||||
|
|
||||||
// Fermer toutes les vues de processus existantes
|
// Close all existing process views
|
||||||
const allDetailsAreas = document.querySelectorAll('.process-details');
|
const allDetailsAreas = document.querySelectorAll('.process-details');
|
||||||
allDetailsAreas.forEach(area => {
|
allDetailsAreas.forEach(area => {
|
||||||
(area as HTMLElement).style.display = 'none';
|
(area as HTMLElement).style.display = 'none';
|
||||||
@ -525,11 +496,11 @@ function showProcessDetails(group: Group, groupId: number) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Charger les données du localStorage
|
// Load the data from localStorage
|
||||||
const storedGroups = JSON.parse(localStorage.getItem('groups') || '[]');
|
const storedGroups = JSON.parse(localStorage.getItem('groups') || '[]');
|
||||||
const storedGroup = storedGroups.find((g: Group) => g.id === groupId);
|
const storedGroup = storedGroups.find((g: Group) => g.id === groupId);
|
||||||
|
|
||||||
// Utiliser les données du localStorage si disponibles, sinon utiliser le groupe passé en paramètre
|
// Use the data from localStorage if available, otherwise use the group passed as a parameter
|
||||||
const displayGroup = storedGroup || group;
|
const displayGroup = storedGroup || group;
|
||||||
|
|
||||||
let detailsArea = document.getElementById(`process-details-${groupId}`);
|
let detailsArea = document.getElementById(`process-details-${groupId}`);
|
||||||
@ -565,7 +536,6 @@ function showProcessDetails(group: Group, groupId: number) {
|
|||||||
sig.member && 'id' in sig.member && sig.member.id === currentUser.id && !sig.signed
|
sig.member && 'id' in sig.member && sig.member.id === currentUser.id && !sig.signed
|
||||||
);
|
);
|
||||||
|
|
||||||
// Ajouter le bouton de signature pour tous les documents non vierges en mode dev
|
|
||||||
const signButton = !isVierge ? `
|
const signButton = !isVierge ? `
|
||||||
${totalSignatures > 0 && signedCount < totalSignatures && canSign ? `
|
${totalSignatures > 0 && signedCount < totalSignatures && canSign ? `
|
||||||
<button class="sign-button" onclick="signDocument(${document.id}, ${groupId}, true)">
|
<button class="sign-button" onclick="signDocument(${document.id}, ${groupId}, true)">
|
||||||
@ -625,7 +595,7 @@ function showProcessDetails(group: Group, groupId: number) {
|
|||||||
<div class="details-section">
|
<div class="details-section">
|
||||||
<h3>Roles and Documents</h3>
|
<h3>Roles and Documents</h3>
|
||||||
${displayGroup.roles.map((role: { name: string; documents?: any[] }) => {
|
${displayGroup.roles.map((role: { name: string; documents?: any[] }) => {
|
||||||
// Filtrer les documents selon les droits d'accès
|
// Filter the documents according to the access rights
|
||||||
const accessibleDocuments = (role.documents || []).filter(doc =>
|
const accessibleDocuments = (role.documents || []).filter(doc =>
|
||||||
canUserAccessDocument(doc, role.name, currentUser.processRoles?.[0]?.role || '')
|
canUserAccessDocument(doc, role.name, currentUser.processRoles?.[0]?.role || '')
|
||||||
);
|
);
|
||||||
@ -711,10 +681,6 @@ function showProcessDetails(group: Group, groupId: number) {
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
/**const newRequestBtn = document.createElement('button');
|
|
||||||
newRequestBtn.className = 'new-request-btn';
|
|
||||||
newRequestBtn.textContent = 'New request';
|
|
||||||
newRequestBtn.onclick = () => newRequest(group);**/
|
|
||||||
|
|
||||||
const newCloseProcessButton = document.createElement('button');
|
const newCloseProcessButton = document.createElement('button');
|
||||||
newCloseProcessButton.className = 'close-btn';
|
newCloseProcessButton.className = 'close-btn';
|
||||||
@ -723,13 +689,12 @@ function showProcessDetails(group: Group, groupId: number) {
|
|||||||
|
|
||||||
const headerButtons = detailsArea.querySelector('.header-buttons');
|
const headerButtons = detailsArea.querySelector('.header-buttons');
|
||||||
if (headerButtons) {
|
if (headerButtons) {
|
||||||
/**headerButtons.appendChild(newRequestBtn);**/
|
|
||||||
headerButtons.appendChild(newCloseProcessButton);
|
headerButtons.appendChild(newCloseProcessButton);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fonction pour fermer les détails et revenir au chat
|
// Function to close the details and return to the chat
|
||||||
function closeProcessDetails(groupId: number) {
|
function closeProcessDetails(groupId: number) {
|
||||||
const detailsArea = document.getElementById(`process-details-${groupId}`);
|
const detailsArea = document.getElementById(`process-details-${groupId}`);
|
||||||
const chatArea = document.getElementById('chat-area');
|
const chatArea = document.getElementById('chat-area');
|
||||||
@ -746,7 +711,7 @@ function closeProcessDetails(groupId: number) {
|
|||||||
window.closeProcessDetails = closeProcessDetails;
|
window.closeProcessDetails = closeProcessDetails;
|
||||||
window.loadMemberChat = loadMemberChat;
|
window.loadMemberChat = loadMemberChat;
|
||||||
|
|
||||||
// Nouvelle fonction pour afficher les documents d'un rôle
|
// New function to display the documents of a role
|
||||||
function showRoleDocuments(role: {
|
function showRoleDocuments(role: {
|
||||||
name: string;
|
name: string;
|
||||||
documents?: Array<{
|
documents?: Array<{
|
||||||
@ -761,16 +726,16 @@ function showRoleDocuments(role: {
|
|||||||
}>;
|
}>;
|
||||||
id?: number;
|
id?: number;
|
||||||
}, group: Group) {
|
}, group: Group) {
|
||||||
// Charger les données depuis le localStorage
|
// Load the data from localStorage
|
||||||
const storedGroups = JSON.parse(localStorage.getItem('groups') || '[]');
|
const storedGroups = JSON.parse(localStorage.getItem('groups') || '[]');
|
||||||
const storedGroup = storedGroups.find((g: Group) => g.id === group.id);
|
const storedGroup = storedGroups.find((g: Group) => g.id === group.id);
|
||||||
const storedRole = storedGroup?.roles.find((r: any) => r.name === role.name);
|
const storedRole = storedGroup?.roles.find((r: any) => r.name === role.name);
|
||||||
|
|
||||||
// Utiliser les données du localStorage si disponibles, sinon utiliser les données passées en paramètre
|
// Use the data from localStorage if available, otherwise use the data passed as a parameter
|
||||||
const displayRole = storedRole || role;
|
const displayRole = storedRole || role;
|
||||||
|
|
||||||
console.log('Showing documents for role:', displayRole.name, 'in group:', group.name);
|
console.log('Showing documents for role:', displayRole.name, 'in group:', group.name);
|
||||||
// Fermer d'abord toutes les vues de documents existantes
|
// Close all existing document views first
|
||||||
const allDetailsAreas = document.querySelectorAll('.process-details');
|
const allDetailsAreas = document.querySelectorAll('.process-details');
|
||||||
allDetailsAreas.forEach(area => {
|
allDetailsAreas.forEach(area => {
|
||||||
area.remove();
|
area.remove();
|
||||||
@ -782,11 +747,11 @@ function showRoleDocuments(role: {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Créer une nouvelle zone de détails
|
// Create a new details area
|
||||||
const detailsArea = document.createElement('div');
|
const detailsArea = document.createElement('div');
|
||||||
detailsArea.id = `role-documents-${displayRole.name}`;
|
detailsArea.id = `role-documents-${displayRole.name}`;
|
||||||
detailsArea.className = 'process-details';
|
detailsArea.className = 'process-details';
|
||||||
// Filtrer les documents accessibles
|
// Filter the accessible documents
|
||||||
const accessibleDocuments = (displayRole.documents || []).filter((doc: {
|
const accessibleDocuments = (displayRole.documents || []).filter((doc: {
|
||||||
name: string;
|
name: string;
|
||||||
visibility: string;
|
visibility: string;
|
||||||
@ -862,7 +827,7 @@ function showRoleDocuments(role: {
|
|||||||
<p>${signedCount} out of ${totalSignatures} signed (${percentage.toFixed(0)}%)</p>
|
<p>${signedCount} out of ${totalSignatures} signed (${percentage.toFixed(0)}%)</p>
|
||||||
</div>
|
</div>
|
||||||
` : `
|
` : `
|
||||||
<p>Document vierge - En attente de création</p>
|
<p>Blank document - Waiting for creation</p>
|
||||||
${canUserAccessDocument(document, displayRole.name, currentUser.processRoles?.[0]?.role || '') ? `
|
${canUserAccessDocument(document, displayRole.name, currentUser.processRoles?.[0]?.role || '') ? `
|
||||||
<button class="new-request-btn" onclick="newRequest({
|
<button class="new-request-btn" onclick="newRequest({
|
||||||
processId: ${group.id},
|
processId: ${group.id},
|
||||||
@ -887,7 +852,7 @@ function showRoleDocuments(role: {
|
|||||||
container.appendChild(detailsArea);
|
container.appendChild(detailsArea);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fonction pour fermer la vue des documents d'un rôle
|
// Function to close the documents view of a role
|
||||||
function closeRoleDocuments(roleName: string) {
|
function closeRoleDocuments(roleName: string) {
|
||||||
const detailsArea = document.getElementById(`role-documents-${roleName}`);
|
const detailsArea = document.getElementById(`role-documents-${roleName}`);
|
||||||
if (detailsArea) {
|
if (detailsArea) {
|
||||||
@ -901,7 +866,7 @@ window.closeRoleDocuments = closeRoleDocuments;
|
|||||||
|
|
||||||
window.switchUser = switchUser;
|
window.switchUser = switchUser;
|
||||||
|
|
||||||
// Fonction pour calculer la durée entre deux dates
|
// Function to calculate the duration between two dates
|
||||||
function calculateDuration(startDate: string | null | undefined, endDate: string | null | undefined): number {
|
function calculateDuration(startDate: string | null | undefined, endDate: string | null | undefined): number {
|
||||||
const start = new Date(startDate || '');
|
const start = new Date(startDate || '');
|
||||||
const end = new Date(endDate || '');
|
const end = new Date(endDate || '');
|
||||||
@ -914,38 +879,27 @@ window.newRequest = newRequest;
|
|||||||
window.submitRequest = submitRequest;
|
window.submitRequest = submitRequest;
|
||||||
window.closeNewRequest = closeNewRequest;
|
window.closeNewRequest = closeNewRequest;
|
||||||
|
|
||||||
// Définir la fonction removeMember pour supprimer un membre par son ID
|
// Function to manage the new request
|
||||||
function removeMember(memberId: string | number) {
|
|
||||||
const memberElement = document.querySelector(`.selected-member[data-member-id="${memberId}"]`);
|
|
||||||
if (memberElement) {
|
|
||||||
memberElement.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
window.removeMember = removeMember;
|
|
||||||
|
|
||||||
|
|
||||||
// Fonction pour gérer la nouvelle demande
|
|
||||||
function newRequest(params: RequestParams) {
|
function newRequest(params: RequestParams) {
|
||||||
// Ajout de validation des paramètres
|
// Add parameter validation
|
||||||
if (!params || !params.processId) {
|
if (!params || !params.processId) {
|
||||||
console.error('Paramètres invalides:', params);
|
console.error('Paramètres invalides:', params);
|
||||||
showAlert('Paramètres invalides pour la nouvelle demande');
|
showAlert('Invalid parameters for new request');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const modal = document.createElement('div');
|
const modal = document.createElement('div');
|
||||||
modal.className = 'modal-overlay';
|
modal.className = 'modal-overlay';
|
||||||
|
|
||||||
// Récupérer le processus avec une vérification
|
// Retrieve the process with a verification
|
||||||
const process = groupsMock.find(g => g.id === params.processId);
|
const process = groupsMock.find(g => g.id === params.processId);
|
||||||
if (!process) {
|
if (!process) {
|
||||||
console.error('Processus non trouvé:', params.processId);
|
console.error('Processus non trouvé:', params.processId);
|
||||||
showAlert('Processus non trouvé');
|
showAlert('Process not found');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Déterminer les membres avec une vérification supplémentaire
|
// Determine the members with an additional verification
|
||||||
let membersToDisplay = [];
|
let membersToDisplay = [];
|
||||||
try {
|
try {
|
||||||
if (params.roleName === 'common') {
|
if (params.roleName === 'common') {
|
||||||
@ -958,7 +912,7 @@ function newRequest(params: RequestParams) {
|
|||||||
} else {
|
} else {
|
||||||
const role = process.roles.find(r => r.name === params.roleName);
|
const role = process.roles.find(r => r.name === params.roleName);
|
||||||
if (!role) {
|
if (!role) {
|
||||||
throw new Error(`Rôle ${params.roleName} non trouvé`);
|
throw new Error(`Role ${params.roleName} not found`);
|
||||||
}
|
}
|
||||||
membersToDisplay = role.members.map(member => ({
|
membersToDisplay = role.members.map(member => ({
|
||||||
...member,
|
...member,
|
||||||
@ -966,8 +920,8 @@ function newRequest(params: RequestParams) {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Erreur lors de la récupération des membres:', error);
|
console.error('Error retrieving members:', error);
|
||||||
showAlert('Erreur lors de la récupération des membres');
|
showAlert('Error retrieving members');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1067,12 +1021,12 @@ function newRequest(params: RequestParams) {
|
|||||||
const fileInput = modal.querySelector('#fileInput') as HTMLInputElement;
|
const fileInput = modal.querySelector('#fileInput') as HTMLInputElement;
|
||||||
const fileList = modal.querySelector('#fileList') as HTMLDivElement;
|
const fileList = modal.querySelector('#fileList') as HTMLDivElement;
|
||||||
|
|
||||||
// Rendre la zone cliquable
|
// Make the area clickable
|
||||||
dropZone.addEventListener('click', () => {
|
dropZone.addEventListener('click', () => {
|
||||||
fileInput.click();
|
fileInput.click();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Gérer la sélection de fichiers
|
// Manage the file selection
|
||||||
fileInput.addEventListener('change', (e: Event) => {
|
fileInput.addEventListener('change', (e: Event) => {
|
||||||
const target = e.target as HTMLInputElement;
|
const target = e.target as HTMLInputElement;
|
||||||
if (target.files && target.files.length > 0) {
|
if (target.files && target.files.length > 0) {
|
||||||
@ -1080,7 +1034,7 @@ function newRequest(params: RequestParams) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Gérer le drag & drop
|
// Manage the drag & drop
|
||||||
dropZone.addEventListener('dragover', (e: DragEvent) => {
|
dropZone.addEventListener('dragover', (e: DragEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
dropZone.classList.add('dragover');
|
dropZone.classList.add('dragover');
|
||||||
@ -1103,7 +1057,7 @@ function newRequest(params: RequestParams) {
|
|||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
reader.onload = (e) => {
|
reader.onload = (e) => {
|
||||||
const fileContent = e.target?.result;
|
const fileContent = e.target?.result;
|
||||||
// Vérifier si le fichier n'est pas déjà dans la liste
|
// Verify if the file is not already in the list
|
||||||
const existingFiles = fileList.querySelectorAll('.file-name');
|
const existingFiles = fileList.querySelectorAll('.file-name');
|
||||||
const isDuplicate = Array.from(existingFiles).some(
|
const isDuplicate = Array.from(existingFiles).some(
|
||||||
existingFile => existingFile.textContent === file.name
|
existingFile => existingFile.textContent === file.name
|
||||||
@ -1150,11 +1104,11 @@ function submitNewDocument(event: Event) {
|
|||||||
|
|
||||||
const form = document.getElementById('newDocumentForm') as HTMLFormElement;
|
const form = document.getElementById('newDocumentForm') as HTMLFormElement;
|
||||||
if (!form) {
|
if (!form) {
|
||||||
showAlert('Formulaire non trouvé');
|
showAlert('Form not found');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Récupération des fichiers
|
// Retrieve the files
|
||||||
const fileList = document.getElementById('fileList');
|
const fileList = document.getElementById('fileList');
|
||||||
const files = Array.from(fileList?.querySelectorAll('.file-item') || []).map(fileItem => {
|
const files = Array.from(fileList?.querySelectorAll('.file-item') || []).map(fileItem => {
|
||||||
const fileName = fileItem.querySelector('.file-name')?.textContent || '';
|
const fileName = fileItem.querySelector('.file-name')?.textContent || '';
|
||||||
@ -1164,7 +1118,7 @@ function submitNewDocument(event: Event) {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// Récupération des valeurs du formulaire
|
// Retrieve the values from the form
|
||||||
const processId = Number((form.querySelector('#processId') as HTMLInputElement)?.value);
|
const processId = Number((form.querySelector('#processId') as HTMLInputElement)?.value);
|
||||||
const documentId = Number((form.querySelector('#documentId') as HTMLInputElement)?.value);
|
const documentId = Number((form.querySelector('#documentId') as HTMLInputElement)?.value);
|
||||||
const documentName = (form.querySelector('#documentName') as HTMLInputElement)?.value?.trim();
|
const documentName = (form.querySelector('#documentName') as HTMLInputElement)?.value?.trim();
|
||||||
@ -1174,17 +1128,17 @@ function submitNewDocument(event: Event) {
|
|||||||
|
|
||||||
// Validation
|
// Validation
|
||||||
if (!documentName || !description || !deadline) {
|
if (!documentName || !description || !deadline) {
|
||||||
showAlert('Veuillez remplir tous les champs obligatoires');
|
showAlert('Please fill in all required fields');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Récupérer les données actuelles
|
// Retrieve the current data
|
||||||
const groups = JSON.parse(localStorage.getItem('groups') || JSON.stringify(groupsMock));
|
const groups = JSON.parse(localStorage.getItem('groups') || JSON.stringify(groupsMock));
|
||||||
const group = groups.find((g: Group) => g.id === processId);
|
const group = groups.find((g: Group) => g.id === processId);
|
||||||
|
|
||||||
if (!group) {
|
if (!group) {
|
||||||
showAlert('Processus non trouvé');
|
showAlert('Process not found');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1193,11 +1147,11 @@ function submitNewDocument(event: Event) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!role) {
|
if (!role) {
|
||||||
showAlert('Rôle non trouvé');
|
showAlert('Role not found');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Créer le nouveau document avec les signatures des membres du rôle
|
// Create the new document with the signatures of the role members
|
||||||
const updatedDocument = {
|
const updatedDocument = {
|
||||||
id: documentId,
|
id: documentId,
|
||||||
name: documentName,
|
name: documentName,
|
||||||
@ -1214,16 +1168,16 @@ function submitNewDocument(event: Event) {
|
|||||||
files: files // Ajout des fichiers au document
|
files: files // Ajout des fichiers au document
|
||||||
};
|
};
|
||||||
|
|
||||||
// Mettre à jour le document dans le rôle
|
// Update the document in the role
|
||||||
const documentIndex = role.documents.findIndex((d: any) => d.id === documentId);
|
const documentIndex = role.documents.findIndex((d: any) => d.id === documentId);
|
||||||
if (documentIndex !== -1) {
|
if (documentIndex !== -1) {
|
||||||
role.documents[documentIndex] = updatedDocument;
|
role.documents[documentIndex] = updatedDocument;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sauvegarder dans le localStorage
|
// Save in localStorage
|
||||||
localStorage.setItem('groups', JSON.stringify(groups));
|
localStorage.setItem('groups', JSON.stringify(groups));
|
||||||
|
|
||||||
// Mettre à jour également groupsMock pour la cohérence
|
// Also update groupsMock for consistency
|
||||||
const mockGroup = groupsMock.find(g => g.id === processId);
|
const mockGroup = groupsMock.find(g => g.id === processId);
|
||||||
if (mockGroup) {
|
if (mockGroup) {
|
||||||
const mockRole = mockGroup.roles.find(r => r.name === role.name);
|
const mockRole = mockGroup.roles.find(r => r.name === role.name);
|
||||||
@ -1238,18 +1192,18 @@ function submitNewDocument(event: Event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fermer le modal
|
// Close the modal
|
||||||
if (event.target instanceof HTMLElement) {
|
if (event.target instanceof HTMLElement) {
|
||||||
closeModal(event.target);
|
closeModal(event.target);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recharger la vue des documents avec les données mises à jour
|
// Reload the documents view with the updated data
|
||||||
showRoleDocuments(role, group);
|
showRoleDocuments(role, group);
|
||||||
showAlert('Document mis à jour avec succès!');
|
showAlert('Document updated successfully!');
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Erreur lors de la sauvegarde:', error);
|
console.error('Error saving:', error);
|
||||||
showAlert('Une erreur est survenue lors de la sauvegarde');
|
showAlert('An error occurred while saving');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1260,7 +1214,7 @@ function submitCommonDocument(event: Event) {
|
|||||||
|
|
||||||
const form = document.getElementById('newDocumentForm') as HTMLFormElement;
|
const form = document.getElementById('newDocumentForm') as HTMLFormElement;
|
||||||
if (!form) {
|
if (!form) {
|
||||||
showAlert('Formulaire non trouvé');
|
showAlert('Form not found');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1272,7 +1226,7 @@ function submitCommonDocument(event: Event) {
|
|||||||
const visibility = (form.querySelector('#visibility') as HTMLSelectElement)?.value;
|
const visibility = (form.querySelector('#visibility') as HTMLSelectElement)?.value;
|
||||||
|
|
||||||
if (!documentName || !description || !deadline) {
|
if (!documentName || !description || !deadline) {
|
||||||
showAlert('Veuillez remplir tous les champs obligatoires');
|
showAlert('Please fill in all required fields');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1281,11 +1235,11 @@ function submitCommonDocument(event: Event) {
|
|||||||
const group = groups.find((g: Group) => g.id === processId);
|
const group = groups.find((g: Group) => g.id === processId);
|
||||||
|
|
||||||
if (!group) {
|
if (!group) {
|
||||||
showAlert('Processus non trouvé');
|
showAlert('Process not found');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Récupérer tous les membres de tous les rôles du groupe
|
// Retrieve all members of all roles in the group
|
||||||
const allMembers = group.roles.reduce((acc: any[], role: any) => {
|
const allMembers = group.roles.reduce((acc: any[], role: any) => {
|
||||||
return acc.concat(role.members);
|
return acc.concat(role.members);
|
||||||
}, []);
|
}, []);
|
||||||
@ -1315,7 +1269,7 @@ function submitCommonDocument(event: Event) {
|
|||||||
files: files
|
files: files
|
||||||
};
|
};
|
||||||
|
|
||||||
// Mettre à jour le document commun
|
// Update the common document
|
||||||
const documentIndex = group.commonDocuments.findIndex((d: { id: number }) => d.id === documentId);
|
const documentIndex = group.commonDocuments.findIndex((d: { id: number }) => d.id === documentId);
|
||||||
if (documentIndex !== -1) {
|
if (documentIndex !== -1) {
|
||||||
group.commonDocuments[documentIndex] = updatedDocument;
|
group.commonDocuments[documentIndex] = updatedDocument;
|
||||||
@ -1328,11 +1282,11 @@ function submitCommonDocument(event: Event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
showProcessDetails(group, group.id);
|
showProcessDetails(group, group.id);
|
||||||
showAlert('Document commun mis à jour avec succès!');
|
showAlert('Document common updated successfully!');
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Erreur lors de la sauvegarde:', error);
|
console.error('Error saving:', error);
|
||||||
showAlert('Une erreur est survenue lors de la sauvegarde');
|
showAlert('An error occurred while saving');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1461,64 +1415,9 @@ if (addMembersBtn) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fonction d'initialisation pour le router
|
// FUNCTIONS FOR SIGNATURE
|
||||||
export function initSignature() {
|
|
||||||
// Réinitialiser l'affichage
|
|
||||||
const groupList = document.getElementById('group-list');
|
|
||||||
if (groupList) {
|
|
||||||
groupList.innerHTML = ''; // Nettoyer la liste existante
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recharger les messages depuis le store
|
// Add this function to sign a document
|
||||||
messagesMock = messageStore.getMessages();
|
|
||||||
if (messagesMock.length === 0) {
|
|
||||||
messageStore.setMessages(initialMessagesMock);
|
|
||||||
messagesMock = messageStore.getMessages();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Réinitialiser l'interface
|
|
||||||
updateCurrentUserDisplay();
|
|
||||||
loadGroupList();
|
|
||||||
|
|
||||||
// Si un membre était sélectionné, recharger son chat
|
|
||||||
if (selectedMemberId) {
|
|
||||||
loadMemberChat(selectedMemberId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Event listeners
|
|
||||||
document.addEventListener('click', (event) => {
|
|
||||||
const userList = document.getElementById('userList');
|
|
||||||
const userSwitchBtn = document.getElementById('userSwitchBtn');
|
|
||||||
if (userSwitchBtn && userList && !userSwitchBtn.contains(event.target as Node) && !userList.contains(event.target as Node)) {
|
|
||||||
userList.classList.remove('show');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Réattacher les event listeners pour les messages
|
|
||||||
const sendBtn = document.getElementById('send-button');
|
|
||||||
if (sendBtn) sendBtn.onclick = sendMessage;
|
|
||||||
|
|
||||||
const messageInput = document.getElementById('message-input');
|
|
||||||
if (messageInput) {
|
|
||||||
messageInput.addEventListener('keydown', function (event) {
|
|
||||||
if (event.key === 'Enter') {
|
|
||||||
event.preventDefault();
|
|
||||||
sendMessage();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ajouter cette interface pour la signature
|
|
||||||
interface SignatureResponse {
|
|
||||||
success: boolean;
|
|
||||||
message: string;
|
|
||||||
documentId: number;
|
|
||||||
memberId: string | number;
|
|
||||||
signedAt: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ajouter cette fonction pour signer un document
|
|
||||||
function signDocument(documentId: number, processId: number, isCommonDocument: boolean = false) {
|
function signDocument(documentId: number, processId: number, isCommonDocument: boolean = false) {
|
||||||
if (typeof window === 'undefined' || typeof document === 'undefined') {
|
if (typeof window === 'undefined' || typeof document === 'undefined') {
|
||||||
console.error('Cette fonction ne peut être exécutée que dans un navigateur');
|
console.error('Cette fonction ne peut être exécutée que dans un navigateur');
|
||||||
@ -1530,7 +1429,7 @@ function signDocument(documentId: number, processId: number, isCommonDocument: b
|
|||||||
const group = groups.find((g: Group) => g.id === processId);
|
const group = groups.find((g: Group) => g.id === processId);
|
||||||
|
|
||||||
if (!group) {
|
if (!group) {
|
||||||
throw new Error('Processus non trouvé');
|
throw new Error('Process not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
let targetDoc;
|
let targetDoc;
|
||||||
@ -1546,7 +1445,7 @@ function signDocument(documentId: number, processId: number, isCommonDocument: b
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!targetDoc) {
|
if (!targetDoc) {
|
||||||
throw new Error('Document non trouvé');
|
throw new Error('Document not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
const canSign = isCommonDocument ?
|
const canSign = isCommonDocument ?
|
||||||
@ -1556,11 +1455,11 @@ function signDocument(documentId: number, processId: number, isCommonDocument: b
|
|||||||
canUserSignDocument(targetDoc, currentUser?.name, currentUser);
|
canUserSignDocument(targetDoc, currentUser?.name, currentUser);
|
||||||
|
|
||||||
if (!canSign) {
|
if (!canSign) {
|
||||||
showAlert("Vous n'avez pas les droits nécessaires pour signer ce document.");
|
showAlert("You do not have the necessary rights to sign this document.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Créer et insérer la modal directement dans le body
|
// Create and insert the modal directly into the body
|
||||||
const modalHtml = `
|
const modalHtml = `
|
||||||
<div class="modal-overlay" id="signatureModal">
|
<div class="modal-overlay" id="signatureModal">
|
||||||
<div class="modal-document">
|
<div class="modal-document">
|
||||||
@ -1590,7 +1489,7 @@ function signDocument(documentId: number, processId: number, isCommonDocument: b
|
|||||||
|
|
||||||
<div class="description-section">
|
<div class="description-section">
|
||||||
<h4>Description:</h4>
|
<h4>Description:</h4>
|
||||||
<p>${targetDoc.description || 'Aucune description disponible'}</p>
|
<p>${targetDoc.description || 'No description available'}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="signatures-section">
|
<div class="signatures-section">
|
||||||
@ -1601,8 +1500,8 @@ function signDocument(documentId: number, processId: number, isCommonDocument: b
|
|||||||
<span class="signer-name">${sig.member.name}</span>
|
<span class="signer-name">${sig.member.name}</span>
|
||||||
<span class="signature-status">
|
<span class="signature-status">
|
||||||
${sig.signed ?
|
${sig.signed ?
|
||||||
`✓ Signé le ${sig.signedAt ? new Date(sig.signedAt).toLocaleDateString() : 'date inconnue'}` :
|
`✓ Signed on ${sig.signedAt ? new Date(sig.signedAt).toLocaleDateString() : 'unknown date'}` :
|
||||||
'⌛ En attente'}
|
'⌛ Pending'}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
`).join('')}
|
`).join('')}
|
||||||
@ -1623,20 +1522,20 @@ function signDocument(documentId: number, processId: number, isCommonDocument: b
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
`).join('')
|
`).join('')
|
||||||
: '<p>Aucun fichier joint</p>'
|
: '<p>No file attached</p>'
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
` : ''}
|
` : ''}
|
||||||
|
|
||||||
<div class="confirmation-section">
|
<div class="confirmation-section">
|
||||||
<p class="warning-text">En signant ce document, vous confirmez avoir pris connaissance de son contenu.</p>
|
<p class="warning-text">By signing this document, you confirm that you have read its contents.</p>
|
||||||
<div class="signature-slider-container">
|
<div class="signature-slider-container">
|
||||||
<div class="slider-track">
|
<div class="slider-track">
|
||||||
<div class="slider-handle" id="signatureSlider" draggable="true">
|
<div class="slider-handle" id="signatureSlider" draggable="true">
|
||||||
<span class="slider-arrow">➜</span>
|
<span class="slider-arrow">➜</span>
|
||||||
</div>
|
</div>
|
||||||
<span class="slider-text">Glisser pour signer</span>
|
<span class="slider-text">Drag to sign</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -1647,7 +1546,7 @@ function signDocument(documentId: number, processId: number, isCommonDocument: b
|
|||||||
|
|
||||||
document.body.insertAdjacentHTML('beforeend', modalHtml);
|
document.body.insertAdjacentHTML('beforeend', modalHtml);
|
||||||
|
|
||||||
// Ajouter la logique du slider après création de la modal
|
// Add the slider logic after creating the modal
|
||||||
const slider = document.getElementById('signatureSlider');
|
const slider = document.getElementById('signatureSlider');
|
||||||
const sliderTrack = slider?.parentElement;
|
const sliderTrack = slider?.parentElement;
|
||||||
let isDragging = false;
|
let isDragging = false;
|
||||||
@ -1659,7 +1558,7 @@ function signDocument(documentId: number, processId: number, isCommonDocument: b
|
|||||||
document.addEventListener('mousemove', drag);
|
document.addEventListener('mousemove', drag);
|
||||||
document.addEventListener('mouseup', stopDrag);
|
document.addEventListener('mouseup', stopDrag);
|
||||||
|
|
||||||
// Touch events pour mobile
|
// Touch events for mobile
|
||||||
slider.addEventListener('touchstart', initDrag);
|
slider.addEventListener('touchstart', initDrag);
|
||||||
document.addEventListener('touchmove', drag);
|
document.addEventListener('touchmove', drag);
|
||||||
document.addEventListener('touchend', stopDrag);
|
document.addEventListener('touchend', stopDrag);
|
||||||
@ -1678,17 +1577,17 @@ function signDocument(documentId: number, processId: number, isCommonDocument: b
|
|||||||
const rect = sliderTrack.getBoundingClientRect();
|
const rect = sliderTrack.getBoundingClientRect();
|
||||||
const x = 'touches' in e ? e.touches[0].clientX : e.clientX;
|
const x = 'touches' in e ? e.touches[0].clientX : e.clientX;
|
||||||
|
|
||||||
// Calculer la position relative à la track
|
// Calculate the position relative to the track
|
||||||
let newLeft = x - rect.left - (slider.offsetWidth / 2);
|
let newLeft = x - rect.left - (slider.offsetWidth / 2);
|
||||||
|
|
||||||
// Limiter le déplacement
|
// Limit the movement
|
||||||
const maxLeft = sliderTrack.offsetWidth - slider.offsetWidth;
|
const maxLeft = sliderTrack.offsetWidth - slider.offsetWidth;
|
||||||
newLeft = Math.max(0, Math.min(newLeft, maxLeft));
|
newLeft = Math.max(0, Math.min(newLeft, maxLeft));
|
||||||
|
|
||||||
// Mettre à jour la position
|
// Update the position
|
||||||
slider.style.left = `${newLeft}px`;
|
slider.style.left = `${newLeft}px`;
|
||||||
|
|
||||||
// Si le slider atteint 90% du chemin, déclencher la signature
|
// If the slider reaches 90% of the path, trigger the signature
|
||||||
if (newLeft > maxLeft * 0.9) {
|
if (newLeft > maxLeft * 0.9) {
|
||||||
stopDrag(e);
|
stopDrag(e);
|
||||||
confirmSignature(documentId, processId, isCommonDocument);
|
confirmSignature(documentId, processId, isCommonDocument);
|
||||||
@ -1699,29 +1598,29 @@ function signDocument(documentId: number, processId: number, isCommonDocument: b
|
|||||||
if (!isDragging || !slider) return;
|
if (!isDragging || !slider) return;
|
||||||
isDragging = false;
|
isDragging = false;
|
||||||
|
|
||||||
// Réinitialiser la position si pas assez glissé
|
// Reset the position if not enough dragged
|
||||||
if (slider.offsetLeft < (sliderTrack?.offsetWidth || 0) * 0.9) {
|
if (slider.offsetLeft < (sliderTrack?.offsetWidth || 0) * 0.9) {
|
||||||
slider.style.left = '0px';
|
slider.style.left = '0px';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Erreur lors de l\'affichage de la modal:', error);
|
console.error('Error displaying modal:', error);
|
||||||
showAlert(error instanceof Error ? error.message : 'Erreur lors de l\'affichage de la modal');
|
showAlert(error instanceof Error ? error.message : 'Error displaying modal');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nouvelle fonction pour confirmer la signature
|
// New function to confirm the signature
|
||||||
function confirmSignature(documentId: number, processId: number, isCommonDocument: boolean) {
|
function confirmSignature(documentId: number, processId: number, isCommonDocument: boolean) {
|
||||||
try {
|
try {
|
||||||
// Ajout du console.log pour voir l'utilisateur actuel
|
// Add console.log to see the current user
|
||||||
console.log('Current user:', currentUser);
|
console.log('Current user:', currentUser);
|
||||||
|
|
||||||
const groups = JSON.parse(localStorage.getItem('groups') || JSON.stringify(groupsMock));
|
const groups = JSON.parse(localStorage.getItem('groups') || JSON.stringify(groupsMock));
|
||||||
const group = groups.find((g: Group) => g.id === processId);
|
const group = groups.find((g: Group) => g.id === processId);
|
||||||
|
|
||||||
if (!group) {
|
if (!group) {
|
||||||
throw new Error('Processus non trouvé');
|
throw new Error('Process not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
let targetDoc;
|
let targetDoc;
|
||||||
@ -1737,7 +1636,7 @@ function confirmSignature(documentId: number, processId: number, isCommonDocumen
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!targetDoc) {
|
if (!targetDoc) {
|
||||||
throw new Error('Document non trouvé');
|
throw new Error('Document not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
const userSignature = targetDoc.signatures.find((sig: DocumentSignature) =>
|
const userSignature = targetDoc.signatures.find((sig: DocumentSignature) =>
|
||||||
@ -1745,7 +1644,7 @@ function confirmSignature(documentId: number, processId: number, isCommonDocumen
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!userSignature) {
|
if (!userSignature) {
|
||||||
throw new Error(`L'utilisateur ${currentUser.name} n'est pas autorisé à signer ce document. Veuillez vous connecter avec un utilisateur autorisé.`);
|
throw new Error(`The user ${currentUser.name} is not authorized to sign this document. Please log in with an authorized user.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
userSignature.signed = true;
|
userSignature.signed = true;
|
||||||
@ -1753,7 +1652,6 @@ function confirmSignature(documentId: number, processId: number, isCommonDocumen
|
|||||||
|
|
||||||
localStorage.setItem('groups', JSON.stringify(groups));
|
localStorage.setItem('groups', JSON.stringify(groups));
|
||||||
|
|
||||||
// Modification ici : utiliser document.querySelector au lieu de document
|
|
||||||
const closeBtn = document.querySelector('.modal-overlay .close-btn');
|
const closeBtn = document.querySelector('.modal-overlay .close-btn');
|
||||||
if (closeBtn instanceof HTMLElement) {
|
if (closeBtn instanceof HTMLElement) {
|
||||||
closeModal(closeBtn);
|
closeModal(closeBtn);
|
||||||
@ -1768,11 +1666,11 @@ function confirmSignature(documentId: number, processId: number, isCommonDocumen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
showAlert('Document signé avec succès!');
|
showAlert('Document signed successfully!');
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Erreur lors de la signature:', error);
|
console.error('Error signing document:', error);
|
||||||
showAlert(error instanceof Error ? error.message : 'Erreur lors de la signature');
|
showAlert(error instanceof Error ? error.message : 'Error signing document');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1784,24 +1682,83 @@ if (typeof window !== 'undefined') {
|
|||||||
(window as any).confirmSignature = confirmSignature;
|
(window as any).confirmSignature = confirmSignature;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ajouter cette fonction helper
|
// Add this helper function
|
||||||
function canUserAccessDocument(document: any, roleId: string, currentUserRole: string): boolean {
|
function canUserAccessDocument(document: any, roleId: string, currentUserRole: string): boolean {
|
||||||
// Modification de la logique d'accès
|
// Modify the access logic
|
||||||
if (document.visibility === 'public') {
|
if (document.visibility === 'public') {
|
||||||
return true; // Peut voir mais pas forcément signer
|
return true; // Can see but not necessarily sign
|
||||||
}
|
}
|
||||||
return roleId === currentUserRole;
|
return roleId === currentUserRole;
|
||||||
}
|
}
|
||||||
|
|
||||||
function canUserSignDocument(document: any, role: string, user: Member): boolean {
|
function canUserSignDocument(document: any, role: string, user: Member): boolean {
|
||||||
// Vérifier si l'utilisateur a le bon rôle pour ce processus
|
console.log('Checking signing rights for:', {
|
||||||
const userRole = user.processRoles?.find(pr => pr.role === role);
|
document,
|
||||||
if (!userRole) {
|
role,
|
||||||
|
user,
|
||||||
|
userRoles: user.processRoles
|
||||||
|
});
|
||||||
|
|
||||||
|
// Vérifier si l'utilisateur est dans la liste des signatures
|
||||||
|
const isSignatory = document.signatures?.some((sig: DocumentSignature) =>
|
||||||
|
sig.member && 'id' in sig.member && sig.member.id === user.id && !sig.signed
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!isSignatory) {
|
||||||
|
console.log('User is not in signatures list or has already signed');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vérifier si l'utilisateur est dans la liste des signataires
|
// Si l'utilisateur est dans la liste des signatures, il peut signer
|
||||||
return document.signatures?.some((sig: DocumentSignature) =>
|
return true;
|
||||||
sig.member && 'id' in sig.member && sig.member.id === user.id && !sig.signed
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Function to initialize the router
|
||||||
|
export function initSignature() {
|
||||||
|
// Reset the display
|
||||||
|
const groupList = document.getElementById('group-list');
|
||||||
|
if (groupList) {
|
||||||
|
groupList.innerHTML = ''; // Clear the existing list
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reload the messages from the store
|
||||||
|
messagesMock = messageStore.getMessages();
|
||||||
|
if (messagesMock.length === 0) {
|
||||||
|
messageStore.setMessages(initialMessagesMock);
|
||||||
|
messagesMock = messageStore.getMessages();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the interface
|
||||||
|
updateCurrentUserDisplay();
|
||||||
|
loadGroupList();
|
||||||
|
|
||||||
|
// If a member was selected, reload their chat
|
||||||
|
if (selectedMemberId) {
|
||||||
|
loadMemberChat(selectedMemberId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Event listeners
|
||||||
|
document.addEventListener('click', (event) => {
|
||||||
|
const userList = document.getElementById('userList');
|
||||||
|
const userSwitchBtn = document.getElementById('userSwitchBtn');
|
||||||
|
if (userSwitchBtn && userList && !userSwitchBtn.contains(event.target as Node) && !userList.contains(event.target as Node)) {
|
||||||
|
userList.classList.remove('show');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Reattach the event listeners for the messages
|
||||||
|
const sendBtn = document.getElementById('send-button');
|
||||||
|
if (sendBtn) sendBtn.onclick = sendMessage;
|
||||||
|
|
||||||
|
const messageInput = document.getElementById('message-input');
|
||||||
|
if (messageInput) {
|
||||||
|
messageInput.addEventListener('keydown', function (event) {
|
||||||
|
if (event.key === 'Enter') {
|
||||||
|
event.preventDefault();
|
||||||
|
sendMessage();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user