typo3-typescript-sources 14.3.8 → 14.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/sync-and-publish.yml +240 -191
- package/.last-synced-tag +1 -1
- package/README.md +13 -5
- package/adminpanel/admin-panel.ts +22 -22
- package/adminpanel/modules/cache.ts +3 -3
- package/backend/action-dispatcher.ts +8 -3
- package/backend/bookmark/bookmark-store.ts +5 -5
- package/backend/clipboard-panel.ts +2 -2
- package/backend/code-editor/element/code-mirror-element.ts +1 -1
- package/backend/code-editor/language/typoscript.ts +3 -3
- package/backend/code-editor/stream-parser/typoscript.ts +2 -2
- package/backend/color-picker.ts +2 -2
- package/backend/column-selector-button.ts +6 -6
- package/backend/context-help.ts +3 -3
- package/backend/context-menu.ts +8 -3
- package/backend/drag-tooltip.ts +9 -4
- package/backend/drag-uploader.ts +4 -4
- package/backend/element/draggable-resizable-element.ts +18 -12
- package/backend/element/icon-element.ts +2 -2
- package/backend/element/thumbnail-element.ts +2 -2
- package/backend/element-browser.ts +1 -1
- package/backend/event/consumer-scope.ts +2 -2
- package/backend/event/interaction-request-assignment.ts +1 -1
- package/backend/event/interaction-request-map.ts +3 -3
- package/backend/form-engine/container/flex-form-container-container.ts +2 -2
- package/backend/form-engine/container/flex-form-section-container.ts +1 -1
- package/backend/form-engine/container/inline-control-container.ts +14 -14
- package/backend/form-engine/element/abstract-sortable-select-items.ts +3 -3
- package/backend/form-engine/element/color-element.ts +1 -1
- package/backend/form-engine/element/datetime-element.ts +1 -1
- package/backend/form-engine/element/extra/char-counter.ts +2 -2
- package/backend/form-engine/element/extra/select-box-filter.ts +1 -1
- package/backend/form-engine/element/mfa-info-element.ts +2 -2
- package/backend/form-engine/element/online-media-form-element.ts +5 -1
- package/backend/form-engine/element/select-multiple-side-by-side-element.ts +2 -2
- package/backend/form-engine/element/select-tree.ts +3 -3
- package/backend/form-engine/element/slug-element.ts +7 -7
- package/backend/form-engine/element/suggest/result-container.ts +1 -1
- package/backend/form-engine/element/table-wizard-element.ts +4 -4
- package/backend/form-engine/inline-relation/ajax-dispatcher.ts +3 -3
- package/backend/form-engine-validation.ts +11 -5
- package/backend/form-engine.ts +11 -11
- package/backend/global-event-handler.ts +1 -1
- package/backend/hotkeys/hotkey-struct.ts +1 -1
- package/backend/hotkeys.ts +3 -3
- package/backend/image-manipulation.ts +19 -19
- package/backend/layout-module/drag-drop.ts +4 -4
- package/backend/layout-module/paste.ts +1 -1
- package/backend/live-search/element/result/item/action/action-container.ts +1 -1
- package/backend/live-search/element/result/item/item-container.ts +4 -4
- package/backend/live-search/element/result/result-container.ts +5 -0
- package/backend/live-search/element/result/result-pagination.ts +1 -1
- package/backend/live-search/live-search.ts +2 -2
- package/backend/localization/label-provider.ts +4 -4
- package/backend/localization/localization-wizard.ts +4 -4
- package/backend/localization/steps/content-record-selection-step.ts +8 -8
- package/backend/localization/steps/handler-selection-step.ts +4 -4
- package/backend/localization/steps/mode-step.ts +4 -4
- package/backend/localization/steps/source-language-step.ts +4 -4
- package/backend/localization/steps/target-language-step.ts +4 -4
- package/backend/login.ts +2 -2
- package/backend/module/iframe.ts +10 -0
- package/backend/module/router.ts +10 -0
- package/backend/module-menu.ts +3 -3
- package/backend/multi-record-selection-action.ts +1 -1
- package/backend/multi-record-selection-delete-action.ts +1 -1
- package/backend/multi-record-selection.ts +14 -14
- package/backend/multi-step-wizard.ts +9 -2
- package/backend/new-multiple-pages.ts +2 -2
- package/backend/new-record-wizard.ts +15 -15
- package/backend/page-wizard/page-wizard.ts +2 -2
- package/backend/page-wizard/steps/doktype-step.ts +5 -5
- package/backend/pagetsconfig/pagetsconfig-includes.ts +1 -1
- package/backend/popover.ts +5 -5
- package/backend/record-download-button.ts +1 -1
- package/backend/recordlist.ts +6 -6
- package/backend/security/element/csp-reports.ts +8 -8
- package/backend/setup-module.ts +2 -2
- package/backend/sortable-table.ts +10 -4
- package/backend/storage/abstract-client-storage.ts +2 -2
- package/backend/storage/module-state-storage.ts +2 -2
- package/backend/tests/backend/utility/dom-helper-test.ts +2 -2
- package/backend/tests/form-engine/element/extra/select-box-filter-test.ts +3 -3
- package/backend/tests/form-engine-validation-test.ts +1 -1
- package/backend/tests/tree/tree-test.ts +41 -0
- package/backend/tree/file-storage-browser.ts +1 -1
- package/backend/tree/file-storage-tree-container.ts +4 -4
- package/backend/tree/page-browser.ts +1 -1
- package/backend/tree/page-position-select.ts +1 -1
- package/backend/tree/page-tree-element.ts +1 -1
- package/backend/tree/page-tree.ts +7 -1
- package/backend/tree/tree-module-state.ts +5 -5
- package/backend/tree/tree.ts +15 -8
- package/backend/user-pass-login.ts +2 -2
- package/backend/utility/collapse-state-persister.ts +1 -1
- package/backend/utility/collapse-state-search.ts +6 -6
- package/backend/utility/dom-helper.ts +3 -3
- package/backend/utility.ts +6 -6
- package/backend/viewport/content-navigation.ts +5 -0
- package/backend/viewport/navigation-container.ts +1 -1
- package/backend/viewport/toolbar.ts +3 -3
- package/backend/window-manager.ts +2 -2
- package/backend/wizard/events/auto-advance-event.ts +6 -0
- package/backend/wizard/events/before-next-step-event.ts +6 -0
- package/backend/wizard/events/step-summary-event.ts +6 -0
- package/backend/wizard/move-content-element.ts +1 -1
- package/backend/wizard/wizard.ts +8 -10
- package/belog/backend-log.ts +2 -2
- package/beuser/permissions.ts +2 -2
- package/core/ajax/ajax-response.ts +1 -1
- package/core/ajax/input-transformer.ts +1 -1
- package/core/event/debounce-event.ts +4 -4
- package/core/event/event-interface.ts +3 -3
- package/core/event/regular-event.ts +7 -7
- package/core/event/request-animation-frame-event.ts +4 -4
- package/core/event/throttle-event.ts +4 -4
- package/core/java-script-item-processor.ts +6 -0
- package/core/referrer-refresh.ts +2 -2
- package/core/security-utility.ts +1 -1
- package/dashboard/dashboard-wizard.ts +2 -2
- package/dashboard/dashboard.ts +5 -5
- package/dashboard/wizard/steps/preset-step.ts +3 -3
- package/extensionmanager/main.ts +7 -7
- package/filelist/browse-files.ts +1 -1
- package/filelist/browse-folders.ts +2 -2
- package/filelist/file-list-dragdrop.ts +5 -5
- package/filelist/file-list-transfer-handler.ts +2 -2
- package/filelist/file-list.ts +5 -5
- package/form/backend/form-editor/component/date-editor.ts +4 -0
- package/form/backend/form-editor/component/form-element-selector.ts +4 -0
- package/form/backend/form-editor/inspector-component.ts +6 -6
- package/form/backend/form-editor/mediator.ts +36 -36
- package/form/backend/form-editor/modals-component.ts +1 -1
- package/form/backend/form-editor/stage-component.ts +4 -4
- package/form/backend/form-editor/view-model.ts +7 -7
- package/form/backend/form-manager/view-model.ts +5 -5
- package/form/backend/form-wizard/form-wizard.ts +2 -2
- package/form/backend/form-wizard/steps/storage-step.ts +1 -1
- package/impexp/import-export.ts +1 -1
- package/info/translation-status.ts +2 -2
- package/install/ajax/ajax-queue.ts +1 -1
- package/install/module/abstract-interactable-module.ts +2 -2
- package/install/module/environment/image-processing.ts +4 -4
- package/install/module/environment/mail-test.ts +2 -2
- package/install/module/maintenance/clear-tables.ts +3 -3
- package/install/module/maintenance/clear-typo3temp-files.ts +8 -8
- package/install/module/maintenance/create-admin.ts +3 -3
- package/install/module/maintenance/database-analyzer.ts +9 -7
- package/install/module/maintenance/language-packs.ts +4 -4
- package/install/module/maintenance/reference-index.ts +1 -1
- package/install/module/settings/change-install-tool-password.ts +1 -1
- package/install/module/settings/extension-configuration.ts +5 -5
- package/install/module/settings/features.ts +1 -1
- package/install/module/settings/local-configuration.ts +5 -5
- package/install/module/settings/presets.ts +2 -2
- package/install/module/settings/system-maintainer.ts +1 -1
- package/install/module/upgrade/extension-scanner.ts +5 -5
- package/install/module/upgrade/tca-migrations-check.ts +1 -1
- package/install/module/upgrade/upgrade-docs.ts +16 -16
- package/install/module/upgrade/upgrade-wizards.ts +7 -8
- package/install/renderable/language-packs.ts +8 -2
- package/lowlevel/query-generator.ts +2 -2
- package/package.json +2 -2
- package/redirects/event-handler.ts +6 -0
- package/rte-ckeditor/ckeditor5.ts +7 -3
- package/rte-ckeditor/tests/ckeditor5-test.ts +68 -0
- package/scheduler/form-engine/element/timing-options-element.ts +1 -1
- package/scheduler/scheduler.ts +2 -2
- package/styleguide/checkbox-demo.ts +1 -1
- package/tstemplate/template-analyzer.ts +1 -1
- package/viewpage/main.ts +1 -1
- package/workspaces/backend.ts +5 -5
- package/workspaces/preview.ts +2 -2
- package/workspaces/renderable/record-table.ts +1 -1
- package/workspaces/renderable/send-to-stage-form.ts +1 -1
|
@@ -98,7 +98,7 @@ class FlexFormSectionContainer {
|
|
|
98
98
|
|
|
99
99
|
private readonly updateSorting = (e: Sortable.SortableEvent): void => {
|
|
100
100
|
const actionFields: NodeListOf<HTMLInputElement> = this.container.querySelectorAll(Selectors.actionFieldSelector);
|
|
101
|
-
actionFields.forEach((element
|
|
101
|
+
actionFields.forEach((element, key): void => {
|
|
102
102
|
element.value = key.toString();
|
|
103
103
|
});
|
|
104
104
|
|
|
@@ -161,7 +161,7 @@ class InlineControlContainer extends HTMLElement {
|
|
|
161
161
|
}
|
|
162
162
|
|
|
163
163
|
private static getValuesFromHashMap(hashmap: UniqueDefinitionCollection): Array<any> {
|
|
164
|
-
return Object.keys(hashmap).map((key
|
|
164
|
+
return Object.keys(hashmap).map((key) => hashmap[key]);
|
|
165
165
|
}
|
|
166
166
|
|
|
167
167
|
private static selectOptionValueExists(selectElement: HTMLSelectElement, value: string): boolean {
|
|
@@ -449,10 +449,10 @@ class InlineControlContainer extends HTMLElement {
|
|
|
449
449
|
* @param {string} afterUid
|
|
450
450
|
*/
|
|
451
451
|
private async importRecord(params: Array<any>, afterUid?: string): Promise<void> {
|
|
452
|
-
return this.ajaxDispatcher.send(
|
|
452
|
+
return this.ajaxDispatcher.send<InlineResponseInterface>(
|
|
453
453
|
this.ajaxDispatcher.newRequest(this.ajaxDispatcher.getEndpoint(this.endpoints.create)),
|
|
454
454
|
params,
|
|
455
|
-
).then(async (response
|
|
455
|
+
).then(async (response): Promise<void> => {
|
|
456
456
|
if (this.isBelowMax()) {
|
|
457
457
|
this.createRecord(
|
|
458
458
|
response.compilerInput.uid,
|
|
@@ -553,10 +553,10 @@ class InlineControlContainer extends HTMLElement {
|
|
|
553
553
|
return;
|
|
554
554
|
}
|
|
555
555
|
|
|
556
|
-
this.ajaxDispatcher.send(
|
|
556
|
+
this.ajaxDispatcher.send<InlineResponseInterface>(
|
|
557
557
|
this.ajaxDispatcher.newRequest(this.ajaxDispatcher.getEndpoint(this.endpoints.synchronizelocalize)),
|
|
558
558
|
[this.objectGroup, targetElement.dataset.type],
|
|
559
|
-
).then(async (response
|
|
559
|
+
).then(async (response): Promise<void> => {
|
|
560
560
|
this.recordsContainer.insertAdjacentHTML('beforeend', response.data);
|
|
561
561
|
|
|
562
562
|
const objectIdPrefix = this.objectGroup + Separators.structureSeparator;
|
|
@@ -617,9 +617,9 @@ class InlineControlContainer extends HTMLElement {
|
|
|
617
617
|
|
|
618
618
|
if (!isLoading) {
|
|
619
619
|
const ajaxRequest = this.ajaxDispatcher.newRequest(this.ajaxDispatcher.getEndpoint(this.endpoints.details));
|
|
620
|
-
const request = this.ajaxDispatcher.send(ajaxRequest, [objectId]);
|
|
620
|
+
const request = this.ajaxDispatcher.send<InlineResponseInterface>(ajaxRequest, [objectId]);
|
|
621
621
|
|
|
622
|
-
request.then(async (response
|
|
622
|
+
request.then(async (response): Promise<void> => {
|
|
623
623
|
delete this.requestQueue[objectId];
|
|
624
624
|
delete this.progressQueue[objectId];
|
|
625
625
|
|
|
@@ -762,7 +762,7 @@ class InlineControlContainer extends HTMLElement {
|
|
|
762
762
|
const currentRecordContainer = this.getRecordContainer(objectId);
|
|
763
763
|
const recordUid = currentRecordContainer.dataset.objectUid;
|
|
764
764
|
const recordListContainer = this.recordsContainer;
|
|
765
|
-
const records = Array.from(recordListContainer.children).map((child
|
|
765
|
+
const records = Array.from(recordListContainer.children as HTMLCollectionOf<HTMLElement>).map((child) => child.dataset.objectUid);
|
|
766
766
|
const position = records.indexOf(recordUid);
|
|
767
767
|
let isChanged = false;
|
|
768
768
|
|
|
@@ -795,8 +795,8 @@ class InlineControlContainer extends HTMLElement {
|
|
|
795
795
|
}
|
|
796
796
|
|
|
797
797
|
const recordListContainer = this.recordsContainer;
|
|
798
|
-
const records = Array.from(recordListContainer.querySelectorAll(selector`[data-object-parent-group="${this.objectGroup}"][data-placeholder-record="0"]`))
|
|
799
|
-
.map((child
|
|
798
|
+
const records = Array.from(recordListContainer.querySelectorAll<HTMLElement>(selector`[data-object-parent-group="${this.objectGroup}"][data-placeholder-record="0"]`))
|
|
799
|
+
.map((child) => child.dataset.objectUid);
|
|
800
800
|
|
|
801
801
|
(<HTMLInputElement>formField).value = records.join(',');
|
|
802
802
|
FormEngine.markFieldAsChanged(formField);
|
|
@@ -841,12 +841,12 @@ class InlineControlContainer extends HTMLElement {
|
|
|
841
841
|
* @param {boolean} visible
|
|
842
842
|
*/
|
|
843
843
|
private toggleContainerControls(visible: boolean): void {
|
|
844
|
-
const controlContainer = this.querySelectorAll(
|
|
844
|
+
const controlContainer = this.querySelectorAll<HTMLElement>(
|
|
845
845
|
':scope > ' + Selectors.controlContainer
|
|
846
846
|
);
|
|
847
|
-
controlContainer.forEach((container
|
|
847
|
+
controlContainer.forEach((container): void => {
|
|
848
848
|
const controlContainerButtons = container.querySelectorAll<HTMLButtonElement | HTMLAnchorElement>('button, a');
|
|
849
|
-
controlContainerButtons.forEach((button
|
|
849
|
+
controlContainerButtons.forEach((button): void => {
|
|
850
850
|
button.hidden = !visible;
|
|
851
851
|
});
|
|
852
852
|
});
|
|
@@ -912,7 +912,7 @@ class InlineControlContainer extends HTMLElement {
|
|
|
912
912
|
return;
|
|
913
913
|
}
|
|
914
914
|
|
|
915
|
-
records.forEach((recordUid
|
|
915
|
+
records.forEach((recordUid, index): void => {
|
|
916
916
|
const recordContainer = this.getRecordContainer(objectId + Separators.structureSeparator + recordUid);
|
|
917
917
|
if (recordContainer === null) {
|
|
918
918
|
return;
|
|
@@ -25,7 +25,7 @@ export abstract class AbstractSortableSelectItems {
|
|
|
25
25
|
* @param {HTMLSelectElement} fieldElement
|
|
26
26
|
*/
|
|
27
27
|
private static moveOptionToTop(fieldElement: HTMLSelectElement): void {
|
|
28
|
-
Array.from(fieldElement.querySelectorAll(':checked')).reverse().forEach((optionEl
|
|
28
|
+
Array.from(fieldElement.querySelectorAll<HTMLOptionElement>(':checked')).reverse().forEach((optionEl): void => {
|
|
29
29
|
fieldElement.insertBefore(optionEl, fieldElement.firstElementChild);
|
|
30
30
|
});
|
|
31
31
|
}
|
|
@@ -36,7 +36,7 @@ export abstract class AbstractSortableSelectItems {
|
|
|
36
36
|
* @param {HTMLSelectElement} fieldElement
|
|
37
37
|
*/
|
|
38
38
|
private static moveOptionToBottom(fieldElement: HTMLSelectElement): void {
|
|
39
|
-
fieldElement.querySelectorAll(':checked').forEach((optionEl
|
|
39
|
+
fieldElement.querySelectorAll<HTMLOptionElement>(':checked').forEach((optionEl): void => {
|
|
40
40
|
fieldElement.insertBefore(optionEl, null);
|
|
41
41
|
});
|
|
42
42
|
}
|
|
@@ -85,7 +85,7 @@ export abstract class AbstractSortableSelectItems {
|
|
|
85
85
|
*/
|
|
86
86
|
private static removeOption(fieldElement: HTMLSelectElement, availableFieldElement: HTMLSelectElement): void {
|
|
87
87
|
const previousSelectIndex = fieldElement.selectedIndex;
|
|
88
|
-
fieldElement.querySelectorAll(':checked').forEach((option
|
|
88
|
+
fieldElement.querySelectorAll<HTMLOptionElement>(':checked').forEach((option): void => {
|
|
89
89
|
const originalOption = <HTMLOptionElement>availableFieldElement.querySelector(selector`option[value="${option.value}"]`);
|
|
90
90
|
if (originalOption !== null) {
|
|
91
91
|
originalOption.classList.remove('hidden');
|
|
@@ -72,7 +72,7 @@ class ColorElement extends HTMLElement {
|
|
|
72
72
|
FormEngineValidation.validateField(e.target as HTMLInputElement);
|
|
73
73
|
FormEngine.markFieldAsChanged(e.target as HTMLInputElement);
|
|
74
74
|
|
|
75
|
-
document.querySelectorAll('.module-docheader-bar .btn').forEach((btn
|
|
75
|
+
document.querySelectorAll<HTMLButtonElement>('.module-docheader-bar .btn').forEach((btn): void => {
|
|
76
76
|
btn.classList.remove('disabled');
|
|
77
77
|
btn.disabled = false;
|
|
78
78
|
});
|
|
@@ -56,7 +56,7 @@ class DatetimeElement extends HTMLElement {
|
|
|
56
56
|
FormEngineValidation.validateField(e.target as HTMLInputElement);
|
|
57
57
|
FormEngine.markFieldAsChanged(e.target as HTMLInputElement);
|
|
58
58
|
|
|
59
|
-
document.querySelectorAll('.module-docheader-bar .btn').forEach((btn
|
|
59
|
+
document.querySelectorAll<HTMLButtonElement>('.module-docheader-bar .btn').forEach((btn): void => {
|
|
60
60
|
btn.classList.remove('disabled');
|
|
61
61
|
btn.disabled = false;
|
|
62
62
|
});
|
|
@@ -73,11 +73,11 @@ export class CharCounter extends LitElement {
|
|
|
73
73
|
this.targetElement.removeEventListener('blur', this.onBlur);
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
private readonly onInput = (e:
|
|
76
|
+
private readonly onInput = (e: Event): void => {
|
|
77
77
|
this.determineRemainingCharacters(e.target as HTMLInputElement|HTMLTextAreaElement);
|
|
78
78
|
};
|
|
79
79
|
|
|
80
|
-
private readonly onFocus = (e:
|
|
80
|
+
private readonly onFocus = (e: Event): void => {
|
|
81
81
|
this.determineRemainingCharacters(e.target as HTMLInputElement|HTMLTextAreaElement);
|
|
82
82
|
this.hidden = false;
|
|
83
83
|
};
|
|
@@ -82,7 +82,7 @@ class SelectBoxFilter {
|
|
|
82
82
|
// A plain substring match, no RegExp involved, therefore nothing to escape either
|
|
83
83
|
const foldedFilterText = TextNormalizer.foldCaseAndDiacritics(TextNormalizer.normalizeInvisibleCharacters(filterText));
|
|
84
84
|
|
|
85
|
-
this.availableOptions.forEach((option
|
|
85
|
+
this.availableOptions.forEach((option, index): void => {
|
|
86
86
|
option.hidden = filterText.length > 0 && !this.foldedLabels[index].includes(foldedFilterText);
|
|
87
87
|
SelectBoxFilter.toggleOptGroup(option);
|
|
88
88
|
});
|
|
@@ -71,7 +71,7 @@ class MfaInfoElement {
|
|
|
71
71
|
this.prepareDeactivateRequest(this.deactivteMfaButton);
|
|
72
72
|
}).bindTo(this.deactivteMfaButton);
|
|
73
73
|
|
|
74
|
-
this.deactivteProviderButtons.forEach((buttonElement
|
|
74
|
+
this.deactivteProviderButtons.forEach((buttonElement): void => {
|
|
75
75
|
new RegularEvent('click', (e: Event): void => {
|
|
76
76
|
e.preventDefault();
|
|
77
77
|
this.prepareDeactivateRequest(buttonElement);
|
|
@@ -120,7 +120,7 @@ class MfaInfoElement {
|
|
|
120
120
|
}).then(async (response: AjaxResponse): Promise<void> => {
|
|
121
121
|
const data: Response = await response.resolve();
|
|
122
122
|
if (data.status.length > 0) {
|
|
123
|
-
data.status.forEach((status
|
|
123
|
+
data.status.forEach((status): void => {
|
|
124
124
|
if (data.success) {
|
|
125
125
|
Notification.success(status.title, status.message);
|
|
126
126
|
} else {
|
|
@@ -36,7 +36,7 @@ export class OnlineMediaFormElement extends LitElement {
|
|
|
36
36
|
<div class="form-text">
|
|
37
37
|
${this.allowedExtensionsHelpText}<br>
|
|
38
38
|
<ul class="badge-list">
|
|
39
|
-
${this.allowedExtensions.split(',').map((ext
|
|
39
|
+
${this.allowedExtensions.split(',').map((ext) => html`
|
|
40
40
|
<li><span class="badge badge-secondary">${ext.trim().toLowerCase()}</span></li>
|
|
41
41
|
`)}
|
|
42
42
|
</ul>
|
|
@@ -62,4 +62,8 @@ declare global {
|
|
|
62
62
|
interface HTMLElementTagNameMap {
|
|
63
63
|
'typo3-backend-formengine-online-media-form': OnlineMediaFormElement;
|
|
64
64
|
}
|
|
65
|
+
|
|
66
|
+
interface HTMLElementEventMap {
|
|
67
|
+
'typo3:formengine:online-media-added': CustomEvent<{ file: number }>;
|
|
68
|
+
}
|
|
65
69
|
}
|
|
@@ -52,9 +52,9 @@ class SelectMultipleSideBySideElement extends AbstractSortableSelectItems {
|
|
|
52
52
|
const fieldName = element.dataset.relatedfieldname;
|
|
53
53
|
if (fieldName) {
|
|
54
54
|
const exclusiveValues = Utility.trimExplode(',', element.dataset?.exclusivevalues ?? '');
|
|
55
|
-
const selectedOptions = element.querySelectorAll('option:checked'); // Yep, :checked finds selected options
|
|
55
|
+
const selectedOptions = element.querySelectorAll<HTMLOptionElement>('option:checked'); // Yep, :checked finds selected options
|
|
56
56
|
if (selectedOptions.length > 0) {
|
|
57
|
-
selectedOptions.forEach((optionElement
|
|
57
|
+
selectedOptions.forEach((optionElement): void => {
|
|
58
58
|
FormEngine.setSelectOptionFromExternalSource(
|
|
59
59
|
fieldName,
|
|
60
60
|
optionElement.value,
|
|
@@ -65,7 +65,7 @@ export class SelectTree extends Tree
|
|
|
65
65
|
* Expand all nodes and refresh view
|
|
66
66
|
*/
|
|
67
67
|
public expandAll(): void {
|
|
68
|
-
this.nodes.forEach((node
|
|
68
|
+
this.nodes.forEach((node) => { this.showChildren(node); });
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
/**
|
|
@@ -105,7 +105,7 @@ export class SelectTree extends Tree
|
|
|
105
105
|
// A plain substring match, no RegExp involved, therefore nothing to escape either
|
|
106
106
|
const foldedSearchTerm = SelectTree.fold(searchTerm ?? '');
|
|
107
107
|
|
|
108
|
-
this.nodes.forEach((node
|
|
108
|
+
this.nodes.forEach((node) => {
|
|
109
109
|
// skip the root node in searches
|
|
110
110
|
if (node === firstNode) {
|
|
111
111
|
return;
|
|
@@ -190,7 +190,7 @@ export class SelectTree extends Tree
|
|
|
190
190
|
*/
|
|
191
191
|
private prepareLoadedNodes(evt: CustomEvent): void {
|
|
192
192
|
const nodes = evt.detail.nodes as Array<TreeNodeInterface>;
|
|
193
|
-
evt.detail.nodes = nodes.map((node
|
|
193
|
+
evt.detail.nodes = nodes.map((node) => {
|
|
194
194
|
if (node.selectable === false) {
|
|
195
195
|
this.settings.unselectableElements.push(node.identifier);
|
|
196
196
|
}
|
|
@@ -88,7 +88,7 @@ class SlugElement {
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
private registerEvents(): void {
|
|
91
|
-
const fieldsToListenOnList = Object.values(this.getAvailableFieldsForProposalGeneration()).map((field
|
|
91
|
+
const fieldsToListenOnList = Object.values(this.getAvailableFieldsForProposalGeneration()).map((field) => field.dataset.slugSelector);
|
|
92
92
|
const recreateButton: HTMLButtonElement = this.fullElement.querySelector(Selectors.recreateButton);
|
|
93
93
|
|
|
94
94
|
// Listen on 'listenerFieldNames' for new pages. This is typically the 'title' field
|
|
@@ -158,7 +158,7 @@ class SlugElement {
|
|
|
158
158
|
private sendSlugProposal(mode: ProposalModes): void {
|
|
159
159
|
const input: Record<string, string> = {};
|
|
160
160
|
if (mode === ProposalModes.AUTO || mode === ProposalModes.RECREATE) {
|
|
161
|
-
Object.entries(this.getAvailableFieldsForProposalGeneration()).forEach((entry
|
|
161
|
+
Object.entries(this.getAvailableFieldsForProposalGeneration()).forEach((entry) => {
|
|
162
162
|
input[entry[0]] = entry[1].value;
|
|
163
163
|
});
|
|
164
164
|
if (this.options.includeUidInValues === true) {
|
|
@@ -214,18 +214,18 @@ class SlugElement {
|
|
|
214
214
|
*
|
|
215
215
|
* @return Record<string, string>
|
|
216
216
|
*/
|
|
217
|
-
private getAvailableFieldsForProposalGeneration(): { [key: string]:
|
|
218
|
-
const availableFields: { [key: string]:
|
|
217
|
+
private getAvailableFieldsForProposalGeneration(): { [key: string]: HTMLInputElement|HTMLSelectElement } {
|
|
218
|
+
const availableFields: { [key: string]: HTMLInputElement|HTMLSelectElement } = {};
|
|
219
219
|
for (const [fieldName, selector] of Object.entries(this.fieldsToListenOn)) {
|
|
220
220
|
const selectorCandidates = [
|
|
221
221
|
'[data-formengine-input-name="' + selector + '"]',
|
|
222
222
|
// Also check for fields, which do not point to a hidden input field (e.g. "input type=hidden", readOnly, or select fields)
|
|
223
223
|
'[name="' + selector + '"]'
|
|
224
224
|
];
|
|
225
|
-
let field:
|
|
225
|
+
let field: HTMLInputElement|HTMLSelectElement;
|
|
226
226
|
let usedSelector = '';
|
|
227
|
-
selectorCandidates.some((testSelector
|
|
228
|
-
field = document.querySelector(testSelector)
|
|
227
|
+
selectorCandidates.some((testSelector) => {
|
|
228
|
+
field = document.querySelector<HTMLInputElement|HTMLSelectElement>(testSelector);
|
|
229
229
|
usedSelector = testSelector;
|
|
230
230
|
return field !== null;
|
|
231
231
|
});
|
|
@@ -44,7 +44,7 @@ export class ResultContainer extends LitElement {
|
|
|
44
44
|
if (this.results.length === 0) {
|
|
45
45
|
content = html`<div class="alert alert-info">${labels.get('search.no_records_found')}</div>`;
|
|
46
46
|
} else {
|
|
47
|
-
content = html`${this.results.map((result
|
|
47
|
+
content = html`${this.results.map((result) => this.renderResultItem(result))}`;
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
|
|
@@ -73,7 +73,7 @@ export class TableWizardElement extends LitElement {
|
|
|
73
73
|
const textarea: HTMLTextAreaElement = document.querySelector(this.selectorData);
|
|
74
74
|
const table: string[][] = [];
|
|
75
75
|
|
|
76
|
-
textarea.value.split('\n').forEach((row
|
|
76
|
+
textarea.value.split('\n').forEach((row) => {
|
|
77
77
|
if (row !== '') {
|
|
78
78
|
if(this.enclosure) {
|
|
79
79
|
row = row.replace(new RegExp(this.enclosure, 'g'), '');
|
|
@@ -167,7 +167,7 @@ export class TableWizardElement extends LitElement {
|
|
|
167
167
|
|
|
168
168
|
private renderTemplate(): TemplateResult {
|
|
169
169
|
this.provideMinimalTable();
|
|
170
|
-
const colIndexes = Object.keys(this.firstRow).map((item
|
|
170
|
+
const colIndexes = Object.keys(this.firstRow).map((item) => parseInt(item, 10));
|
|
171
171
|
const lastColIndex = colIndexes[colIndexes.length - 1];
|
|
172
172
|
const lastRowIndex = this.table.length - 1;
|
|
173
173
|
|
|
@@ -176,7 +176,7 @@ export class TableWizardElement extends LitElement {
|
|
|
176
176
|
<table class="table table-center">
|
|
177
177
|
<thead>
|
|
178
178
|
<th>${this.renderTypeButton()}</th>
|
|
179
|
-
${colIndexes.map((colIndex
|
|
179
|
+
${colIndexes.map((colIndex) => html`
|
|
180
180
|
<th>${this.renderColButtons(colIndex, lastColIndex)}</th>
|
|
181
181
|
`)}
|
|
182
182
|
</thead>
|
|
@@ -184,7 +184,7 @@ export class TableWizardElement extends LitElement {
|
|
|
184
184
|
${this.table.map((row: string[], rowIndex: number) => html`
|
|
185
185
|
<tr>
|
|
186
186
|
<td>${this.renderRowButtons(rowIndex, lastRowIndex)}</td>
|
|
187
|
-
${row.map((value
|
|
187
|
+
${row.map((value, colIndex) => html`
|
|
188
188
|
<td>${this.renderDataElement(value, rowIndex, colIndex)}</td>
|
|
189
189
|
`)}
|
|
190
190
|
</tr>
|
|
@@ -57,9 +57,9 @@ export class AjaxDispatcher {
|
|
|
57
57
|
throw 'Undefined endpoint for route "' + routeName + '"';
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
public send(request: AjaxRequest, params: Array<string>): Promise<
|
|
61
|
-
const sentRequest = request.post(this.createRequestBody(params)).then(async (response: AjaxResponse): Promise<
|
|
62
|
-
return this.processResponse(await response.resolve());
|
|
60
|
+
public send<T extends AjaxDispatcherResponse = AjaxDispatcherResponse>(request: AjaxRequest, params: Array<string>): Promise<T> {
|
|
61
|
+
const sentRequest = request.post(this.createRequestBody(params)).then(async (response: AjaxResponse): Promise<T> => {
|
|
62
|
+
return this.processResponse(await response.resolve()) as T;
|
|
63
63
|
});
|
|
64
64
|
sentRequest.catch((reason: Error): void => {
|
|
65
65
|
if (reason instanceof DOMException && reason.name === 'AbortError') {
|
|
@@ -65,7 +65,7 @@ export default class FormEngineValidation {
|
|
|
65
65
|
*/
|
|
66
66
|
public static initialize(formEngine: typeof FormEngine): void {
|
|
67
67
|
formEngineInstance = formEngine;
|
|
68
|
-
formEngineInstance.formElement.querySelectorAll('.' + FormEngineValidation.errorClass).forEach((e
|
|
68
|
+
formEngineInstance.formElement.querySelectorAll<HTMLElement>('.' + FormEngineValidation.errorClass).forEach((e) => e.classList.remove(FormEngineValidation.errorClass));
|
|
69
69
|
|
|
70
70
|
// Initialize input fields
|
|
71
71
|
FormEngineValidation.initializeInputFields();
|
|
@@ -91,7 +91,7 @@ export default class FormEngineValidation {
|
|
|
91
91
|
* Initialize all input fields
|
|
92
92
|
*/
|
|
93
93
|
public static initializeInputFields(): void {
|
|
94
|
-
formEngineInstance.formElement.querySelectorAll(FormEngineValidation.inputSelector).forEach((visibleField
|
|
94
|
+
formEngineInstance.formElement.querySelectorAll<FormEngineFieldElement>(FormEngineValidation.inputSelector).forEach((visibleField): void => {
|
|
95
95
|
// ignore fields which already have been initialized
|
|
96
96
|
if ('formengineInputInitialized' in visibleField.dataset) {
|
|
97
97
|
return;
|
|
@@ -500,7 +500,7 @@ export default class FormEngineValidation {
|
|
|
500
500
|
*/
|
|
501
501
|
public static validate(section?: Element): void {
|
|
502
502
|
if (typeof section === 'undefined' || section instanceof Document) {
|
|
503
|
-
formEngineInstance.formElement.querySelectorAll(FormEngineValidation.markerSelector + ', [role="tablist"] > .nav-item').forEach((tabMenuItem
|
|
503
|
+
formEngineInstance.formElement.querySelectorAll<HTMLElement>(FormEngineValidation.markerSelector + ', [role="tablist"] > .nav-item').forEach((tabMenuItem): void => {
|
|
504
504
|
tabMenuItem.classList.remove(FormEngineValidation.validationErrorClass);
|
|
505
505
|
});
|
|
506
506
|
}
|
|
@@ -568,8 +568,8 @@ export default class FormEngineValidation {
|
|
|
568
568
|
* Find tab by field and mark it as has-validation-error
|
|
569
569
|
*/
|
|
570
570
|
public static markParentTab(element: FormEngineFieldElement, isValid: boolean): void {
|
|
571
|
-
const panes = DomHelper.parents(element, '.tab-pane');
|
|
572
|
-
panes.forEach((pane
|
|
571
|
+
const panes = DomHelper.parents<HTMLElement>(element, '.tab-pane');
|
|
572
|
+
panes.forEach((pane): void => {
|
|
573
573
|
if (isValid) {
|
|
574
574
|
// If incoming element is valid, check for errors in the same sheet
|
|
575
575
|
isValid = pane.querySelector('.has-error') === null;
|
|
@@ -631,3 +631,9 @@ export default class FormEngineValidation {
|
|
|
631
631
|
});
|
|
632
632
|
}
|
|
633
633
|
}
|
|
634
|
+
|
|
635
|
+
declare global {
|
|
636
|
+
interface HTMLElementEventMap {
|
|
637
|
+
't3-formengine-postfieldvalidation': CustomEvent<PostValidationEvent>;
|
|
638
|
+
}
|
|
639
|
+
}
|
package/backend/form-engine.ts
CHANGED
|
@@ -65,7 +65,7 @@ const enum FormAction {
|
|
|
65
65
|
saveAndAddRecord = '_savedokaddrecord',
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
type OnChangeFieldHandlerCallback = (data:
|
|
68
|
+
type OnChangeFieldHandlerCallback = (data: never, e: Event) => void;
|
|
69
69
|
type PreviewActionCallback = (targetName: string, previewUrl: string, $actionElement: JQuery, modal: ModalElement) => void;
|
|
70
70
|
type NewActionCallback = (targetName: string, $actionElement: JQuery) => void;
|
|
71
71
|
type DuplicateActionCallback = (targetName: string, $actionElement: JQuery) => void;
|
|
@@ -236,7 +236,7 @@ export default (function() {
|
|
|
236
236
|
return Modal.advanced({
|
|
237
237
|
type: Modal.types.iframe,
|
|
238
238
|
content: FormEngine.browserUrl + '&' + (new URLSearchParams(queryParams)).toString(),
|
|
239
|
-
size: Modal.sizes.
|
|
239
|
+
size: Modal.sizes.full
|
|
240
240
|
});
|
|
241
241
|
};
|
|
242
242
|
|
|
@@ -318,7 +318,7 @@ export default (function() {
|
|
|
318
318
|
}
|
|
319
319
|
|
|
320
320
|
if (reenableOptions && typeof optionEl !== 'undefined') {
|
|
321
|
-
optionEl.closest('select').querySelectorAll('[disabled]').forEach(function (disabledOption
|
|
321
|
+
optionEl.closest('select').querySelectorAll<HTMLOptionElement>('[disabled]').forEach(function (disabledOption) {
|
|
322
322
|
disabledOption.classList.remove('hidden');
|
|
323
323
|
disabledOption.disabled = false;
|
|
324
324
|
FormEngine.enableOptGroup(disabledOption);
|
|
@@ -394,7 +394,7 @@ export default (function() {
|
|
|
394
394
|
* @param {HTMLElement} originalFieldEl the hidden form field
|
|
395
395
|
*/
|
|
396
396
|
FormEngine.updateHiddenFieldValueFromSelect = function(selectFieldEl: HTMLSelectElement, originalFieldEl: HTMLSelectElement): void {
|
|
397
|
-
const selectedValues: string[] = Array.from(selectFieldEl.options).map((el
|
|
397
|
+
const selectedValues: string[] = Array.from(selectFieldEl.options).map((el) => el.value);
|
|
398
398
|
|
|
399
399
|
// make a comma separated list, if it is a multi-select
|
|
400
400
|
// set the values to the final hidden field
|
|
@@ -672,8 +672,8 @@ export default (function() {
|
|
|
672
672
|
}
|
|
673
673
|
};
|
|
674
674
|
|
|
675
|
-
const minlengthElements = document.querySelectorAll('[minlength]:not([data-input-type="datetimepicker"]):not(.t3js-charcounter-min-initialized)');
|
|
676
|
-
minlengthElements.forEach((field
|
|
675
|
+
const minlengthElements = document.querySelectorAll<HTMLInputElement|HTMLTextAreaElement>('[minlength]:not([data-input-type="datetimepicker"]):not(.t3js-charcounter-min-initialized)');
|
|
676
|
+
minlengthElements.forEach((field) => {
|
|
677
677
|
field.addEventListener('focus', (event) => {
|
|
678
678
|
const minCharacterCountLeft = FormEngine.getMinCharacterLeftCount(field);
|
|
679
679
|
if (minCharacterCountLeft > 0) {
|
|
@@ -720,7 +720,7 @@ export default (function() {
|
|
|
720
720
|
* Initialize input / text field "null" checkbox CSS overlay if no placeholder is set.
|
|
721
721
|
*/
|
|
722
722
|
FormEngine.initializeNullNoPlaceholderCheckboxes = function(): void {
|
|
723
|
-
document.querySelectorAll('.t3-form-field-eval-null-checkbox').forEach((el
|
|
723
|
+
document.querySelectorAll<HTMLElement>('.t3-form-field-eval-null-checkbox').forEach((el) => {
|
|
724
724
|
// Add disabled class to "t3js-formengine-field-item" if the null checkbox is NOT set,
|
|
725
725
|
// This activates a CSS overlay "disabling" the input field and everything around.
|
|
726
726
|
const checkbox = el.querySelector('input[type="checkbox"]') as HTMLInputElement;
|
|
@@ -735,7 +735,7 @@ export default (function() {
|
|
|
735
735
|
* Initialize input / text field "null" checkbox placeholder / real field if placeholder is set.
|
|
736
736
|
*/
|
|
737
737
|
FormEngine.initializeNullWithPlaceholderCheckboxes = function(): void {
|
|
738
|
-
document.querySelectorAll('.t3js-form-field-eval-null-placeholder-checkbox').forEach((el
|
|
738
|
+
document.querySelectorAll<HTMLElement>('.t3js-form-field-eval-null-placeholder-checkbox').forEach((el) => {
|
|
739
739
|
FormEngine.toggleCheckboxField(el.querySelector('input[type="checkbox"]'), false);
|
|
740
740
|
});
|
|
741
741
|
};
|
|
@@ -787,7 +787,7 @@ export default (function() {
|
|
|
787
787
|
* Disable the input field on load if localization state selector is set to "parent" or "source"
|
|
788
788
|
*/
|
|
789
789
|
FormEngine.initializeLocalizationStateSelector = function(): void {
|
|
790
|
-
document.querySelectorAll('.t3js-l10n-state-container').forEach((el
|
|
790
|
+
document.querySelectorAll<HTMLElement>('.t3js-l10n-state-container').forEach((el) => {
|
|
791
791
|
const input = el.closest('.t3js-formengine-field-item')?.querySelector('[data-formengine-input-name]') as HTMLInputElement|null;
|
|
792
792
|
if (input === undefined || input === null) {
|
|
793
793
|
return;
|
|
@@ -1011,7 +1011,7 @@ export default (function() {
|
|
|
1011
1011
|
items.forEach((item) => {
|
|
1012
1012
|
const handler = onFieldChangeHandlers.get(item.name);
|
|
1013
1013
|
if (handler instanceof Function) {
|
|
1014
|
-
handler.call(null, item.data || null, evt);
|
|
1014
|
+
handler.call(null, (item.data || null) as never, evt);
|
|
1015
1015
|
}
|
|
1016
1016
|
});
|
|
1017
1017
|
};
|
|
@@ -1160,7 +1160,7 @@ export default (function() {
|
|
|
1160
1160
|
}
|
|
1161
1161
|
}
|
|
1162
1162
|
const contentElement = document.createElement('p');
|
|
1163
|
-
contentStrings.forEach((item
|
|
1163
|
+
contentStrings.forEach((item, i): void => {
|
|
1164
1164
|
contentElement.append(item);
|
|
1165
1165
|
if (i !== contentStrings.length - 1) {
|
|
1166
1166
|
contentElement.append(document.createElement('br'));
|
|
@@ -228,7 +228,7 @@ class GlobalEventHandler {
|
|
|
228
228
|
private assignHTMLFormChildElementValue(element: HTMLElement, value: string): void {
|
|
229
229
|
const type: string = element.getAttribute('type');
|
|
230
230
|
if (element instanceof HTMLSelectElement) {
|
|
231
|
-
Array.from(element.options).some((option
|
|
231
|
+
Array.from(element.options).some((option, index) => {
|
|
232
232
|
if (option.value === value) {
|
|
233
233
|
element.selectedIndex = index;
|
|
234
234
|
return true;
|
|
@@ -34,7 +34,7 @@ export class HotkeyStruct {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
public static fromHotkey(hotkey: string[]): HotkeyStruct {
|
|
37
|
-
const nonModifierCodes = hotkey.filter((hotkeyPart
|
|
37
|
+
const nonModifierCodes = hotkey.filter((hotkeyPart) => !Object.values<string>(ModifierKeys).includes(hotkeyPart));
|
|
38
38
|
if (nonModifierCodes.length > 1) {
|
|
39
39
|
throw new Error('Cannot create HotkeyStruct with more than one non-modifier key, "' + nonModifierCodes.join('+') + '" given.');
|
|
40
40
|
}
|
package/backend/hotkeys.ts
CHANGED
|
@@ -60,12 +60,12 @@ class Hotkeys {
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
public register(hotkey: Hotkey, handler: (e: KeyboardEvent) => void, options: Partial<Options> = {}): void {
|
|
63
|
-
if (hotkey.filter((hotkeyPart
|
|
63
|
+
if (hotkey.filter((hotkeyPart) => !Object.values<string>(ModifierKeys).includes(hotkeyPart)).length === 0) {
|
|
64
64
|
throw new Error('Attempted to register hotkey "' + hotkey.join('+') + '" without a non-modifier key.');
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
// Normalize trigger
|
|
68
|
-
hotkey = hotkey.map((h
|
|
68
|
+
hotkey = hotkey.map((h) => h.toLowerCase());
|
|
69
69
|
|
|
70
70
|
const mergedConfiguration: Options = { ...this.defaultOptions, ...options };
|
|
71
71
|
if (!this.scopedHotkeyMap.has(mergedConfiguration.scope)) {
|
|
@@ -161,7 +161,7 @@ class Hotkeys {
|
|
|
161
161
|
}
|
|
162
162
|
|
|
163
163
|
// The standard requires to have modifier keys to be at first
|
|
164
|
-
parts.sort((a
|
|
164
|
+
parts.sort((a, b): number => {
|
|
165
165
|
const aIsModifierKey = Object.values<string>(ModifierKeys).includes(a);
|
|
166
166
|
const bIsModifierKey = Object.values<string>(ModifierKeys).includes(b);
|
|
167
167
|
|