/* eslint-disable @typescript-eslint/no-non-null-assertion, unicorn/prefer-module */ import type * as globalTypes from '../types/globalTypes' import type * as recordTypes from '../types/recordTypes' import type { cityssmGlobal } from '@cityssm/bulma-webapp-js/src/types' import type { BulmaJS } from '@cityssm/bulma-js/types' declare const cityssm: cityssmGlobal declare const bulmaJS: BulmaJS ;(() => { const los = exports.los as globalTypes.LOS const containerElement = document.querySelector( '#container--lotTypes' ) as HTMLElement let lotTypes: recordTypes.LotType[] = exports.lotTypes delete exports.lotTypes const expandedLotTypes = new Set() function toggleLotTypeFields(clickEvent: Event) { const toggleButtonElement = clickEvent.currentTarget as HTMLButtonElement const lotTypeElement = toggleButtonElement.closest( '.container--lotType' ) as HTMLElement const lotTypeId = Number.parseInt(lotTypeElement.dataset.lotTypeId!, 10) if (expandedLotTypes.has(lotTypeId)) { expandedLotTypes.delete(lotTypeId) } else { expandedLotTypes.add(lotTypeId) } toggleButtonElement.innerHTML = expandedLotTypes.has(lotTypeId) ? '' : '' const panelBlockElements = lotTypeElement.querySelectorAll('.panel-block') for (const panelBlockElement of panelBlockElements) { panelBlockElement.classList.toggle('is-hidden') } } function lotTypeResponseHandler(responseJSON: { success: boolean errorMessage?: string lotTypes?: recordTypes.LotType[] }) { if (responseJSON.success) { lotTypes = responseJSON.lotTypes! renderLotTypes() } else { bulmaJS.alert({ title: `Error Updating ${exports.aliases.lot} Type`, message: responseJSON.errorMessage || '', contextualColorName: 'danger' }) } } function deleteLotType(clickEvent: Event) { const lotTypeId = Number.parseInt( ( (clickEvent.currentTarget as HTMLElement).closest( '.container--lotType' ) as HTMLElement ).dataset.lotTypeId!, 10 ) function doDelete() { cityssm.postJSON( los.urlPrefix + '/admin/doDeleteLotType', { lotTypeId }, lotTypeResponseHandler ) } bulmaJS.confirm({ title: `Delete ${exports.aliases.lot} Type`, message: `Are you sure you want to delete this ${exports.aliases.lot.toLowerCase()} type?`, contextualColorName: 'warning', okButton: { text: `Yes, Delete ${exports.aliases.lot} Type`, callbackFunction: doDelete } }) } function openEditLotType(clickEvent: Event) { const lotTypeId = Number.parseInt( ( (clickEvent.currentTarget as HTMLElement).closest( '.container--lotType' ) as HTMLElement ).dataset.lotTypeId!, 10 ) const lotType = lotTypes.find((currentLotType) => { return lotTypeId === currentLotType.lotTypeId })! let editCloseModalFunction: () => void const doEdit = (submitEvent: SubmitEvent) => { submitEvent.preventDefault() cityssm.postJSON( los.urlPrefix + '/admin/doUpdateLotType', submitEvent.currentTarget, (responseJSON: { success: boolean errorMessage?: string occupancyTypes?: recordTypes.OccupancyType[] }) => { lotTypeResponseHandler(responseJSON) if (responseJSON.success) { editCloseModalFunction() } } ) } cityssm.openHtmlModal('adminLotTypes-editLotType', { onshow(modalElement) { los.populateAliases(modalElement) ;( modalElement.querySelector( '#lotTypeEdit--lotTypeId' ) as HTMLInputElement ).value = lotTypeId.toString() ;( modalElement.querySelector( '#lotTypeEdit--lotType' ) as HTMLInputElement ).value = lotType.lotType }, onshown(modalElement, closeModalFunction) { editCloseModalFunction = closeModalFunction ;( modalElement.querySelector( '#lotTypeEdit--lotType' ) as HTMLInputElement ).focus() modalElement.querySelector('form')!.addEventListener('submit', doEdit) bulmaJS.toggleHtmlClipped() }, onremoved() { bulmaJS.toggleHtmlClipped() } }) } function openAddLotTypeField(clickEvent: Event) { const lotTypeId = Number.parseInt( ( (clickEvent.currentTarget as HTMLElement).closest( '.container--lotType' ) as HTMLElement ).dataset.lotTypeId!, 10 ) let addCloseModalFunction: () => void const doAdd = (submitEvent: SubmitEvent) => { submitEvent.preventDefault() cityssm.postJSON( los.urlPrefix + '/admin/doAddLotTypeField', submitEvent.currentTarget, (responseJSON: { success: boolean errorMessage?: string lotTypes?: recordTypes.LotType[] lotTypeFieldId?: number }) => { expandedLotTypes.add(lotTypeId) lotTypeResponseHandler(responseJSON) if (responseJSON.success) { addCloseModalFunction() openEditLotTypeField(lotTypeId, responseJSON.lotTypeFieldId!) } } ) } cityssm.openHtmlModal('adminLotTypes-addLotTypeField', { onshow(modalElement) { los.populateAliases(modalElement) if (lotTypeId) { ;( modalElement.querySelector( '#lotTypeFieldAdd--lotTypeId' ) as HTMLInputElement ).value = lotTypeId.toString() } }, onshown(modalElement, closeModalFunction) { addCloseModalFunction = closeModalFunction ;( modalElement.querySelector( '#lotTypeFieldAdd--lotTypeField' ) as HTMLInputElement ).focus() modalElement.querySelector('form')!.addEventListener('submit', doAdd) bulmaJS.toggleHtmlClipped() }, onremoved() { bulmaJS.toggleHtmlClipped() } }) } function moveLotType(clickEvent: MouseEvent) { const buttonElement = clickEvent.currentTarget as HTMLButtonElement const lotTypeId = ( buttonElement.closest('.container--lotType') as HTMLElement ).dataset.lotTypeId cityssm.postJSON( los.urlPrefix + '/admin/' + (buttonElement.dataset.direction === 'up' ? 'doMoveLotTypeUp' : 'doMoveLotTypeDown'), { lotTypeId, moveToEnd: clickEvent.shiftKey ? '1' : '0' }, lotTypeResponseHandler ) } function openEditLotTypeField(lotTypeId: number, lotTypeFieldId: number) { const lotType = lotTypes.find((currentLotType) => { return currentLotType.lotTypeId === lotTypeId })! const lotTypeField = lotType.lotTypeFields!.find((currentLotTypeField) => { return currentLotTypeField.lotTypeFieldId === lotTypeFieldId })! let minimumLengthElement: HTMLInputElement let maximumLengthElement: HTMLInputElement let patternElement: HTMLInputElement let lotTypeFieldValuesElement: HTMLTextAreaElement let editCloseModalFunction: () => void function updateMaximumLengthMin() { maximumLengthElement.min = minimumLengthElement.value } function toggleInputFields() { if (lotTypeFieldValuesElement.value === '') { minimumLengthElement.disabled = false maximumLengthElement.disabled = false patternElement.disabled = false } else { minimumLengthElement.disabled = true maximumLengthElement.disabled = true patternElement.disabled = true } } function doUpdate(submitEvent: SubmitEvent) { submitEvent.preventDefault() cityssm.postJSON( los.urlPrefix + '/admin/doUpdateLotTypeField', submitEvent.currentTarget, (responseJSON: { success: boolean errorMessage?: string occupancyTypes?: recordTypes.OccupancyType[] }) => { lotTypeResponseHandler(responseJSON) if (responseJSON.success) { editCloseModalFunction() } } ) } function doDelete() { cityssm.postJSON( los.urlPrefix + '/admin/doDeleteLotTypeField', { lotTypeFieldId }, (responseJSON: { success: boolean errorMessage?: string lotTypes?: recordTypes.LotType[] }) => { lotTypeResponseHandler(responseJSON) if (responseJSON.success) { editCloseModalFunction() } } ) } function confirmDoDelete() { bulmaJS.confirm({ title: 'Delete Field', message: 'Are you sure you want to delete this field? Note that historical records that make use of this field will not be affected.', contextualColorName: 'warning', okButton: { text: 'Yes, Delete Field', callbackFunction: doDelete } }) } cityssm.openHtmlModal('adminLotTypes-editLotTypeField', { onshow(modalElement) { los.populateAliases(modalElement) ;( modalElement.querySelector( '#lotTypeFieldEdit--lotTypeFieldId' ) as HTMLInputElement ).value = lotTypeField.lotTypeFieldId.toString() ;( modalElement.querySelector( '#lotTypeFieldEdit--lotTypeField' ) as HTMLInputElement ).value = lotTypeField.lotTypeField! ;( modalElement.querySelector( '#lotTypeFieldEdit--isRequired' ) as HTMLSelectElement ).value = lotTypeField.isRequired ? '1' : '0' minimumLengthElement = modalElement.querySelector( '#lotTypeFieldEdit--minimumLength' ) as HTMLInputElement minimumLengthElement.value = lotTypeField.minimumLength!.toString() maximumLengthElement = modalElement.querySelector( '#lotTypeFieldEdit--maximumLength' ) as HTMLInputElement maximumLengthElement.value = lotTypeField.maximumLength!.toString() patternElement = modalElement.querySelector( '#lotTypeFieldEdit--pattern' ) as HTMLInputElement patternElement.value = lotTypeField.pattern! lotTypeFieldValuesElement = modalElement.querySelector( '#lotTypeFieldEdit--lotTypeFieldValues' ) as HTMLTextAreaElement lotTypeFieldValuesElement.value = lotTypeField.lotTypeFieldValues! toggleInputFields() }, onshown(modalElement, closeModalFunction) { editCloseModalFunction = closeModalFunction bulmaJS.init(modalElement) bulmaJS.toggleHtmlClipped() cityssm.enableNavBlocker() modalElement.querySelector('form')!.addEventListener('submit', doUpdate) minimumLengthElement.addEventListener('keyup', updateMaximumLengthMin) updateMaximumLengthMin() lotTypeFieldValuesElement.addEventListener('keyup', toggleInputFields) modalElement .querySelector('#button--deleteLotTypeField')! .addEventListener('click', confirmDoDelete) }, onremoved() { bulmaJS.toggleHtmlClipped() cityssm.disableNavBlocker() } }) } function openEditLotTypeFieldByClick(clickEvent: Event) { clickEvent.preventDefault() const lotTypeFieldId = Number.parseInt( ( (clickEvent.currentTarget as HTMLElement).closest( '.container--lotTypeField' ) as HTMLElement ).dataset.lotTypeFieldId!, 10 ) const lotTypeId = Number.parseInt( ( (clickEvent.currentTarget as HTMLElement).closest( '.container--lotType' ) as HTMLElement ).dataset.lotTypeId!, 10 ) openEditLotTypeField(lotTypeId, lotTypeFieldId) } function moveLotTypeField(clickEvent: MouseEvent) { const buttonElement = clickEvent.currentTarget as HTMLButtonElement const lotTypeFieldId = ( buttonElement.closest('.container--lotTypeField') as HTMLElement ).dataset.lotTypeFieldId cityssm.postJSON( los.urlPrefix + '/admin/' + (buttonElement.dataset.direction === 'up' ? 'doMoveLotTypeFieldUp' : 'doMoveLotTypeFieldDown'), { lotTypeFieldId, moveToEnd: clickEvent.shiftKey ? '1' : '0' }, lotTypeResponseHandler ) } function renderLotTypeFields( panelElement: HTMLElement, lotTypeId: number, lotTypeFields: recordTypes.LotTypeField[] ) { if (lotTypeFields.length === 0) { panelElement.insertAdjacentHTML( 'beforeend', '
' + '
' + '

There are no additional fields.

' + '
' + '
' ) } else { for (const lotTypeField of lotTypeFields) { const panelBlockElement = document.createElement('div') panelBlockElement.className = 'panel-block is-block container--lotTypeField' if (!expandedLotTypes.has(lotTypeId)) { panelBlockElement.classList.add('is-hidden') } panelBlockElement.dataset.lotTypeFieldId = lotTypeField.lotTypeFieldId.toString() panelBlockElement.innerHTML = '
' + '' + '
' + ('
' + los.getMoveUpDownButtonFieldHTML( 'button--moveLotTypeFieldUp', 'button--moveLotTypeFieldDown' ) + '
') + '
' + '
' panelBlockElement .querySelector('.button--editLotTypeField')! .addEventListener('click', openEditLotTypeFieldByClick) ;( panelBlockElement.querySelector( '.button--moveLotTypeFieldUp' ) as HTMLButtonElement ).addEventListener('click', moveLotTypeField) ;( panelBlockElement.querySelector( '.button--moveLotTypeFieldDown' ) as HTMLButtonElement ).addEventListener('click', moveLotTypeField) panelElement.append(panelBlockElement) } } } function renderLotTypes() { containerElement.innerHTML = '' if (lotTypes.length === 0) { containerElement.insertAdjacentHTML( 'afterbegin', `
There are no active ${los.escapedAliases.lot} types.

` ) return } for (const lotType of lotTypes) { const lotTypeContainer = document.createElement('div') lotTypeContainer.className = 'panel container--lotType' lotTypeContainer.dataset.lotTypeId = lotType.lotTypeId.toString() lotTypeContainer.innerHTML = '
' + '
' + ('
' + '
' + '' + '
' + '
' + '

' + cityssm.escapeHTML(lotType.lotType) + '

' + '
' + '
') + ('
' + ('
' + '' + '
') + ('
' + '' + '
') + ('
' + '' + '
') + ('
' + los.getMoveUpDownButtonFieldHTML( 'button--moveLotTypeUp', 'button--moveLotTypeDown' ) + '
') + '
') + '
' + '
' renderLotTypeFields( lotTypeContainer, lotType.lotTypeId, lotType.lotTypeFields! ) lotTypeContainer .querySelector('.button--toggleLotTypeFields')! .addEventListener('click', toggleLotTypeFields) lotTypeContainer .querySelector('.button--deleteLotType')! .addEventListener('click', deleteLotType) lotTypeContainer .querySelector('.button--editLotType')! .addEventListener('click', openEditLotType) lotTypeContainer .querySelector('.button--addLotTypeField')! .addEventListener('click', openAddLotTypeField) ;( lotTypeContainer.querySelector( '.button--moveLotTypeUp' ) as HTMLButtonElement ).addEventListener('click', moveLotType) ;( lotTypeContainer.querySelector( '.button--moveLotTypeDown' ) as HTMLButtonElement ).addEventListener('click', moveLotType) containerElement.append(lotTypeContainer) } } document .querySelector('#button--addLotType')! .addEventListener('click', () => { let addCloseModalFunction: () => void function doAdd(submitEvent: SubmitEvent): void { submitEvent.preventDefault() cityssm.postJSON( los.urlPrefix + '/admin/doAddLotType', submitEvent.currentTarget, (responseJSON: { success: boolean errorMessage?: string lotTypes?: recordTypes.LotType[] }) => { if (responseJSON.success) { addCloseModalFunction() lotTypes = responseJSON.lotTypes! renderLotTypes() } else { bulmaJS.alert({ title: `Error Adding ${los.escapedAliases.Lot} Type`, message: responseJSON.errorMessage || '', contextualColorName: 'danger' }) } } ) } cityssm.openHtmlModal('adminLotTypes-addLotType', { onshow(modalElement) { los.populateAliases(modalElement) }, onshown(modalElement, closeModalFunction) { addCloseModalFunction = closeModalFunction ;( modalElement.querySelector( '#lotTypeAdd--lotType' ) as HTMLInputElement ).focus() modalElement.querySelector('form')!.addEventListener('submit', doAdd) bulmaJS.toggleHtmlClipped() }, onremoved() { bulmaJS.toggleHtmlClipped() } }) }) renderLotTypes() })()