Easy_solution/assets/controllers/organization_controller.js

156 lines
5.6 KiB
JavaScript

import {Controller} from '@hotwired/stimulus'
// Important: include a build with Ajax + pagination (TabulatorFull is simplest)
import {TabulatorFull as Tabulator} from 'tabulator-tables';
import {eyeIconLink, TABULATOR_FR_LANG} from "../js/global.js";
export default class extends Controller {
static values = {aws: String,
id: String,
activities: Boolean,
table: Boolean,
sadmin: Boolean,
user: Number
};
static targets = ["activityList", "emptyMessage"]
connect() {
if(this.activitiesValue){
this.loadActivities();
setInterval(() => {
this.loadActivities();
}, 60000); // Refresh every 60 seconds
}
if (this.tableValue && this.sadminValue) {
this.table();
}
}
table(){
const table = new Tabulator("#tabulator-org", {
// Register locales here
langs: TABULATOR_FR_LANG,
placeholder: "Aucun résultat trouvé pour cette recherche",
locale: "fr", //'en' for English, 'fr' for French (en is default, no need to include it)
ajaxURL: `/organization/data/${this.userValue}`,
ajaxConfig: "GET",
pagination: true,
paginationMode: "remote",
paginationSize: 10,
//paginationSizeSelector: [5, 10, 20, 50], // Désactivé pour l'instant car jpp faire de jolie style
ajaxResponse: (url, params, response) => response,
paginationDataSent: { page: "page", size: "size" },
paginationDataReceived: { last_page: "last_page" },
filterMode: "remote",
ajaxURLGenerator: function(url, config, params) {
let queryParams = new URLSearchParams();
queryParams.append('page', params.page || 1);
queryParams.append('size', params.size || 10);
// Add filters
if (params.filter) {
params.filter.forEach(filter => {
queryParams.append(`filter[${filter.field}]`, filter.value);
});
}
return `${url}?${queryParams.toString()}`;
},
ajaxSorting: true,
ajaxFiltering: true,
rowHeight: 60,
layout: "fitColumns", // activate French
columns: [
{
title: "Logo",
field: "logoUrl",
formatter: "image",
formatterParams: {
height: "50px",
width: "50px",
urlPrefix: "",
urlSuffix: "",
},
width: 100,
},
// TODO: regarder quel style est mieux entre les "hozAlign"
// TODO: regarder quel style est mieux avec/sans headerFilter
{title: "Nom", field: "name", headerFilter: "input", widthGrow: 2, vertAlign: "middle", headerHozAlign: "left"},
{title: "Email", field: "email", headerFilter: "input", widthGrow: 2, vertAlign: "middle", hozAlign: "center"},
{
title: "Actions",
field: "showUrl",
hozAlign: "center",
width: 100,
vertAlign: "middle",
headerSort: false,
formatter: (cell) => {
const url = cell.getValue();
if (url) {
return eyeIconLink(url);
}
return '';
}
}],
});
}
async loadActivities() {
try {
// 1. Fetch the data using the ID from values
const response = await fetch(`/actions/organization/${this.idValue}/activities-ajax`);
if (!response.ok) {
throw new Error('Network response was not ok');
}
const activities = await response.json();
// 2. Render
this.renderActivities(activities);
} catch (error) {
console.error('Error fetching activities:', error);
this.activityListTarget.innerHTML = `<div class="text-danger">Erreur lors du chargement.</div>`;
}
}
renderActivities(activities) {
// Clear the loading spinner
this.activityListTarget.innerHTML = '';
if (activities.length === 0) {
// Show empty message
this.activityListTarget.innerHTML = this.emptyMessageTarget.innerHTML;
return;
}
// Loop through JSON and build HTML
const html = activities.map(activity => {
return `
<div class="card shadow-sm mb-3 border-0 bg-white rounded-end"
style="border-left: 6px solid ${activity.color} !important;">
<div class="card-header bg-transparent border-0 pb-0 pt-3">
<h6 class="text-muted text-uppercase fw-bold mb-0" style="font-size: 0.85rem;">
${activity.date}
</h6>
</div>
<div class="card-body pt-2 pb-4">
<div class="card-text fs-5 lh-sm">
<span class="fw-bold text-dark">${activity.userName}</span>
<div class="text-secondary mt-1">${activity.actionType}</div>
</div>
</div>
</div>
`;
}).join('');
this.activityListTarget.innerHTML = html;
}
}