Initial commit.

This commit is contained in:
2025-06-21 17:51:07 +01:00
commit 6fd3a23aa7
296 changed files with 29154 additions and 0 deletions

123
static/js/pages/base.js Normal file
View File

@@ -0,0 +1,123 @@
import BusinessObjects from "../lib/business_objects/business_objects.js";
import Events from "../lib/events.js";
import LocalStorage from "../lib/local_storage.js";
import API from "../api.js";
import DOM from "../dom.js";
import Utils from "../lib/utils.js";
import OverlayConfirm from "../components/common/temporary/overlay_confirm.js";
import OverlayError from "../components/common/temporary/overlay_error.js";
export default class BasePage {
constructor(router) {
if (!router) {
throw new Error("Router is required");
}
else {
Utils.consoleLogIfNotProductionEnvironment("initialising with router: ", router);
}
this.router = router;
this.title = titlePageCurrent;
if (this.constructor === BasePage) {
throw new Error("Cannot instantiate abstract class");
}
if (!this.constructor.hash) {
throw new Error(`Class ${this.constructor.name} must have a static hash attribute.`);
}
}
initialize() {
throw new Error("Method 'initialize()' must be implemented.");
}
sharedInitialize() {
this.logInitialisation();
this.hookupCommonElements();
}
logInitialisation() {
Utils.consoleLogIfNotProductionEnvironment('Initializing ' + this.title + ' page');
}
hookupCommonElements() {
// hookupVideos();
this.hookupLogos();
this.hookupOverlays();
}
hookupEventHandler(eventType, selector, callback) {
Events.initialiseEventHandler(selector, flagInitialised, (element) => {
element.addEventListener(eventType, (event) => {
event.stopPropagation();
callback(event, element);
});
});
}
hookupLogos() {
this.hookupEventHandler("click", "." + flagImageLogo + "," + "." + flagLogo, (event, element) => {
Utils.consoleLogIfNotProductionEnvironment('clicking logo');
this.router.navigateToHash(hashPageHome);
});
}
hookupOverlays() {
this.hookupOverlayFromId(idOverlayConfirm);
this.hookupOverlayFromId(idOverlayError);
}
hookupOverlayFromId(idOverlay) {
Events.initialiseEventHandler(idOverlay, flagInitialised, (overlay) => {
overlay.querySelector('button.' + flagCancel).addEventListener("click", (event) => {
event.stopPropagation();
overlay.style.display = 'none';
});
});
}
hookupButtonSave() {
Events.initialiseEventHandler('form.' + flagFilter + ' button.' + flagSave, flagInitialised, (button) => {
button.addEventListener("click", (event) => {
event.stopPropagation();
Utils.consoleLogIfNotProductionEnvironment('saving page: ', this.title);
OverlayConfirm.show();
});
});
}
leave() {
Utils.consoleLogIfNotProductionEnvironment('Leaving ' + this.title + ' page');
if (this.constructor === BasePage) {
throw new Error("Must implement leave() method.");
}
}
setLocalStoragePage(dataPage) {
LocalStorage.setLocalStorage(this.hash, dataPage);
}
getLocalStoragePage() {
return LocalStorage.getLocalStorage(this.hash);
}
toggleShowButtonsSaveCancel(show) { // , buttonSave = null, buttonCancel = null
let buttonSave = document.querySelector('form.' + flagFilter + ' button.' + flagSave);
let buttonCancel = document.querySelector('form.' + flagFilter + ' button.' + flagCancel);
if (show) {
buttonCancel.classList.remove(flagCollapsed);
buttonSave.classList.remove(flagCollapsed);
Utils.consoleLogIfNotProductionEnvironment('showing buttons');
} else {
buttonCancel.classList.add(flagCollapsed);
buttonSave.classList.add(flagCollapsed);
Utils.consoleLogIfNotProductionEnvironment('hiding buttons');
}
}
static isDirtyFilter(filter) {
let isDirty = DOM.updateAndCheckIsElementDirty(filter);
if (isDirty) document.querySelectorAll(idTableMain + ' tbody tr').remove();
return isDirty;
}
}

View File

@@ -0,0 +1,553 @@
import BusinessObjects from "../lib/business_objects/business_objects.js";
import Events from "../lib/events.js";
import LocalStorage from "../lib/local_storage.js";
import Validation from "../lib/validation.js";
import BasePage from "./base.js";
import API from "../api.js";
import DOM from "../dom.js";
import Utils from "../lib/utils.js";
import OverlayConfirm from "../components/common/temporary/overlay_confirm.js";
import OverlayError from "../components/common/temporary/overlay_error.js";
export default class TableBasePage extends BasePage {
// static hash
// static attrIdRowObject
// callSaveTableContent
constructor(router) {
super(router);
this.cursorYInitial = null;
this.rowInitial = null;
this.placeholder = null;
this.dragSrcEl = null;
this.dragSrcRow = null;
this.hookupTableCellDdls = this.hookupTableCellDdls.bind(this);
}
initialize(isPopState = false) {
throw new Error("Must implement initialize() method.");
}
sharedInitialize(isPopState = false, isSinglePageApp = false) {
if (!isPopState) {
super.sharedInitialize();
this.hookupFilters();
this.hookupButtonsSaveCancel();
this.hookupTableMain();
OverlayConfirm.hookup(() => {
if (isSinglePageApp) {
this.saveRecordsTableDirtySinglePageApp();
}
else {
this.saveRecordsTableDirty();
}
});
} else {
let dataPage = this.getLocalStoragePage();
let filters = dataPage[flagFormFilters];
let formFilters = this.getFormFilters();
let filtersDefault = DOM.convertForm2JSON(formFilters);
if (!Validation.areEqualDicts(filters, filtersDefault)) {
this.callFilterTableContent();
}
}
}
hookupFilters() {
if (this.constructor === TableBasePage) {
throw new Error("Subclass of TableBasePage must implement method hookupFilters().");
}
}
sharedHookupFilters() {
this.hookupButtonApplyFilters();
}
hookupFilterActive() {
this.hookupFilter(flagActive);
}
hookupFilter(filterFlag, handler = (event, filter) => { return TableBasePage.isDirtyFilter(filter); }) {
let filterSelector = idFormFilters + ' .' + filterFlag;
this.hookupEventHandler("change", filterSelector, handler);
}
static isDirtyFilter(filter) {
let isDirty = DOM.updateAndCheckIsElementDirty(filter);
if (isDirty) {
let tbody = document.querySelector(idTableMain + ' tbody');
tbody.querySelectorAll('tr').remove();
tbody.appendChild(document.createElement('<div>Press "Apply Filters" to refresh the table.</div>'));
}
return isDirty;
}
hookupFilterIsNotEmpty() {
this.hookupFilter(flagIsNotEmpty);
}
hookupButtonApplyFilters() {
this.hookupEventHandler("click", idButtonApplyFilters, (event, button) => {
event.stopPropagation();
this.callFilterTableContent();
});
}
/*
getAndLoadFilteredTableContent = () => {
this.callFilterTableContent()
.catch(error => console.error('Error:', error));
}
*/
getFormFilters() {
return document.querySelector(idFormFilters);
}
callFilterTableContent() {
let formFilters = this.getFormFilters();
let filtersJson = DOM.convertForm2JSON(formFilters);
this.leave();
API.goToHash(this.constructor.hash, filtersJson);
}
callbackLoadTableContent(response) {
let table = TableBasePage.getTableMain();
let bodyTable = table.querySelector('tbody');
bodyTable.querySelectorAll('tr').forEach(function(row) { row.remove(); });
let rowsJson = response.data[flagRows];
if (!Validation.isEmpty(rowsJson) && rowsJson.every(row => row.hasOwnProperty('display_order'))) {
rowsJson = rowsJson.sort((a, b) => a.display_order - b.display_order);
}
rowsJson.forEach(this.loadRowTable.bind(this));
this.hookupTableMain();
}
static getTableMain() {
return document.querySelector(idTableMain);
}
loadRowTable(rowJson) {
throw new Error("Subclass of TableBasePage must implement method loadRowTable().");
}
getAndLoadFilteredTableContentSinglePageApp() {
this.callFilterTableContent()
.then(data => {
Utils.consoleLogIfNotProductionEnvironment('Table data received:', data);
this.callbackLoadTableContent(data);
})
.catch(error => console.error('Error:', error));
}
hookupButtonsSaveCancel() {
this.hookupButtonSave();
this.hookupButtonCancel();
this.toggleShowButtonsSaveCancel(false);
}
saveRecordsTableDirty() {
let records = this.getTableRecords(true);
if (records.length == 0) {
OverlayError.show('No records to save');
return;
}
let formElement = this.getFormFilters();
let comment = DOM.getElementValueCurrent(document.querySelector(idTextareaConfirm));
this.callSaveTableContent(records, formElement, comment)
.then(data => {
if (data[flagStatus] == flagSuccess) {
if (_verbose) {
Utils.consoleLogIfNotProductionEnvironment('Records saved!');
Utils.consoleLogIfNotProductionEnvironment('Data received:', data);
}
this.callFilterTableContent();
}
else {
Utils.consoleLogIfNotProductionEnvironment("error: ", data[flagMessage]);
OverlayError.show(data[flagMessage]);
}
})
.catch(error => console.error('Error:', error));
}
getTableRecords(dirtyOnly = false) {
let records = [];
let record;
document.querySelectorAll(idTableMain + ' > tbody > tr').forEach((row) => {
if (dirtyOnly && !DOM.hasDirtyChildrenContainer(row)) return;
record = this.getJsonRow(row);
records.push(record);
});
return records;
}
getJsonRow(row) {
throw new Error("Subclass of TableBasePage must implement method getJsonRow().");
}
saveRecordsTableDirtySinglePageApp() {
let records = this.getTableRecords(true);
if (records.length == 0) {
OverlayError.show('No records to save');
return;
}
let formElement = this.getFormFilters();
let comment = DOM.getElementValueCurrent(document.querySelector(idTextareaConfirm));
this.callSaveTableContent(records, formElement, comment)
.then(data => {
if (data[flagStatus] == flagSuccess) {
if (_verbose) {
Utils.consoleLogIfNotProductionEnvironment('Records saved!');
Utils.consoleLogIfNotProductionEnvironment('Data received:', data);
}
this.callbackLoadTableContent(data);
}
else {
Utils.consoleLogIfNotProductionEnvironment("error: ", data[flagMessage]);
OverlayError.show(data[flagMessage]);
}
})
.catch(error => console.error('Error:', error));
}
hookupButtonCancel() {
Events.initialiseEventHandler(idFormFilters + ' button.' + flagCancel, flagInitialised, (button) => {
button.addEventListener("click", (event) => {
event.stopPropagation();
this.callFilterTableContent();
});
button.classList.add(flagCollapsed);
});
}
handleClickAddRowTable(event, button) {
event.stopPropagation();
_rowBlank.setAttribute(this.constructor.attrIdRowObject, -1 - _rowBlank.getAttribute(this.constructor.attrIdRowObject));
let tbody = document.querySelector(idTableMain + ' tbody');
let row = _rowBlank.cloneNode(true);
row.classList.remove(flagInitialised);
row.querySelectorAll('.' + flagInitialised).forEach(function(element) {
element.classList.remove(flagInitialised);
});
let countRows = document.querySelectorAll(idTableMain + ' > tbody > tr').length;
row.setAttribute(this.constructor.attrIdRowObject, -1 - countRows);
this.initialiseRowNew(tbody, row);
tbody.appendChild(row);
this.hookupTableMain();
}
initialiseRowNew(tbody, row) {
if (this.constructor === TableBasePage) {
throw new Error("Subclass of TableBasePage must implement method initialiseRowNew().");
}
row.classList.remove(flagRowNew);
}
hookupTableMain() {
if (this.constructor === TableBasePage) {
throw new Error("Must implement hookupTableMain() method.");
}
if (true) { // _rowBlank == null) {
Events.initialiseEventHandler(idTableMain, flagInitialised, (table) => {
this.cacheRowBlank();
});
}
}
cacheRowBlank() {
let selectorRowNew = idTableMain + ' tbody tr.' + flagRowNew;
let rowBlankTemp = document.querySelector(selectorRowNew);
Utils.consoleLogIfNotProductionEnvironment("row blank temp: ", rowBlankTemp);
let countRows = document.querySelectorAll(idTableMain + ' > tbody > tr').length;
_rowBlank = rowBlankTemp.cloneNode(true);
document.querySelectorAll(selectorRowNew).forEach(function(row) {
row.remove();
});
_rowBlank.setAttribute(this.constructor.attrIdRowObject, -1 - countRows);
}
initialiseSliderDisplayOrderRowNew(tbody, row) {
// let tdSelector = ':scope > tr > td.' + flagDisplayOrder;
// let tbody = document.querySelector('table' + (Validation.isEmpty(flagTable) ? '' : '.' + flagTable) + ' > tbody');
let slidersDisplayOrder = tbody.querySelectorAll(':scope > tr > td.' + flagDisplayOrder + ' input.' + flagSlider);
let maxDisplayOrder = 0;
slidersDisplayOrder.forEach((slider) => {
maxDisplayOrder = Math.max(maxDisplayOrder, parseFloat(DOM.getElementValueCurrent(slider)));
});
let sliderDisplayOrder = row.querySelector('td.' + flagDisplayOrder + ' .' + flagSlider);
DOM.setElementValuesCurrentAndPrevious(sliderDisplayOrder, maxDisplayOrder + 1);
}
hookupSlidersDisplayOrderTable() {
let selectorDisplayOrder = idTableMain + ' tbody tr td.' + flagDisplayOrder + ' input.' + flagSlider + '.' + flagDisplayOrder;
this.hookupChangeHandlerTableCells(selectorDisplayOrder);
}
hookupChangeHandlerTableCells(inputSelector, handler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }) {
Events.initialiseEventHandler(inputSelector, flagInitialised, (input) => {
input.addEventListener("change", (event) => {
handler(event, input);
});
handler(null, input);
});
}
/*
handleChangeElementCellTable(event, element) {
let row = DOM.getRowFromElement(element);
let td = DOM.getCellFromElement(element);
let wasDirtyRow = DOM.hasDirtyChildrenContainer(row);
let wasDirtyElement = element.classList.contains(flagDirty);
let isDirtyElement = DOM.updateAndCheckIsElementDirty(element);
if (isDirtyElement != wasDirtyElement) {
DOM.handleDirtyElement(td, isDirtyElement);
let isNowDirtyRow = DOM.hasDirtyChildrenContainer(row);
if (isNowDirtyRow != wasDirtyRow) {
DOM.handleDirtyElement(row, isNowDirtyRow);
let rows = this.getTableRecords(true);
let existsDirtyRecord = rows.length > 0;
this.toggleShowButtonsSaveCancel(existsDirtyRecord);
}
}
}
handleChangeElementNestedCellTable(event, element, flagColumnList = [], orderNesting = 1) {
let orderNestingTemp = orderNesting;
let row, td, nestedRowSelector;
while (orderNestingTemp > 0) {
nestedRowSelector = idTableMain;
for (let indexOrderNesting = 0; indexOrderNesting < orderNestingTemp; indexOrderNesting++) {
nestedRowSelector += ' tbody tr';
}
row = DOM.getClosestParent(element, nestedRowSelector);
td = row.querySelector('td.' + flag);
}
let row = DOM.getRowFromElement(element);
let td = DOM.getCellFromElement(element);
let wasDirtyRow = DOM.hasDirtyChildrenContainer(row);
let wasDirtyElement = element.classList.contains(flagDirty);
let isDirtyElement = DOM.updateAndCheckIsElementDirty(element);
if (isDirtyElement != wasDirtyElement) {
DOM.handleDirtyElement(td, isDirtyElement);
let isNowDirtyRow = DOM.hasDirtyChildrenContainer(row);
if (isNowDirtyRow != wasDirtyRow) {
DOM.handleDirtyElement(row, isNowDirtyRow);
let rows = this.getTableRecords(true);
let existsDirtyRecord = rows.length > 0;
this.toggleShowButtonsSaveCancel(existsDirtyRecord);
}
}
}
handleChangeElementSubtableCell(event, element, flagFieldSubtable) {
let rowSubtable = element.closest(idTableMain + ' td.' + flagFieldSubtable + ' tbody tr');
let rowTable = rowSubtable.closest(idTableMain + ' > tbody > tr');
let td = DOM.getCellFromElement(element);
// let tdSubtable = td.closest('td.' + flagFieldSubtable);
let wasDirtyRowSubtable = DOM.hasDirtyChildrenContainer(rowSubtable);
let wasDirtyRowTable = DOM.hasDirtyChildrenContainer(rowTable);
let wasDirtyElement = element.classList.contains(flagDirty);
let isDirtyElement = DOM.updateAndCheckIsElementDirty(element);
Utils.consoleLogIfNotProductionEnvironment({isDirtyElement, wasDirtyElement});
if (isDirtyElement != wasDirtyElement) {
DOM.handleDirtyElement(td, isDirtyElement);
let isNowDirtyRowSubtable = DOM.hasDirtyChildrenContainer(rowSubtable);
Utils.consoleLogIfNotProductionEnvironment({isNowDirtyRowSubtable, wasDirtyRowSubtable});
if (isNowDirtyRowSubtable != wasDirtyRowSubtable) {
DOM.handleDirtyElement(rowSubtable, isNowDirtyRowSubtable);
let isNowDirtyRowTable = DOM.hasDirtyChildrenContainer(rowTable);
Utils.consoleLogIfNotProductionEnvironment({isNowDirtyRowTable, wasDirtyRowTable});
if (isNowDirtyRowTable != wasDirtyRowTable) {
DOM.handleDirtyElement(rowTable, isNowDirtyRowTable);
let rows = this.getTableRecords(true);
let existsDirtyRecord = rows.length > 0;
this.toggleShowButtonsSaveCancel(existsDirtyRecord);
}
}
}
}
*/
handleChangeNestedElementCellTable(event, element) {
let wasDirtyParentRows = this.getAllIsDirtyRowsInParentTree(element);
let wasDirtyElement = element.classList.contains(flagDirty);
let isDirtyElement = DOM.updateAndCheckIsElementDirty(element);
Utils.consoleLogIfNotProductionEnvironment({isDirtyElement, wasDirtyElement, wasDirtyParentRows});
let td = DOM.getCellFromElement(element);
DOM.setElementAttributeValueCurrent(td, DOM.getElementAttributeValueCurrent(element));
if (isDirtyElement != wasDirtyElement) {
DOM.handleDirtyElement(td, isDirtyElement);
this.updateAndToggleShowButtonsSaveCancel();
this.cascadeChangedIsDirtyNestedElementCellTable(element, isDirtyElement, wasDirtyParentRows);
}
}
getAllIsDirtyRowsInParentTree(element) {
let rows = [];
let parent = element;
let isDirty;
while (parent) {
if (parent.matches('tr')) {
isDirty = parent.classList.contains(flagDirty)
rows.push(isDirty);
}
parent = parent.parentElement;
}
return rows;
}
cascadeChangedIsDirtyNestedElementCellTable(element, isDirtyElement, wasDirtyParentRows) {
if (Validation.isEmpty(wasDirtyParentRows)) return;
let td = DOM.getCellFromElement(element);
let isDirtyTd = isDirtyElement || DOM.hasDirtyChildrenContainer(tr);
DOM.handleDirtyElement(td, isDirtyTd);
let tr = DOM.getRowFromElement(td);
let isDirtyRow = isDirtyTd || DOM.hasDirtyChildrenContainer(tr);
let wasDirtyRow = wasDirtyParentRows.shift();
Utils.consoleLogIfNotProductionEnvironment({isDirtyRow, wasDirtyRow});
if (isDirtyRow != wasDirtyRow) {
DOM.handleDirtyElement(tr, isDirtyRow);
this.updateAndToggleShowButtonsSaveCancel();
this.cascadeChangedIsDirtyNestedElementCellTable(tr.parentElement, isDirtyRow, wasDirtyParentRows);
}
}
hookupChangeHandlerTableCellsWhenNotCollapsed(inputSelector, handler = (event, element) => {
if (!element.classList.contains(flagCollapsed)) this.handleChangeNestedElementCellTable(event, element);
}) {
this.hookupEventHandler("change", inputSelector, handler);
}
hookupTextareasCodeTable() {
this.hookupChangeHandlerTableCells(idTableMain + ' tbody tr td.' + flagCode + ' textarea');
}
hookupTextareasNameTable() {
this.hookupChangeHandlerTableCells(idTableMain + ' tbody tr td.' + flagName + ' textarea');
}
hookupTextareasDescriptionTable() {
this.hookupChangeHandlerTableCells(idTableMain + ' tbody tr td.' + flagDescription + ' textarea');
}
hookupFieldsActive(flagTable = '', handleClickRowNew = (event, element) => { this.handleClickAddRowTable(event, element); }) {
let selectorButton = 'table' + (Validation.isEmpty(flagTable) ? '' : '.' + flagTable) + ' > tbody > tr > td.' + flagActive + ' button';
let selectorButtonDelete = selectorButton + '.' + flagDelete;
let selectorButtonUndelete = selectorButton + ':not(.' + flagDelete + ')';
Utils.consoleLogIfNotProductionEnvironment("hookupFieldsActive: ", selectorButtonDelete, selectorButtonUndelete);
this.hookupButtonsRowDelete(selectorButtonDelete, selectorButtonUndelete);
this.hookupButtonsRowUndelete(selectorButtonDelete, selectorButtonUndelete);
this.hookupEventHandler(
"click"
, 'table' + (Validation.isEmpty(flagTable) ? '' : '.' + flagTable) + ' > thead > tr > th.' + flagActive + ' button'
, (event, button) => { handleClickRowNew(event, button); }
);
}
hookupButtonsRowDelete(selectorButtonDelete, selectorButtonUndelete, changeHandler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }) {
this.hookupEventHandler("click", selectorButtonDelete, (event, element) => {
this.handleClickButtonRowDelete(event, element, selectorButtonDelete, selectorButtonUndelete, (changeEvent, changeElement) => { changeHandler(changeEvent, changeElement); });
});
}
handleClickButtonRowDelete(event, element, selectorButtonDelete, selectorButtonUndelete, changeHandler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }) {
let row = DOM.getRowFromElement(element);
if (row.classList.contains(flagRowNew) && !DOM.hasDirtyChildrenContainer(row)) {
row.parentNode.removeChild(row);
}
let buttonAdd = element.cloneNode(false);
buttonAdd.classList.remove(flagInitialised);
buttonAdd.classList.remove(flagDelete);
buttonAdd.classList.add(flagAdd);
buttonAdd.textContent = '+';
element.replaceWith(buttonAdd);
changeHandler(null, buttonAdd);
this.hookupButtonsRowUndelete(selectorButtonDelete, selectorButtonUndelete, (changeEvent, changeElement) => { changeHandler(changeEvent, changeElement); });
this.updateAndToggleShowButtonsSaveCancel();
}
hookupButtonsRowUndelete(selectorButtonDelete, selectorButtonUndelete, changeHandler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }) {
this.hookupEventHandler("click", selectorButtonUndelete, (event, element) => {
this.handleClickButtonRowUndelete(event, element, selectorButtonDelete, selectorButtonUndelete, (changeEvent, changeElement) => { changeHandler(changeEvent, changeElement); });
});
}
handleClickButtonRowUndelete(event, element, selectorButtonDelete, selectorButtonUndelete, changeHandler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }) {
let buttonDelete = element.cloneNode(false);
buttonDelete.classList.remove(flagInitialised);
buttonDelete.classList.remove(flagAdd);
buttonDelete.classList.add(flagDelete);
buttonDelete.textContent = 'x';
element.replaceWith(buttonDelete);
changeHandler(null, buttonDelete);
this.hookupButtonsRowDelete(selectorButtonDelete, selectorButtonUndelete, (changeEvent, changeElement) => { changeHandler(changeEvent, changeElement); });
this.updateAndToggleShowButtonsSaveCancel();
}
hookupTdsAccessLevel() {
let cellSelector = idTableMain + ' tbody td.' + flagAccessLevel;
this.hookupTableCellDdlPreviews(cellSelector, Utils.getListFromDict(accessLevels));
}
hookupTableCellDdlPreviews(
cellSelector
, optionList
, ddlHookup = (cellSelector) => { this.hookupTableCellDdls(cellSelector); }
, changeHandler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }
) {
this.hookupEventHandler("click", cellSelector, (event, td) => {
this.handleClickTableCellDdlPreview(
event
, td
, optionList
, cellSelector
, (cellSelector) => { ddlHookup(
cellSelector
, (event, element) => { changeHandler(event, element); }
); }
);
});
ddlHookup(cellSelector + ' select');
}
hookupTableCellDdls(ddlSelector, changeHandler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }) {
this.hookupEventHandler("change", ddlSelector, (event, element) => { changeHandler(event, element); });
}
handleClickTableCellDdlPreview(event, td, optionObjectList, cellSelector, ddlHookup = (cellSelector) => { this.hookupTableCellDdls(cellSelector); }) {
if (td.querySelector('select')) return;
let tdNew = td.cloneNode(true);
td.parentNode.replaceChild(tdNew, td);
let idSelected = DOM.getElementAttributeValueCurrent(tdNew);
tdNew.innerHTML = '';
let ddl = document.createElement('select');
DOM.setElementValuesCurrentAndPrevious(ddl, idSelected);
let optionJson, option;
if (_verbose) {
Utils.consoleLogIfNotProductionEnvironment("click table cell ddl preview");
Utils.consoleLogIfNotProductionEnvironment({optionObjectList, cellSelector});
}
option = DOM.createOption(null);
ddl.appendChild(option);
optionObjectList.forEach((optionObjectJson) => {
optionJson = BusinessObjects.getOptionJsonFromObjectJson(optionObjectJson, idSelected);
option = DOM.createOption(optionJson);
ddl.appendChild(option);
});
tdNew.appendChild(ddl);
let ddlSelector = cellSelector + ' select';
ddlHookup(ddlSelector);
}
hookupTableCellDDlPreviewsWhenNotCollapsed(cellSelector, optionList, ddlHookup = (event, element) => { this.hookupTableCellDdls(event, element); }) {
this.hookupEventHandler("click", cellSelector, (event, td) => {
let div = td.querySelector('div');
if (!div || div.classList.contains(flagCollapsed)) return;
this.handleClickTableCellDdlPreview(event, td, optionList, cellSelector, (event, element) => { ddlHookup(event, element); });
});
}
toggleColumnCollapsed(flagColumn, isCollapsed) {
this.toggleColumnHasClassnameFlag(flagColumn, isCollapsed, flagCollapsed);
}
toggleColumnHeaderCollapsed(flagColumn, isCollapsed) {
this.toggleColumnHasClassnameFlag(flagColumn, isCollapsed, flagCollapsed);
}
createTdActive(isActive) {
let tdActive = document.createElement("td");
tdActive.classList.add(flagActive);
let buttonActive = document.createElement("button");
buttonActive.classList.add(flagActive);
buttonActive.classList.add(isActive ? flagDelete : flagAdd);
buttonActive.textContent = isActive ? 'x' : '+';
DOM.setElementAttributesValuesCurrentAndPrevious(buttonActive, isActive);
tdActive.appendChild(buttonActive);
return tdActive;
}
leave() {
if (this.constructor === TableBasePage) {
throw new Error("Must implement leave() method.");
}
super.leave();
let formFilters = this.getFormFilters();
let dataPage = {};
dataPage[flagFormFilters] = DOM.convertForm2JSON(formFilters);
this.setLocalStoragePage(dataPage);
}
toggleColumnHasClassnameFlag(columnFlag, isRequiredFlag, classnameFlag) {
let table = TableBasePage.getTableMain();
let columnTh = table.querySelector('th.' + columnFlag);
let columnThHasFlag = columnTh.classList.contains(classnameFlag);
if (isRequiredFlag == columnThHasFlag) return;
DOM.toggleElementHasClassnameFlag(columnTh, isRequiredFlag, classnameFlag);
}
toggleColumnHeaderHasClassnameFlag(columnFlag, isRequiredFlag, classnameFlag) {
let table = TableBasePage.getTableMain();
let columnTh = table.querySelector('th.' + columnFlag);
DOM.toggleElementHasClassnameFlag(columnTh, isRequiredFlag, classnameFlag);
}
updateAndToggleShowButtonsSaveCancel() {
let records = this.getTableRecords(true);
let existsDirtyRecord = records.length > 0;
this.toggleShowButtonsSaveCancel(existsDirtyRecord);
}
}

View File

@@ -0,0 +1,16 @@
// internal
import BasePage from "../base.js";
// vendor
import { Altcha } from "../../vendor/altcha.js";
export default class PageContactSuccess extends BasePage {
static hash = hashPageContactSuccess;
constructor(router) {
super(router);
}
initialize() {
this.sharedInitialize();
}
}

View File

@@ -0,0 +1,23 @@
// internal
import BasePage from "../base.js";
// vendor
import { Altcha } from "../../vendor/altcha.js";
export default class PageContact extends BasePage {
static hash = hashPageContact;
constructor(router) {
super(router);
}
initialize() {
this.sharedInitialize();
this.hookupButtonSubmitFormContactUs();
}
hookupButtonSubmitFormContactUs() {
const button = document.querySelector('form input[type="submit"]');
button.classList.add(flagButton);
button.classList.add(flagButtonPrimary);
}
}

View File

@@ -0,0 +1,23 @@
// internal
import BasePage from "../base.js";
// external
export default class PageHome extends BasePage {
static hash = hashPageHome;
constructor(router) {
super(router);
}
initialize() {
this.sharedInitialize();
this.hookupButtonsNavContact();
}
leave() {
super.leave();
}
}

View File

@@ -0,0 +1,17 @@
import BasePage from "../base.js";
export default class PageAccessibilityReport extends BasePage {
static hash = hashPageAccessibilityReport;
constructor(router) {
super(router);
}
initialize() {
this.sharedInitialize();
}
leave() {
super.leave();
}
}

View File

@@ -0,0 +1,17 @@
import BasePage from "../base.js";
export default class PageAccessibilityStatement extends BasePage {
static hash = hashPageAccessibilityStatement;
constructor(router) {
super(router);
}
initialize() {
this.sharedInitialize();
}
leave() {
super.leave();
}
}

View File

@@ -0,0 +1,18 @@
import BasePage from "../base.js";
export default class PageLicense extends BasePage {
static hash = hashPageLicense;
constructor(router) {
super(router);
}
initialize() {
this.sharedInitialize();
}
leave() {
super.leave();
}
}

View File

@@ -0,0 +1,18 @@
import BasePage from "../base.js";
export default class PagePrivacyPolicy extends BasePage {
static hash = hashPagePrivacyPolicy;
constructor(router) {
super(router);
}
initialize() {
this.sharedInitialize();
}
leave() {
super.leave();
}
}

View File

@@ -0,0 +1,17 @@
import BasePage from "../base.js";
export default class PageRetentionSchedule extends BasePage {
static hash = hashPageDataRetentionSchedule;
constructor(router) {
super(router);
}
initialize() {
this.sharedInitialize();
}
leave() {
super.leave();
}
}

View File

@@ -0,0 +1,19 @@
import BasePage from "../base.js";
export default class PageUser extends BasePage {
static hash = hashPageUser;
constructor(router) {
super(router);
}
initialize() {
this.sharedInitialize();
this.hookupButtonsNavContact();
}
leave() {
super.leave();
}
}