From a6fdb59521c724d23625be418b2fd3986c03b878 Mon Sep 17 00:00:00 2001 From: Charles Date: Wed, 5 Nov 2025 15:02:21 +0100 Subject: [PATCH] refactor --- assets/app.js | 24 +-- assets/controllers/organization_controller.js | 15 +- assets/controllers/user_controller.js | 141 +++++++++--------- assets/js/global.js | 51 +++++++ 4 files changed, 128 insertions(+), 103 deletions(-) create mode 100644 assets/js/global.js diff --git a/assets/app.js b/assets/app.js index 2fd6400..0ca5038 100644 --- a/assets/app.js +++ b/assets/app.js @@ -23,26 +23,4 @@ import './js/cookies.js'; import 'choices.js'; import 'quill' import 'tabulator-tables' - -export const TABULATOR_FR_LANG = { - fr: { - ajax: {loading: "Chargement...", error: "Erreur"}, - pagination: { - page_size: "Taille de page", - page_title: "Afficher la page", - first: "Premier", - first_title: "Première page", - last: "Dernier", - last_title: "Dernière page", - prev: "Précédent", - prev_title: "Page précédente", - next: "Suivant", - next_title: "Page suivante", - all: "Tout", - counter: {showing: "Affiche", of: "de", rows: "lignes", pages: "pages"}, - }, - headerFilters: {default: "Filtrer la colonne...", columns: {}}, - data: {loading: "Chargement des données...", error: "Erreur de chargement des données"}, - groups: {item: "élément", items: "éléments"}, - }, -}; \ No newline at end of file +import './js/global.js' \ No newline at end of file diff --git a/assets/controllers/organization_controller.js b/assets/controllers/organization_controller.js index 50d35ad..127d7c7 100644 --- a/assets/controllers/organization_controller.js +++ b/assets/controllers/organization_controller.js @@ -1,7 +1,7 @@ import {Controller} from '@hotwired/stimulus' // Important: include a build with Ajax + pagination (TabulatorFull is simplest) import {TabulatorFull as Tabulator} from 'tabulator-tables'; -import {TABULATOR_FR_LANG} from "../app.js"; +import {eyeIconLink, TABULATOR_FR_LANG} from "../js/global.js"; export default class extends Controller { static values = {aws: String}; @@ -40,7 +40,7 @@ export default class extends Controller { formatterParams: { height: "50px", width: "50px", - urlPrefix: this.awsValue, + urlPrefix: "", urlSuffix: "", }, width: 100, @@ -59,16 +59,7 @@ export default class extends Controller { formatter: (cell) => { const url = cell.getValue(); if (url) { - return ` - - - - - `; + return eyeIconLink(url); } return ''; } diff --git a/assets/controllers/user_controller.js b/assets/controllers/user_controller.js index 9a8a7bc..801a576 100644 --- a/assets/controllers/user_controller.js +++ b/assets/controllers/user_controller.js @@ -1,8 +1,7 @@ import {Controller} from '@hotwired/stimulus'; import Choices from 'choices.js'; import {TabulatorFull as Tabulator} from 'tabulator-tables'; -import {TABULATOR_FR_LANG} from "../app.js"; - +import {activateUserIcon, deactivateUserIcon, eyeIconLink, sendEmailIcon, TABULATOR_FR_LANG} from "../js/global.js"; export default class extends Controller { @@ -10,7 +9,6 @@ export default class extends Controller { rolesArray: Array, selectedRoleIds: Array, id: Number, - aws: String, list: Boolean, listOrganization: Boolean, new: Boolean, @@ -28,7 +26,7 @@ export default class extends Controller { this.table(); } if (this.newValue) { - this.tableSmall(); + this.tableNew(); } if (this.adminValue) { this.tableSmallAdmin(); @@ -177,27 +175,17 @@ export default class extends Controller { const actionColorClass = isActive ? 'color-secondary' : 'color-primary'; // SVGs - const deactivateSvg = ` - - - `; - - const activateSvg = ` - - `; + const deactivateSvg = deactivateUserIcon(); + const activateSvg = activateUserIcon(); const actionSvg = isActive ? deactivateSvg : activateSvg; return `
- - - - + ${eyeIconLink(url)} ${actionSvg} @@ -303,12 +291,11 @@ export default class extends Controller { onSelectChange(row, newValue) { const data = row.getData(); - console.log("Change select" + data); }; - tableSmall() { + tableNew() { const columns = [ { title: "Profil", @@ -381,16 +368,7 @@ export default class extends Controller { formatter: (cell) => { const url = cell.getValue(); if (url) { - return ` - - - - - `; + return eyeIconLink(url); } return ''; } @@ -495,16 +473,7 @@ export default class extends Controller { formatter: (cell) => { const url = cell.getValue(); if (url) { - return ` - - - - - `; + eyeIconLink(url); } return ''; } @@ -628,12 +597,13 @@ export default class extends Controller { title: "Statut", field: "statut", vertAlign: "middle", formatter: (cell) => { const statut = cell.getValue(); - console.log("Statut value:", statut); if (statut === "INVITED") { return `Invité` } else if (statut === "ACTIVE") { return `Actif` - }else{ + }else if( statut === "EXPIRED"){ + return `Expiré` + } else{ return `Inactif` } } @@ -652,48 +622,85 @@ export default class extends Controller { const statut = rowData.statut; const orgId = this.orgIdValue; - // Decide which action (deactivate vs activate) - const isActive = Boolean(statut); + // Check if user is expired + if (statut === "EXPIRED") { + return ` +
+ ${eyeIconLink(url)} + + ${sendEmailIcon(userId, orgId)} +
+ `; + } + + // Decide which action (deactivate vs activate) for non-expired users + const isActive = (statut === "ACTIVE"); const actionClass = isActive ? 'deactivate-user' : 'activate-user'; const actionTitle = isActive ? 'Désactiver' : 'Réactiver'; const actionColorClass = isActive ? 'color-secondary' : 'color-primary'; // SVGs - const deactivateSvg = ` - - - `; + const deactivateSvg = deactivateUserIcon(); - const activateSvg = ` - - `; + const activateSvg = activateUserIcon(); const actionSvg = isActive ? deactivateSvg : activateSvg; return ` - - `; + + ${actionSvg} + +
+ `; }, cellClick: function (e, cell) { const target = e.target.closest('a'); if (!target) return; + // Handle resend invitation for expired users + if (target.classList.contains('resend-invitation')) { + e.preventDefault(); + const userId = target.getAttribute('data-id'); + if (confirm('Voulez-vous renvoyer l\'invitation à cet utilisateur ?')) { + const formData = new FormData(); + formData.append('organizationId', target.getAttribute('data-org-id')); + + fetch(`/user/organization/resend-invitation/${userId}`, { + method: 'POST', + body: formData, + headers: {'X-Requested-With': 'XMLHttpRequest'} + }) + .then(async (response) => { + if (response.ok) { + const data = cell.getRow().getData(); + data.statut = "INVITED"; + cell.getRow().reformat(); + alert('Invitation renvoyée avec succès'); + } else { + const text = await response.text(); + alert('Erreur lors de l\'envoi : ' + text); + } + }) + .catch(() => alert('Erreur lors de l\'envoi')); + } + } + // Deactivate if (target.classList.contains('deactivate-user')) { e.preventDefault(); @@ -709,9 +716,8 @@ export default class extends Controller { }) .then(async (response) => { if (response.ok) { - // Option 1: update row status and re-render to switch icon const data = cell.getRow().getData(); - data.statut = false; + data.statut = "INACTIVE"; cell.getRow().reformat(); } else { const text = await response.text(); @@ -737,9 +743,8 @@ export default class extends Controller { }) .then(async (response) => { if (response.ok) { - // Switch status back to active and re-render row const data = cell.getRow().getData(); - data.statut = true; + data.statut = "ACTIVE"; cell.getRow().reformat(); } else { const text = await response.text(); diff --git a/assets/js/global.js b/assets/js/global.js new file mode 100644 index 0000000..62f5b75 --- /dev/null +++ b/assets/js/global.js @@ -0,0 +1,51 @@ +export const TABULATOR_FR_LANG = { + fr: { + ajax: {loading: "Chargement...", error: "Erreur"}, + pagination: { + page_size: "Taille de page", + page_title: "Afficher la page", + first: "Premier", + first_title: "Première page", + last: "Dernier", + last_title: "Dernière page", + prev: "Précédent", + prev_title: "Page précédente", + next: "Suivant", + next_title: "Page suivante", + all: "Tout", + counter: {showing: "Affiche", of: "de", rows: "lignes", pages: "pages"}, + }, + headerFilters: {default: "Filtrer la colonne...", columns: {}}, + data: {loading: "Chargement des données...", error: "Erreur de chargement des données"}, + groups: {item: "élément", items: "éléments"}, + }, +}; + +export function eyeIconLink(url) { + return ` + + + `; +} + +export function deactivateUserIcon() { + return ` + + ` +} + +export function activateUserIcon() { + return ` + + ` +} + +export function sendEmailIcon(userId, orgId) { + return ` + + ` +} \ No newline at end of file