- Changes to the list views - now using tabulator with filtering and sorting, client-side pagination, ...
- Adaptation of all list views in the app
This commit is contained in:
@@ -96,9 +96,9 @@
|
||||
|
||||
/* Style for the table header */
|
||||
.ordered-list-editor .tabulator-header {
|
||||
background: linear-gradient(90deg, var(--bs-primary) 0%, var(--bs-secondary) 100%); /* Match JSE gradient */
|
||||
background: #e1e1e1;
|
||||
border-bottom: 2px solid var(--bs-secondary); /* Secondary color for border */
|
||||
color: #ffffff; /* White text for better contrast on gradient */
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* Style for the headers container */
|
||||
@@ -108,14 +108,14 @@
|
||||
|
||||
/* Style for the header cells */
|
||||
.ordered-list-editor .tabulator-col {
|
||||
background: transparent; /* Let the header gradient show through */
|
||||
background: transparent;
|
||||
padding: 8px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
display: table-cell !important; /* Force display as table cell */
|
||||
box-sizing: border-box !important; /* Include padding in width calculation */
|
||||
position: relative !important; /* Ensure proper positioning */
|
||||
color: #ffffff; /* White text for better contrast on gradient */
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* Override any inline styles that might hide column headers */
|
||||
@@ -135,7 +135,7 @@
|
||||
word-break: break-word; /* Break words to prevent horizontal overflow */
|
||||
font-weight: bold;
|
||||
font-size: 0.85rem; /* Kleinere font grootte, dezelfde als in de rijen */
|
||||
color: #ffffff; /* White text for better contrast on gradient */
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* Style for the table rows */
|
||||
@@ -385,7 +385,7 @@
|
||||
}
|
||||
/* Extra specifieke override stijlen voor tabulator paginator en footer */
|
||||
.tabulator .tabulator-footer .tabulator-paginator {
|
||||
background: transparent !important; /* Transparante achtergrond, want de footer heeft al gradient */
|
||||
background: transparent !important;
|
||||
border-top: none !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
@@ -407,14 +407,14 @@
|
||||
border-radius: 4px !important;
|
||||
border: 1px solid white !important;
|
||||
background-color: rgba(255, 255, 255, 0.2) !important;
|
||||
color: white !important;
|
||||
color: #67518c !important;
|
||||
font-size: 0.85rem !important;
|
||||
font-family: inherit !important;
|
||||
}
|
||||
|
||||
/* Styling voor de paginator container */
|
||||
.tabulator .tabulator-footer .tabulator-paginator label {
|
||||
color: white !important; /* Witte tekst voor betere leesbaarheid op donkere gradient */
|
||||
color: #67518c !important;
|
||||
font-size: 0.85rem !important;
|
||||
font-weight: normal !important;
|
||||
margin: 0 5px !important;
|
||||
@@ -465,7 +465,7 @@
|
||||
}
|
||||
/* Styling voor de tabulator paginator -------------------------------------------------------------- */
|
||||
.tabulator-paginator {
|
||||
background: linear-gradient(90deg, var(--bs-secondary) 0%, var(--bs-primary) 100%) !important; /* Omgekeerde gradient van de header */
|
||||
background: #e1e1e1;
|
||||
padding: 10px;
|
||||
border-bottom-left-radius: 0.375rem;
|
||||
border-bottom-right-radius: 0.375rem;
|
||||
@@ -485,13 +485,13 @@
|
||||
|
||||
.tabulator-paginator .tabulator-page:hover {
|
||||
background-color: var(--bs-secondary);
|
||||
color: white;
|
||||
color: #67518c;
|
||||
}
|
||||
|
||||
.tabulator-paginator .tabulator-page.active,
|
||||
.tabulator .tabulator-footer .tabulator-page.active {
|
||||
background-color: var(--bs-primary) !important;
|
||||
color: white !important;
|
||||
color: #67518c !important;
|
||||
border-color: var(--bs-primary) !important;
|
||||
}
|
||||
|
||||
@@ -515,7 +515,7 @@
|
||||
|
||||
.tabulator-footer,
|
||||
.tabulator .tabulator-footer {
|
||||
background: linear-gradient(90deg, var(--bs-secondary) 0%, var(--bs-primary) 100%) !important; /* Omgekeerde gradient van de header */
|
||||
background: #e1e1e1;
|
||||
border-top: 1px solid var(--bs-secondary) !important;
|
||||
border-bottom-left-radius: 0.375rem !important;
|
||||
border-bottom-right-radius: 0.375rem !important;
|
||||
@@ -548,7 +548,7 @@
|
||||
|
||||
/* Algemene tabulator header stijlen -------------------------------------------------------------- */
|
||||
.tabulator .tabulator-header {
|
||||
background: linear-gradient(90deg, var(--bs-primary) 0%, var(--bs-secondary) 100%);
|
||||
background: #e1e1e1;
|
||||
border-bottom: 2px solid var(--bs-secondary);
|
||||
color: #ffffff;
|
||||
}
|
||||
@@ -579,7 +579,7 @@
|
||||
}
|
||||
|
||||
.tabulator .tabulator-header .tabulator-col-title {
|
||||
color: #ffffff;
|
||||
color: #67518c;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
@@ -588,7 +588,7 @@
|
||||
}
|
||||
|
||||
.tabulator .tabulator-header .tabulator-col .tabulator-col-content .tabulator-col-title {
|
||||
color: #ffffff;
|
||||
color: #67518c;
|
||||
font-size: 0.85rem; /* Kleinere font grootte, dezelfde als in de rijen */
|
||||
}
|
||||
|
||||
@@ -607,7 +607,7 @@
|
||||
|
||||
/* Tabulator List View paginator stijlen */
|
||||
.tabulator-list-view .tabulator-footer {
|
||||
background: linear-gradient(90deg, var(--bs-primary) 0%, var(--bs-secondary) 100%); /* Match EveAI gradient */
|
||||
background: #e1e1e1;
|
||||
padding: 8px;
|
||||
border-bottom-left-radius: 0.375rem;
|
||||
border-bottom-right-radius: 0.375rem;
|
||||
@@ -635,20 +635,20 @@
|
||||
|
||||
/* Stijl voor de tabel header */
|
||||
.tabulator-list-view .tabulator-header {
|
||||
background: linear-gradient(90deg, var(--bs-primary) 0%, var(--bs-secondary) 100%); /* Match EveAI gradient */
|
||||
background: #e1e1e1;
|
||||
border-bottom: 2px solid var(--bs-secondary); /* Secundaire kleur voor rand */
|
||||
color: #ffffff; /* Witte tekst voor beter contrast op gradient */
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* Stijl voor de header cellen */
|
||||
.tabulator-list-view .tabulator-col {
|
||||
background: transparent; /* Laat de header gradient doorschijnen */
|
||||
background: transparent;
|
||||
padding: 8px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
box-sizing: border-box !important; /* Padding meenemen in breedte berekening */
|
||||
position: relative !important; /* Juiste positionering verzekeren */
|
||||
color: #ffffff; /* Witte tekst voor beter contrast op gradient */
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* Voorkom kleurverandering bij hover over kolomkoppen */
|
||||
@@ -662,7 +662,7 @@
|
||||
word-break: break-word; /* Breek woorden om horizontale overflow te voorkomen */
|
||||
font-weight: bold;
|
||||
font-size: 0.85rem; /* Kleinere font grootte, dezelfde als in de rijen */
|
||||
color: #ffffff; /* Witte tekst voor beter contrast op gradient */
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* Stijl voor de tabel rijen */
|
||||
|
||||
183
eveai_app/static/assets/js/eveai-list-view.js
Normal file
183
eveai_app/static/assets/js/eveai-list-view.js
Normal file
@@ -0,0 +1,183 @@
|
||||
/**
|
||||
* EveAI List View Component
|
||||
* JavaScript functionaliteit voor het beheren van lijst-weergaven
|
||||
*/
|
||||
|
||||
// Namespace aanmaken als deze nog niet bestaat
|
||||
if (typeof window.EveAI === 'undefined') {
|
||||
window.EveAI = {};
|
||||
}
|
||||
|
||||
// List View namespace
|
||||
window.EveAI.ListView = {
|
||||
// Opslag voor lijst-view instanties
|
||||
instances: {},
|
||||
|
||||
/**
|
||||
* Initialiseer een Tabulator lijst-view
|
||||
* @param {string} elementId - ID van het HTML element
|
||||
* @param {object} config - Configuratie object voor Tabulator
|
||||
* @returns {Tabulator} - Tabulator instantie
|
||||
*/
|
||||
initialize: function(elementId, config) {
|
||||
// Combineer standaard configuratie met aangepaste configuratie
|
||||
const defaultConfig = {
|
||||
height: 600,
|
||||
layout: "fitColumns",
|
||||
selectable: true,
|
||||
movableColumns: true,
|
||||
pagination: "local",
|
||||
paginationSize: 15,
|
||||
paginationSizeSelector: [10, 15, 20, 50, 100],
|
||||
};
|
||||
|
||||
const tableConfig = {...defaultConfig, ...config};
|
||||
|
||||
// Voeg rij selectie event toe
|
||||
tableConfig.rowSelectionChanged = (data, rows) => {
|
||||
console.log("Rij selectie gewijzigd:", rows.length, "rijen geselecteerd");
|
||||
|
||||
// Update de geselecteerde rij in onze instance
|
||||
if (this.instances[elementId]) {
|
||||
this.instances[elementId].selectedRow = rows.length > 0 ? rows[0].getData() : null;
|
||||
this.updateActionButtons(elementId);
|
||||
}
|
||||
};
|
||||
|
||||
// Initialiseer de Tabulator
|
||||
try {
|
||||
const table = new Tabulator(`#${elementId}`, tableConfig);
|
||||
|
||||
// Bewaar de instance
|
||||
this.instances[elementId] = {
|
||||
table: table,
|
||||
config: config || {},
|
||||
selectedRow: null
|
||||
};
|
||||
|
||||
// Bij initialisatie, update de knoppen (standaard inactief voor requiresSelection=true)
|
||||
setTimeout(() => {
|
||||
this.updateActionButtons(elementId);
|
||||
}, 0);
|
||||
|
||||
return table;
|
||||
} catch (error) {
|
||||
console.error(`Fout bij het initialiseren van Tabulator voor ${elementId}:`, error);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Afhandelen van actieknoppen
|
||||
* @param {string} action - Actie identifier
|
||||
* @param {boolean} requiresSelection - Of de actie een selectie vereist
|
||||
* @param {string} tableId - ID van de tabel
|
||||
* @returns {boolean} - Succes indicator
|
||||
*/
|
||||
/**
|
||||
* Update actieknoppen op basis van geselecteerde rij
|
||||
* @param {string} tableId - ID van de tabel
|
||||
*/
|
||||
updateActionButtons: function(tableId) {
|
||||
const instance = this.instances[tableId];
|
||||
if (!instance) return;
|
||||
|
||||
const container = document.getElementById(tableId);
|
||||
if (!container) return;
|
||||
|
||||
const buttons = container.parentElement.querySelectorAll('button[onclick*="handleListViewAction"]');
|
||||
|
||||
buttons.forEach(button => {
|
||||
// Parse de onclick attribuut om de actiewaarde te krijgen
|
||||
const onclickAttr = button.getAttribute('onclick');
|
||||
const match = onclickAttr.match(/handleListViewAction\('([^']+)'/);
|
||||
if (match) {
|
||||
const actionValue = match[1];
|
||||
// Vind de actie in de configuratie
|
||||
const action = instance.config.actions.find(a => a.value === actionValue);
|
||||
if (action && action.requiresSelection === true) {
|
||||
// Schakel de knop in/uit op basis van selectie
|
||||
button.disabled = !instance.selectedRow;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Update de verborgen input met geselecteerde rij data
|
||||
this._updateSelectedRowInput(tableId);
|
||||
},
|
||||
|
||||
/**
|
||||
* Update de verborgen input met geselecteerde rij gegevens
|
||||
* @param {string} tableId - ID van de tabel
|
||||
* @private
|
||||
*/
|
||||
_updateSelectedRowInput: function(tableId) {
|
||||
const instance = this.instances[tableId];
|
||||
const hiddenInput = document.getElementById(`${tableId}-selected-row`);
|
||||
|
||||
if (hiddenInput && instance && instance.selectedRow) {
|
||||
// Bewaar de geselecteerde rij-ID
|
||||
hiddenInput.value = JSON.stringify({value: instance.selectedRow.id});
|
||||
} else if (hiddenInput) {
|
||||
hiddenInput.value = '';
|
||||
}
|
||||
},
|
||||
|
||||
handleAction: function(action, requiresSelection, tableId) {
|
||||
const selectedRowInput = document.getElementById(`${tableId}-selected-row`);
|
||||
const actionInput = document.getElementById(`${tableId}-action`);
|
||||
const table = Tabulator.findTable(`#${tableId}`)[0];
|
||||
|
||||
if (!table) {
|
||||
console.error(`Tabulator tabel met ID ${tableId} niet gevonden`);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Als de actie een selectie vereist, controleer of er een rij is geselecteerd
|
||||
if (requiresSelection) {
|
||||
const selectedRows = table.getSelectedRows();
|
||||
if (selectedRows.length === 0) {
|
||||
alert('Selecteer a.u.b. eerst een item uit de lijst.');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Haal de data van de geselecteerde rij op en sla deze op
|
||||
const rowData = selectedRows[0].getData();
|
||||
selectedRowInput.value = JSON.stringify({ value: rowData.id });
|
||||
|
||||
// Update de instance als deze bestaat
|
||||
if (this.instances[tableId]) {
|
||||
this.instances[tableId].selectedRow = rowData;
|
||||
}
|
||||
}
|
||||
|
||||
// Stel de actie in en verstuur het formulier
|
||||
actionInput.value = action;
|
||||
|
||||
// Zoek het juiste formulier en verstuur het
|
||||
const form = document.getElementById(`${tableId}-form`) ||
|
||||
table.element.closest('form');
|
||||
|
||||
if (form) {
|
||||
form.submit();
|
||||
return true;
|
||||
} else {
|
||||
console.error(`Geen formulier gevonden voor tabel ${tableId}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Functie om beschikbaar te maken in templates
|
||||
function handleListViewAction(action, requiresSelection) {
|
||||
// Vind het tableId op basis van de button die is aangeklikt
|
||||
const target = event?.target || event?.srcElement;
|
||||
|
||||
// Vind het formulier en tableId op basis daarvan
|
||||
const form = target ? target.closest('form') : null;
|
||||
const tableId = form ? form.id.replace('-form', '') : 'unknown_table';
|
||||
|
||||
return window.EveAI.ListView.handleAction(action, requiresSelection, tableId);
|
||||
}
|
||||
|
||||
console.log('EveAI List View component geladen');
|
||||
83
eveai_app/static/assets/js/eveai-tabulator-setup.js
Normal file
83
eveai_app/static/assets/js/eveai-tabulator-setup.js
Normal file
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* EveAI Tabulator Setup
|
||||
* Standaard Tabulator configuratie voor consistente tabelweergaven
|
||||
*/
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Controleer of Tabulator is geladen
|
||||
if (typeof Tabulator !== 'function') {
|
||||
console.warn('Tabulator is niet geladen - overslaan van initialisatie');
|
||||
return;
|
||||
}
|
||||
|
||||
// Zorg ervoor dat de modules correct zijn gedefinieerd
|
||||
if (!Tabulator.modules) {
|
||||
Tabulator.modules = {};
|
||||
}
|
||||
|
||||
if (!Tabulator.modules.format) {
|
||||
Tabulator.modules.format = { formatters: {} };
|
||||
} else if (!Tabulator.modules.format.formatters) {
|
||||
Tabulator.modules.format.formatters = {};
|
||||
}
|
||||
|
||||
// Registreer algemene Tabulator opties en formatters
|
||||
// Gebruik rechtstreekse toewijzing i.p.v. extendModule indien deze functie niet beschikbaar is
|
||||
if (typeof Tabulator.extendModule === 'function') {
|
||||
try {
|
||||
Tabulator.extendModule("format", "formatters", {
|
||||
// Aangepaste formatter voor boolean waarden met mooie iconen
|
||||
"boolean": function(cell, formatterParams){
|
||||
const value = cell.getValue();
|
||||
if (value === true || value === 'true' || value === 1 || value === '1') {
|
||||
return '<i class="fas fa-check text-success"></i>';
|
||||
} else if (value === false || value === 'false' || value === 0 || value === '0') {
|
||||
return '<i class="fas fa-times text-danger"></i>';
|
||||
}
|
||||
return ''; // Geef lege string terug voor null/undefined waarden
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.warn('Fout bij extendModule:', e);
|
||||
// Fallback: rechtstreeks formatters toevoegen
|
||||
Tabulator.modules.format.formatters.boolean = function(cell, formatterParams){
|
||||
const value = cell.getValue();
|
||||
if (value === true || value === 'true' || value === 1 || value === '1') {
|
||||
return '<i class="fas fa-check text-success"></i>';
|
||||
} else if (value === false || value === 'false' || value === 0 || value === '0') {
|
||||
return '<i class="fas fa-times text-danger"></i>';
|
||||
}
|
||||
return '';
|
||||
};
|
||||
}
|
||||
} else {
|
||||
// Directe toewijzing als extendModule niet beschikbaar is
|
||||
Tabulator.modules.format.formatters.boolean = function(cell, formatterParams){
|
||||
const value = cell.getValue();
|
||||
if (value === true || value === 'true' || value === 1 || value === '1') {
|
||||
return '<i class="fas fa-check text-success"></i>';
|
||||
} else if (value === false || value === 'false' || value === 0 || value === '0') {
|
||||
return '<i class="fas fa-times text-danger"></i>';
|
||||
}
|
||||
return '';
|
||||
};
|
||||
}
|
||||
|
||||
// Definieer standaard tabelconfiguratie
|
||||
Tabulator.defaultOptions = {
|
||||
...Tabulator.defaultOptions,
|
||||
layout: "fitColumns",
|
||||
responsiveLayout: false,
|
||||
pagination: "local",
|
||||
paginationSize: 25,
|
||||
paginationSizeSelector: [10, 25, 50, 100],
|
||||
movableColumns: true,
|
||||
tooltips: false,
|
||||
placeholder: "No Data Available",
|
||||
// Verbeterde virtuele DOM-instellingen voor betere prestaties
|
||||
renderVerticalBuffer: 20,
|
||||
virtualDomBuffer: 80
|
||||
};
|
||||
|
||||
console.log('EveAI Tabulator Setup successfully loaded');
|
||||
});
|
||||
Reference in New Issue
Block a user