/** * "createConceptsTables.js" * is a module that creates the concepts table and the child row with concept details. * It uses the DataTables library to create the tables and the dataFetcher module to fetch the data from the API. * The module exports a function that creates the concepts table and returns a function * that updates the concepts table with new data. * The module also exports a function that creates the child row, when a concept row is clicked. * The module uses the createCodesTable module to create the codes table in the modal. */ import { fetchAndFilterArtefactsCollection } from "./dataFetcher.js"; import { getStorageData, createSelectElement, createDropdownLabel, createFlexContainer, addChangeListenerToSelect, addOptionsToSelect, extractLabelFromDsId, } from "./utils.js"; import { sessionKeys } from "./sessionStorageKeys.js"; import { createCodesTable } from "./createCodesTable.js"; /** * Initializes the concepts table with the provided concept data for rows. * @param {Array} conceptDataForRows - The data to populate the table rows. * @returns {Function} - An update function to update the parent data table. */ export async function initializeConceptsTable(conceptDataForRows) { const placeholder = document.querySelector("#concepts-table > table"); const dfIdFullList = getStorageData(sessionKeys.dfIdsAll); const artefactsCollection = await fetchAndFilterArtefactsCollection(dfIdFullList); const tableHeaders = generateTableHeaderAndFooter(artefactsCollection, dfIdFullList); const parentTable = new DataTable(placeholder, { initComplete: function () { this.api() .columns() .every(function (index) { let column = this; if (index === 1) { const id = "generalConceptFilter"; const title = "General Concept Selector"; const select = createSelectElement(title, id).append(new Option("-")); const label = createDropdownLabel(title, id); const flexContainer = createFlexContainer().append(label, select); $("#general-concepts-container").append(flexContainer); addChangeListenerToSelect(select, column); addOptionsToSelect(select, column); } if (index === 2 || index === 3) { const title = $(column.footer()).text(); const input = $('').attr('placeholder', title); $(column.footer()).empty().append(input); input.on('keyup', function() { if (column.search() !== this.value) { column.search(this.value).draw(); } }); } if (index >= 4) { const select = createSelectElement("Data Filter", "").append(new Option("")); $(column.footer()).empty().append(select); addChangeListenerToSelect(select, column); addOptionsToSelect(select, column); } }); }, columnDefs: [ { targets: 0, className: "dt-control", orderable: false, data: null, }, { targets: 1, visible: false }, ], data: conceptDataForRows, columns: tableHeaders, }); parentTable.on("click", "td.dt-control", async function (e) { try { const tr = e.target.closest("tr"); const row = parentTable.row(tr); if (row.child.isShown()) { row.child.hide(); } else { row.child(generateChildRowView(row.data())).show(); attachClickHandlersToDataActionButtons(artefactsCollection); } } catch (error) { console.error('An error occurred:', error); } }); function updateParentDataTable(tableRows) { parentTable.clear(); parentTable.rows.add(tableRows); parentTable.draw(); setColumnVisibility(); } function setColumnVisibility() { parentTable.columns().data().each(function (value, index) { if (index < 3) return; // Skip the first 3 columns // Check if all values in the column are empty or undefined var isEmptyColumn = value.every(function (cellValue) { return cellValue === "" || cellValue === undefined; }); if (isEmptyColumn) { parentTable.column(index).visible(false); // Hide the column } else { parentTable.column(index).visible(true); // Show the column } }); } return updateParentDataTable; } /** * Generates the header and footer for a table based on the artefacts collection and a list of dfIds. * @param {Array} artefactsCollection - The collection of artefacts. * @param {Array} dfIdFullList - The list of dfIds to generate the table columns. * @returns {Array} An array of column objects for the table. */ function generateTableHeaderAndFooter(artefactsCollection, dfIdFullList) { const dsIds = dfIdFullList.map((dfId) => { return artefactsCollection.find((artefact) => artefact.dfId === dfId).dsId; }); setHeader(); setFooter(); const columns = [null, "conceptRoles", "conceptId", "conceptName", ...dfIdFullList].map((col) => ({ data: col, defaultContent: "", })); return columns; function setHeader() { const headers = [ { title: "" }, { title: "roles" }, { title: "Variable ID" }, { title: "Variable Name", className: "min-width-200" }, ...dsIds.map((dsId) => ({ title: extractLabelFromDsId(dsId), className: "rotate-180", })), ]; const headerRows = headers .map( (header) => `