Feat(SQL, UI): 1. Perfected architecture for modular Search functionality across heirarchical Get Many and Calc Stored Procedures that allows text search filtering on different fields as well as by record Id with control over how the filters are applied. \n 2. Updated User Calc and Get Many Stored Procedures with new Search functionality. \n 3. Improved styles on Dog Command Link page.

This commit is contained in:
2025-07-05 23:17:07 +01:00
parent 0d1e644e6c
commit 8cb8508dcd
51 changed files with 4161 additions and 1292 deletions

View File

@@ -19,10 +19,11 @@ export default class DOM {
}
static setElementValueCurrent(element, data) {
DOM.setElementAttributeValueCurrent(element, data);
let tagName = element.tagName.toUpperCase();
if (element.type === "checkbox") {
element.checked = data;
}
else if (element.tagName === 'INPUT' || element.tagName === 'TEXTAREA' || element.tagName === 'SELECT') {
else if (tagName === 'INPUT' || tagName === 'TEXTAREA' || tagName === 'SELECT') {
element.value = data;
}
else {
@@ -109,6 +110,7 @@ export default class DOM {
if (!Validation.isEmpty(element)) {
let tagName = element.tagName.toUpperCase();
if (element.type === "checkbox") {
returnVal = element.checked;
}
@@ -117,15 +119,18 @@ export default class DOM {
returnVal = getDatePickerDate(element, adjust4DayLightSavings);
}
*/
else if (element.tagName === 'INPUT' || element.tagName === 'TEXTAREA' || element.tagName === 'SELECT') {
else if (tagName === 'INPUT' || tagName === 'TEXTAREA' || tagName === 'SELECT') {
returnVal = element.value;
}
else if (element.tagName === 'BUTTON' && element.classList.contains(flagActive)) {
else if (tagName === 'BUTTON' && element.classList.contains(flagActive)) {
returnVal = element.classList.contains(flagDelete);
}
else if (element.tagName === 'TD') {
else if (tagName === 'TD') {
returnVal = DOM.getElementAttributeValueCurrent(element);
}
else if (tagName == 'SVG' && element.classList.contains(flagCheckbox)) {
returnVal = (element.classList.contains(flagIsChecked))
}
else {
returnVal = element.textContent;
}

View File

@@ -61,9 +61,35 @@ export default class TableBasePage extends BasePage {
}
sharedHookupFilters() {
this.hookupButtonApplyFilters();
this.hookupSearchTextFilter();
}
hookupFilterActive() {
this.hookupFilter(flagActive);
let filterSelector = idFormFilters + ' #' + flagActiveOnly;
let filterActiveOld = document.querySelector(filterSelector);
filterActiveOld.removeAttribute('id');
let parentDiv = filterActiveOld.parentElement;
let isChecked = (DOM.getElementAttributeValuePrevious(parentDiv) == "True");
let filterActiveNew = document.querySelector(idFormFilters + ' div.' + flagActiveOnly + '.' + flagContainerInput + ' svg.' + flagActiveOnly);
filterActiveNew.setAttribute('id', flagActiveOnly);
if (isChecked) filterActiveNew.classList.add(flagIsChecked);
this.hookupEventHandler("click", filterSelector, (event, filterActive) => {
console.log({ filterActive });
console.log({ [filterActive.tagName]: filterActive.tagName });
let svgElement = (filterActive.tagName.toUpperCase() == 'SVG') ? filterActive : filterActive.parentElement;
let wasChecked = svgElement.classList.contains(flagIsChecked);
if (wasChecked) {
svgElement.classList.remove(flagIsChecked);
}
else {
svgElement.classList.add(flagIsChecked);
}
return TableBasePage.isDirtyFilter(svgElement);
});
let filter = document.querySelector(filterSelector);
let filterValuePrevious = DOM.getElementValueCurrent(filter);
filter.setAttribute(attrValueCurrent, filterValuePrevious);
filter.setAttribute(attrValuePrevious, filterValuePrevious);
}
hookupFilter(filterFlag, handler = (event, filter) => { return TableBasePage.isDirtyFilter(filter); }) {
let filterSelector = idFormFilters + ' #' + filterFlag;
@@ -91,6 +117,9 @@ export default class TableBasePage extends BasePage {
this.callFilterTableContent();
});
}
hookupSearchTextFilter() {
this.hookupFilter(flagSearch);
}
/*
getAndLoadFilteredTableContent = () => {
this.callFilterTableContent()
@@ -225,12 +254,13 @@ export default class TableBasePage extends BasePage {
this.initialiseRowNew(tbody, row);
tbody.appendChild(row);
this.hookupTableMain();
this.postInitialiseRowNewCallback(tbody);
}
initialiseRowNew(tbody, row) {
if (this.constructor === TableBasePage) {
throw new Error("Subclass of TableBasePage must implement method initialiseRowNew().");
}
row.classList.remove(flagRowNew);
// row.classList.remove(flagRowNew);
}
hookupTableMain() {
if (this.constructor === TableBasePage) {
@@ -253,6 +283,11 @@ export default class TableBasePage extends BasePage {
});
_rowBlank.setAttribute(this.constructor.attrIdRowObject, -1 - countRows);
}
postInitialiseRowNewCallback(tbody) {
if (this.constructor === TableBasePage) {
throw new Error("Subclass of TableBasePage must implement method postInitialiseRowNewCallback(tbody).");
}
}
initialiseSliderDisplayOrderRowNew(tbody, row) {
// let tdSelector = ':scope > tr > td.' + flagDisplayOrder;
// let tbody = document.querySelector('table' + (Validation.isEmpty(flagTable) ? '' : '.' + flagTable) + ' > tbody');
@@ -518,8 +553,100 @@ export default class TableBasePage extends BasePage {
this.toggleColumnHasClassnameFlag(flagColumn, isCollapsed, flagCollapsed);
}
hookupFieldsCommandCategory() {
this.hookupTableCellDdlPreviews(
idTableMain + ' td.' + flagCommandCategory
, Utils.getListFromDict(filterCommandCategories)
, (cellSelector) => { this.hookupCommandCategoryDdls(cellSelector); }
);
}
hookupCommandCategoryDdls(ddlSelector) {
this.hookupChangeHandlerTableCells(ddlSelector, (event, element) => { this.handleChangeCommandCategoryDdl(event, element); });
}
handleChangeCommandCategoryDdl(event, ddlCategory) {
let idCommandCategoryOld = DOM.getElementAttributeValueCurrent(ddlCategory);
this.handleChangeNestedElementCellTable(event, ddlCategory);
let idCommandCategoryNew = DOM.getElementAttributeValueCurrent(ddlCategory);
if (idCommandCategoryOld == idCommandCategoryNew) return;
let row = DOM.getRowFromElement(ddlCategory);
let tdCommand = row.querySelector('td.' + flagCommand);
tdCommand.dispatchEvent(new Event('click'));
let ddlCommand = row.querySelector('td.' + flagCommand + ' select');
ddlCommand.innerHTML = '';
ddlCommand.appendChild(DOM.createOption(null));
let optionJson, option;
Utils.getListFromDict(filterCommands).forEach((command) => {
if (idCommandCategoryNew != '0' && command[attrIdCommandCategory] != idCommandCategoryNew) return;
optionJson = BusinessObjects.getOptionJsonFromObjectJson(command);
option = DOM.createOption(optionJson);
ddlCommand.appendChild(option);
});
this.handleChangeNestedElementCellTable(event, ddlCommand);
}
hookupFieldsCommand() {
this.hookupTableCellDdlPreviews(idTableMain + ' td.' + flagCommand, Utils.getListFromDict(filterCommands));
let cellSelector = idTableMain + ' td.' + flagCommand;
this.hookupEventHandler("click", cellSelector, (event, td) => {
let parentTr = td.parentElement;
let tdCommandCategory = parentTr.querySelector('td.' + flagCommandCategory);
let idCommandCategoryRow = DOM.getElementAttributeValueCurrent(tdCommandCategory);
let idCommandCategoryFilter = this.getIdCommandCategoryFilter();
let filterCommandList = Utils.getListFromDict(filterCommands);
let commandsInCategory = filterCommandList.filter(command =>
(
command[attrIdCommandCategory] == idCommandCategoryRow
)
&& (
command[attrIdCommandCategory] == idCommandCategoryFilter
|| idCommandCategoryFilter == 0
)
);
console.log({ tdCommandCategory, idCommandCategoryRow, filterCommandList, commandsInCategory });
console.log(filterCommandList);
this.handleClickTableCellDdlPreview(
event
, td
, commandsInCategory
, cellSelector
, (cellSelector) => { this.hookupTableCellDdls(
cellSelector
, (event, element) => { this.handleChangeNestedElementCellTable(event, element); }
); }
);
});
this.hookupTableCellDdls(cellSelector + ' select');
}
getIdCommandCategoryFilter() {
let formFilters = this.getFormFilters();
let commandCategoryFilter = formFilters.querySelector('#' + attrIdCommandCategory);
let commandFilter = formFilters.querySelector('#' + attrIdCommand);
let idCommandCategory = 0;
let valueCurrentCommandCategoryFilter = DOM.getElementAttributeValueCurrent(commandCategoryFilter);
console.log({ valueCurrentCommandCategoryFilter });
if (valueCurrentCommandCategoryFilter == "") {
let valueCurrentCommandFilter = DOM.getElementAttributeValueCurrent(commandFilter);
if (valueCurrentCommandFilter != "") {
let command = filterCommands[valueCurrentCommandFilter];
idCommandCategory = command[attrIdCommandCategory];
}
} else {
idCommandCategory = Number(valueCurrentCommandCategoryFilter);
}
return idCommandCategory;
}
getHasCommandCategoryFilter() {
let idCommandCategoryFilter = this.getIdCommandCategoryFilter();
return !(Validation.isEmpty(idCommandCategoryFilter) || idCommandCategoryFilter == 0);
}
getIdCommandFilter() {
let formFilters = this.getFormFilters();
let commandFilter = formFilters.querySelector('#' + attrIdCommand);
let valueCurrentCommandFilter = DOM.getElementAttributeValueCurrent(commandFilter);
let idCommand = Number(valueCurrentCommandFilter);
return idCommand;
}
getHasCommandFilter() {
let idCommandFilter = this.getIdCommandFilter();
return !(Validation.isEmpty(idCommandFilter) || idCommandFilter == 0);
}
hookupFieldsDog() {
this.hookupTableCellDdlPreviews(idTableMain + ' td.' + flagDog, Utils.getListFromDict(filterDogs));

View File

@@ -25,17 +25,21 @@ export default class PageDogDogCommandLinks extends TableBasePage {
hookupFilters() {
this.sharedHookupFilters();
this.hookupFilterDog();
this.hookupFilterCommandCategory();
this.hookupFilterCommand();
this.hookupFilterActive();
}
hookupFilterDog() {
this.hookupFilter(attrIdDog);
/*, (event, filterDog) => {
}
hookupFilterCommandCategory() {
this.hookupFilter(attrIdCommandCategory, (event, filterCommandCategory) => {
// loadDogCommandLinks();
// let wasDirtyFilter = filterDog.classList.contains(flagDirty);
PageDogDogCommandLinks.isDirtyFilter(filterDog);
let isDirtyFilter = filterDog.classList.contains(flagDirty);
let idDog = DOM.getElementValueCurrent(filterDog);
let commands = dogs[idDog];
// let wasDirtyFilter = filterCommandCategory.classList.contains(flagDirty);
PageDogDogCommandLinks.isDirtyFilter(filterCommandCategory);
let isDirtyFilter = filterCommandCategory.classList.contains(flagDirty);
let idCommandCategory = DOM.getElementValueCurrent(filterCommandCategory);
let commands = filterCommands.filter(command => command[attrIdCommandCategory] == idCommandCategory);
let filterCommand = document.querySelector(idFormFilters + ' .' + flagCommand);
let idCommandPrevious = filterCommand.getAttribute(attrValuePrevious);
filterCommand.innerHTML = '';
@@ -48,8 +52,8 @@ export default class PageDogDogCommandLinks extends TableBasePage {
filterCommand.appendChild(option);
});
filterCommand.dispatchEvent(new Event('change'));
return isDirtyFilter;
});
*/
}
hookupFilterCommand() {
this.hookupFilter(attrIdCommand);
@@ -119,7 +123,7 @@ export default class PageDogDogCommandLinks extends TableBasePage {
let tdCommand = row.querySelector('td.' + flagCommand);
let inputHandSignalDescription = row.querySelector('td.' + flagHandSignalDescription + ' textarea');
let inputNotes = row.querySelector('td.' + flagNotes + ' textarea');
let buttonActive = row.querySelector(':scope > td.' + flagActive + ' button');
let buttonActive = row.querySelector('td.' + flagActive + ' .' + flagActive);
let jsonRow = {};
jsonRow[attrIdDogCommandLink] = row.getAttribute(attrIdDogCommandLink);
@@ -131,40 +135,69 @@ export default class PageDogDogCommandLinks extends TableBasePage {
return jsonRow;
}
initialiseRowNew(tbody, row) {
this.initialiseRowNewDdlsDogAndCommand(row);
/*
this.initialiseRowNewDdlsDog(row);
this.initialiseRowNewDdlsCommandCategory(row);
this.initialiseRowNewDdlsCommand(row);
this.initialiseRowNewDdlsDogAndCommand(row);
let checkboxIsSubscription = row.querySelector('td.' + flagIsSubscription + ' input');
let checkboxDoesExpireFasterOnceUnsealed = row.querySelector('td.' + flagDoesExpireFasterOnceUnsealed + ' input');
this.handleChangeCheckboxDoesExpireFasterOnceUnsealed(null, checkboxDoesExpireFasterOnceUnsealed);
this.handleChangeCheckboxIsSubscription(null, checkboxIsSubscription);
*/
}
initialiseRowNewDdlsDogAndCommand(row) {
initialiseRowNewDdlsDog(row) {
let ddlDogFilter = document.querySelector(idFormFilters + ' #' + attrIdDog);
let idDogFilter = DOM.getElementValueCurrent(ddlDogFilter);
let hasDogFilter = !(Validation.isEmpty(idDogFilter) || idDogFilter == '0');
let ddlCommandFilter = document.querySelector(idFormFilters + ' #' + attrIdCommand);
let idCommandFilter = DOM.getElementValueCurrent(ddlCommandFilter);
let hasCommandFilter = !(Validation.isEmpty(idCommandFilter) || idCommandFilter == '0');
if (_verbose) {
console.log("initialiseRowNew: ", row);
console.log({ ddlDogFilter, idDogFilter, hasDogFilter });
}
if (!hasDogFilter) return;
let ddlDog = row.querySelector('td.' + flagDog + ' select');
DOM.setElementValuesCurrentAndPrevious(ddlDog, idDogFilter);
this.handleChangeDogDdl(null, ddlDog);
}
initialiseRowNewDdlsCommandCategory(row) {
let idCommandCategoryFilter = this.getIdCommandCategoryFilter();
let hasCommandCategoryFilter = this.getHasCommandCategoryFilter();
if (_verbose) {
console.log("initialiseRowNew: ", row);
console.log({ddlDogFilter, idDogFilter, hasDogFilter, idCommandCategoryFilter, hasCommandCategoryFilter});
}
if (!hasCommandCategoryFilter) return;
let ddlCommandCategory = row.querySelector('td.' + flagCommandCategory + ' select');
DOM.setElementValuesCurrentAndPrevious(ddlCommandCategory, idCommandCategoryFilter);
}
initialiseRowNewDdlsCommand(row) {
let idCommandFilter = this.getIdCommandFilter();
let hasCommandFilter = this.getHasCommandFilter();
if (_verbose) {
console.log("initialiseRowNew: ", row);
console.log({ddlDogFilter, idDogFilter, hasDogFilter, ddlCommandFilter, idCommandFilter, hasCommandFilter});
}
if (!hasDogFilter && !hasCommandFilter) return;
if (hasDogFilter) {
let ddlDog = row.querySelector('td.' + flagDog + ' select');
DOM.setElementValuesCurrentAndPrevious(ddlDog, idDogFilter);
this.handleChangeDogDdl(null, ddlDog);
}
if (hasCommandFilter) {
let ddlCommand = row.querySelector('td.' + flagCommand + ' select');
DOM.setElementValuesCurrentAndPrevious(ddlCommand, idCommandFilter);
}
if (!hasCommandFilter) return;
let ddlCommand = row.querySelector('td.' + flagCommand + ' select');
DOM.setElementValuesCurrentAndPrevious(ddlCommand, idCommandFilter);
}
postInitialiseRowNewCallback(tbody) {
let newRows = tbody.querySelectorAll('tr.' + flagRowNew);
let newestRow = newRows[newRows.length - 1];
let clickableElementsSelector = [
'td.' + flagDog + ' div.' + flagDog
, ',td.' + flagCommandCategory + ' div.' + flagCommandCategory
, ',td.' + flagCommand + ' div.' + flagCommand
].join('');
newestRow.querySelectorAll(clickableElementsSelector).forEach((clickableElement) => {
clickableElement.click();
});
}
hookupTableMain() {
super.hookupTableMain();
this.hookupFieldsDog();
this.hookupFieldsCommandCategory();
this.hookupFieldsCommand();
this.hookupTextareasHandSignalDescription();
this.hookupTextareasNotes();