diff --git a/config/specialists/traicie/TRAICIE_SELECTION_SPECIALIST/1.0.0.yaml b/config/specialists/traicie/TRAICIE_SELECTION_SPECIALIST/1.0.0.yaml
index 25b0079..6c4d323 100644
--- a/config/specialists/traicie/TRAICIE_SELECTION_SPECIALIST/1.0.0.yaml
+++ b/config/specialists/traicie/TRAICIE_SELECTION_SPECIALIST/1.0.0.yaml
@@ -41,17 +41,17 @@ configuration:
required: false
competency_details:
title:
- name: "title"
+ name: "Title"
description: "Competency Title"
type: "str"
required: true
description:
- name: "description"
+ name: "Description"
description: "Description (in context of the role) of the competency"
type: "text"
required: true
is_knockout:
- name: "Is Knockout"
+ name: "KO"
description: "Defines if the competency is a knock-out criterium"
type: "boolean"
required: true
diff --git a/eveai_app/templates/eveai_ordered_list_editor.html b/eveai_app/templates/eveai_ordered_list_editor.html
index d79f937..f8cb989 100644
--- a/eveai_app/templates/eveai_ordered_list_editor.html
+++ b/eveai_app/templates/eveai_ordered_list_editor.html
@@ -33,21 +33,47 @@ window.EveAI.OrderedListEditors = {
// Create column definitions from list type
const columns = this._createColumnsFromListType(listTypeConfig);
+ // Debug log for data and columns
+ console.log('Data for Tabulator:', data);
+ console.log('Columns for Tabulator:', columns);
+
+ // Debug log for column titles
+ console.log('Column titles:', columns.map(col => col.title || ''));
+
// Initialize Tabulator
try {
console.log('Creating Tabulator for', containerId);
const table = new Tabulator(container, {
data: data || [],
columns: columns,
- layout: "fitColumns",
+ layout: "fitColumns", // Changed to fitColumns to ensure columns display horizontally
movableRows: true,
- height: "400px",
+ {#rowHeader: {headerSort:false, resizable: false, minWidth:30, width:30, rowHandle:true, formatter:"handle"},#}
+ maxHeight: "50%", // Auto height to display all rows
+ placeholder: "No Data Available",
+ autoResize: false,
+ resizableColumnFit: true,
+ responsiveLayout: false,
+ tooltips: true, // Enable tooltips
+ tooltipsHeader: true,
+ selectable: false, // Disable row selection to prevent jumping
+ selectableRangeMode: "click", // Only select on click, not on drag
+ selectableRollingSelection: false, // Disable rolling selection
+ scrollToRowIfVisible: false, // Don't scroll to row even if it's already visible
+ scrollToRowPosition: "nearest",
...options
});
console.log('Tabulator created for', containerId);
container.classList.add('tabulator-initialized');
+ // Debug: Log table structure
+ console.log('Table structure:', {
+ tableElement: container,
+ tableData: table.getData(),
+ tableColumns: table.getColumnDefinitions()
+ });
+
// Add row button
const addRowBtn = document.createElement('button');
addRowBtn.className = 'btn btn-sm btn-primary mt-2';
@@ -56,21 +82,65 @@ window.EveAI.OrderedListEditors = {
const newRow = {};
// Create empty row with default values
Object.entries(listTypeConfig).forEach(([key, field]) => {
- newRow[key] = field.default || '';
+ if (field.type === 'boolean') {
+ newRow[key] = field.default === true;
+ } else {
+ newRow[key] = field.default !== undefined ? field.default : '';
+ }
});
table.addRow(newRow);
this._updateTextarea(containerId, table);
});
container.parentNode.insertBefore(addRowBtn, container.nextSibling);
+ // Add explode button for fullscreen mode
+ const explodeBtn = document.createElement('button');
+ explodeBtn.className = 'btn btn-sm btn-secondary mt-2 ms-2';
+ explodeBtn.innerHTML = 'fullscreen Expand';
+ explodeBtn.addEventListener('click', () => {
+ container.classList.toggle('fullscreen-mode');
+
+ // Update button text based on current state
+ if (container.classList.contains('fullscreen-mode')) {
+ explodeBtn.innerHTML = 'fullscreen_exit Collapse';
+ } else {
+ explodeBtn.innerHTML = 'fullscreen Expand';
+ }
+
+ // Redraw table to adjust to new size
+ table.redraw(true);
+ });
+ container.parentNode.insertBefore(explodeBtn, addRowBtn.nextSibling);
+
// Store instance
this.instances[containerId] = {
table: table,
textarea: document.getElementById(containerId.replace('-editor', ''))
};
- // Update textarea on data change
+ // Prevent scrolling when clicking on cells
+ container.addEventListener('click', function(e) {
+ // Prevent the default behavior which might cause scrolling
+ if (e.target.closest('.tabulator-cell')) {
+ e.preventDefault();
+ }
+ }, { passive: false });
+
+ // Update textarea on various events that change data
table.on("dataChanged", () => {
+ console.log("dataChanged event triggered");
+ this._updateTextarea(containerId, table);
+ });
+
+ // Listen for row movement
+ table.on("rowMoved", () => {
+ console.log("rowMoved event triggered");
+ this._updateTextarea(containerId, table);
+ });
+
+ // Listen for cell edits
+ table.on("cellEdited", () => {
+ console.log("cellEdited event triggered");
this._updateTextarea(containerId, table);
});
@@ -87,65 +157,147 @@ window.EveAI.OrderedListEditors = {
_updateTextarea: function(containerId, table) {
const instance = this.instances[containerId];
if (instance && instance.textarea) {
- instance.textarea.value = JSON.stringify(table.getData());
+ const data = table.getData();
+ console.log('Updating textarea with data:', data);
+ instance.textarea.value = JSON.stringify(data);
+ console.log('Textarea value updated:', instance.textarea.value);
+
+ // Trigger change event on textarea to ensure form validation recognizes the change
+ const event = new Event('change', { bubbles: true });
+ instance.textarea.dispatchEvent(event);
+
+ // Also trigger input event for any listeners that might be using that
+ const inputEvent = new Event('input', { bubbles: true });
+ instance.textarea.dispatchEvent(inputEvent);
+ } else {
+ console.error('Cannot update textarea: instance or textarea not found for', containerId);
}
},
_getListTypeConfig: function(listType) {
- // This would need to be implemented to fetch the list type configuration
- // Could be from a global variable set in the template or via an API call
- return window.listTypeConfigs && window.listTypeConfigs[listType];
+ // Try to get the list type configuration from window.listTypeConfigs
+ if (window.listTypeConfigs && window.listTypeConfigs[listType]) {
+ return window.listTypeConfigs[listType];
+ }
+
+ // If not found, log a warning and return a default configuration
+ console.warn(`List type configuration for ${listType} not found in window.listTypeConfigs. Using a default configuration.`);
+ return {
+ title: {
+ name: "Title",
+ description: "Title",
+ type: "str",
+ required: true
+ },
+ description: {
+ name: "Description",
+ description: "Description",
+ type: "text",
+ required: true
+ }
+ };
+ },
+
+ // Custom formatter for text columns to truncate text in normal mode
+ _truncateFormatter: function(cell, formatterParams, onRendered) {
+ const value = cell.getValue();
+ const maxLength = formatterParams.maxLength || 100;
+
+ if (value && value.length > maxLength) {
+ // Create a truncated version with "..." and show more indicator
+ const truncated = value.substring(0, maxLength) + "...";
+
+ // Return HTML with truncated text and a "show more" button
+ return `
+
${truncated}
+
+ more_horiz
+
+
`;
+ }
+
+ return value;
},
_createColumnsFromListType: function(listTypeConfig) {
const columns = [];
- // Add drag handle column for row reordering
- columns.push({
- formatter: "handle",
- headerSort: false,
- frozen: true,
- width: 30,
- minWidth: 30
- });
-
// Add columns for each field in the list type
Object.entries(listTypeConfig).forEach(([key, field]) => {
const column = {
title: field.name || key,
field: key,
- tooltip: field.description
+ headerTooltip: field.description,
+ headerSort: false,
+ visible: true,
+ resizable: "header",
};
+ console.log("Column ", field.name, " type: ", field.type)
+ // Set width based on field type
+ if (field.type === 'boolean') {
+ column.minWidth = 50;
+ column.maxWidth = 80; // Limit maximum width
+ column.widthGrow = 0; // Don't allow boolean columns to grow
+ } else if (field.type === 'text') {
+ column.width = 400; // Much larger width for text columns (especially description)
+ column.minWidth = 300; // Ensure text columns have adequate minimum width
+ column.widthGrow = 2; // Allow text columns to grow significantly more
+ } else {
+ column.width = 150; // Default width for other columns
+ column.minWidth = 100;
+ column.widthGrow = 1; // Allow some growth
+ }
+
+ // Ensure consistent width calculation
+ column.widthShrink = 0; // Don't allow shrinking below minWidth
// Set editor based on field type
if (field.type === 'boolean') {
column.formatter = 'tickCross';
column.editor = 'tickCross';
column.hozAlign = 'center';
+ column.headerHozAlign = 'center';
+ column.formatterParams = {
+ allowEmpty: true,
+ allowTruthy: true,
+ tickElement: "check_circle",
+ crossElement: "cancel"
+ };
} else if (field.type === 'enum' && field.allowed_values) {
column.editor = 'select';
column.editorParams = {
values: field.allowed_values
};
+ column.hozAlign = 'left';
+ column.headerHozAlign = 'left';
+ } else if (field.type === 'text') {
+ column.editor = 'textarea';
+ column.formatter = this._truncateFormatter; // Use custom formatter to truncate text
+ column.variableHeight = true;
+ // Configure formatter parameters
+ column.formatterParams = {
+ maxLength: 50,
+ autoResize: true
+ };
+ // Prevent scrolling when editing text cells
+ column.editorParams = {
+ elementAttributes: {
+ preventScroll: true
+ }
+ };
+ column.hozAlign = 'left';
+ column.headerHozAlign = 'left';
} else {
column.editor = 'input';
+ column.hozAlign = 'left';
+ column.headerHozAlign = 'left';
}
columns.push(column);
});
- // Add delete button column
- columns.push({
- formatter: function(cell, formatterParams, onRendered) {
- return "";
- },
- width: 40,
- hozAlign: "center",
- headerSort: false,
- cellClick: function(e, cell) {
- cell.getRow().delete();
- }
- });
+ // We don't add a delete button column as per requirements
+ // to prevent users from deleting rows
return columns;
},
@@ -176,8 +328,17 @@ document.addEventListener('DOMContentLoaded', function() {
// Initialize ordered list editors
document.querySelectorAll('.ordered-list-field').forEach(function(textarea) {
const containerId = textarea.id + '-editor';
- const container = document.getElementById(containerId);
- if (!container) return;
+ console.log('Initializing ordered list editor for', containerId);
+
+ // Create container if it doesn't exist
+ let container = document.getElementById(containerId);
+ if (!container) {
+ container = document.createElement('div');
+ container.id = containerId;
+ container.className = 'ordered-list-editor';
+ textarea.parentNode.insertBefore(container, textarea.nextSibling);
+ textarea.classList.add('d-none'); // Hide the textarea
+ }
try {
const data = textarea.value ? JSON.parse(textarea.value) : [];
@@ -185,7 +346,7 @@ document.addEventListener('DOMContentLoaded', function() {
// Check if we have the list type configuration
if (listType && !window.listTypeConfigs[listType]) {
- console.warn(`List type configuration for ${listType} not found. The editor may not work correctly.`);
+ console.warn(`List type configuration for ${listType} not found. Using default configuration.`);
}
window.EveAI.OrderedListEditors.initialize(containerId, data, listType);
@@ -203,19 +364,57 @@ document.addEventListener('DOMContentLoaded', function() {
/* Tabulator styling */
.ordered-list-editor {
margin-bottom: 1rem;
+ min-height: 200px; /* Minimum height, will expand as needed */
}
/* Make sure the Tabulator container has a proper height */
.ordered-list-editor .tabulator {
- height: 400px;
+ height: auto; /* Auto height to display all rows */
+ min-height: 200px; /* Minimum height */
width: 100%;
border: 1px solid #dee2e6;
border-radius: 0.25rem;
+ margin-bottom: 0.5rem;
+}
+
+/* Ensure the table holder has a scrollbar */
+.ordered-list-editor .tabulator-tableholder {
+ /* overflow-y: auto !important; - Removed to allow Tabulator to handle overflow */
+ /* max-height: calc(100% - 42px) !important; - Removed to allow Tabulator to handle height */
+ /* Consider using non-!important values if specific scrolling behavior is needed */
+ overflow-y: auto;
+ max-height: calc(100% - 42px);
+}
+
+/* Style for the table element */
+.ordered-list-editor .tabulator-table {
+ display: table !important; /* Force display as table */
+ width: 100% !important;
+ table-layout: fixed !important; /* Use fixed table layout for consistent column widths */
}
/* Style for the handle column */
.ordered-list-editor .tabulator-row-handle {
cursor: move;
+ background-color: #f8f9fa;
+ border-right: 1px solid #dee2e6;
+}
+
+/* Style for the handle bars to make them more visible */
+.ordered-list-editor .tabulator-row-handle-box {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ height: 100%;
+}
+
+.ordered-list-editor .tabulator-row-handle-bar {
+ background: #666;
+ display: inline-block;
+ width: 10px;
+ height: 2px;
+ margin: 1px 0;
}
/* Style for the delete button */
@@ -228,4 +427,133 @@ document.addEventListener('DOMContentLoaded', function() {
.ordered-list-editor .tabulator-cell[data-type="boolean"] {
text-align: center;
}
+
+/* Style for the table header */
+.ordered-list-editor .tabulator-header {
+ background-color: #f8f9fa;
+ border-bottom: 2px solid #dee2e6;
+}
+
+/* Style for the headers container */
+.ordered-list-editor .tabulator-headers {
+ display: table-row !important; /* Force display as table row */
+}
+
+/* Style for the header cells */
+.ordered-list-editor .tabulator-col {
+ background-color: #f8f9fa;
+ 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 */
+}
+
+/* Override any inline styles that might hide column headers */
+.ordered-list-editor .tabulator-col[style*="display: none"] {
+ display: table-cell !important; /* Force display as table cell */
+}
+
+/* Ensure header cells have the same width as their corresponding data cells */
+.ordered-list-editor .tabulator-col,
+.ordered-list-editor .tabulator-cell {
+ {#width: auto !important; /* Let the table-layout: fixed handle the width */#}
+}
+
+/* Style for the header cell content */
+.ordered-list-editor .tabulator-col-title {
+ white-space: normal; /* Allow header text to wrap */
+ word-break: break-word; /* Break words to prevent horizontal overflow */
+ font-weight: bold;
+ color: #333;
+}
+
+/* Style for the table rows */
+.ordered-list-editor .tabulator-row {
+ border-bottom: 1px solid #dee2e6;
+ display: table-row !important; /* Force display as table row */
+}
+
+/* Style for the table cells */
+.ordered-list-editor .tabulator-cell {
+ padding: 8px;
+ white-space: normal; /* Allow text to wrap */
+ overflow: visible; /* Show overflowing content */
+ height: auto !important; /* Allow cell to grow as needed */
+ word-break: break-word; /* Break words to prevent horizontal overflow */
+ display: table-cell !important; /* Force display as table cell */
+ scroll-margin-top: 100px; /* Prevent unwanted scrolling when focusing */
+ scroll-behavior: auto; /* Disable smooth scrolling which might cause jumping */
+ font-size: 0.85rem; /* Smaller font size */
+}
+
+/* Style for truncated cells */
+.ordered-list-editor .truncated-cell {
+ position: relative;
+ padding-right: 20px;
+}
+
+.ordered-list-editor .truncated-content {
+ white-space: normal;
+ word-break: break-word;
+}
+
+.ordered-list-editor .show-more {
+ position: absolute;
+ right: 0;
+ top: 50%;
+ transform: translateY(-50%);
+ color: #007bff;
+ cursor: pointer;
+}
+
+/* Style for the visible cells */
+.ordered-list-editor .tabulator-cell-visible {
+ display: table-cell !important; /* Force display as table cell */
+}
+
+/* Override any inline styles that might hide cells */
+.ordered-list-editor .tabulator-cell[style*="display: none"] {
+ display: table-cell !important; /* Force display as table cell */
+}
+
+/* Style for the textarea editor */
+.ordered-list-editor .tabulator-cell textarea {
+ min-height: 60px;
+ resize: vertical;
+ width: 100%; /* Ensure textarea fills the cell */
+}
+
+/* Style for the placeholder */
+.ordered-list-editor .tabulator-placeholder {
+ padding: 20px;
+ text-align: center;
+ color: #6c757d;
+}
+
+/* Style for the Add Row button */
+.ordered-list-editor + .btn-primary {
+ margin-top: 0.5rem;
+}
+
+/* Fullscreen mode styles */
+.ordered-list-editor.fullscreen-mode {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100vw;
+ height: 100vh;
+ z-index: 9999;
+ background: white;
+ padding: 20px;
+ margin: 0;
+ overflow: auto;
+ box-sizing: border-box;
+}
+
+.ordered-list-editor.fullscreen-mode .tabulator {
+ height: calc(100vh - 100px) !important;
+ width: 100% !important;
+}
diff --git a/eveai_app/templates/macros.html b/eveai_app/templates/macros.html
index 43e0c08..d513f75 100644
--- a/eveai_app/templates/macros.html
+++ b/eveai_app/templates/macros.html
@@ -69,8 +69,9 @@
{{ field(class="form-control d-none " + class, disabled=disabled, readonly=readonly) }}
{% elif field.type == 'OrderedListField' or 'ordered-list-field' in field_class %}
- {# Behoud ordered-list-field class en voeg form-control toe #}
- {{ field(class="form-control " + field_class|trim, disabled=disabled, readonly=readonly) }}
+ {# Create container for ordered list editor and hide the textarea #}
+
+ {{ field(class="form-control d-none " + field_class|trim, disabled=disabled, readonly=readonly) }}
{% elif field.type == 'SelectField' %}
{{ field(class="form-control form-select " + class, disabled=disabled, readonly=readonly) }}
{% else %}
@@ -449,4 +450,3 @@
{% endmacro %}
-
diff --git a/eveai_app/templates/scripts.html b/eveai_app/templates/scripts.html
index ca5c2ea..876bfce 100644
--- a/eveai_app/templates/scripts.html
+++ b/eveai_app/templates/scripts.html
@@ -13,11 +13,15 @@