typo3-typescript-sources 14.0.0 → 14.1.1
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/.last-synced-tag +1 -1
- package/README-TYPO3.md +1 -1
- package/README.md +1 -1
- package/backend/clear-cache.ts +1 -1
- package/backend/code-editor/stream-parser/typoscript.ts +1 -1
- package/backend/context-menu-actions.ts +16 -2
- package/backend/date-time-picker.ts +20 -0
- package/backend/drag-uploader.ts +10 -4
- package/backend/element/progress-bar-element.ts +127 -1
- package/backend/element/qrcode-element.ts +1 -1
- package/backend/element/sidebar-toggle-element.ts +110 -0
- package/backend/enum/viewport/scaffold-identifier.ts +24 -4
- package/backend/form-engine/container/files-control-container.ts +8 -8
- package/backend/form-engine/container/inline-control-container.ts +8 -12
- package/backend/form-engine/container/site-language-container.ts +8 -8
- package/backend/form-engine/element/category-element.ts +0 -1
- package/backend/form-engine/element/extra/select-box-filter.ts +4 -0
- package/backend/form-engine/element/select-tree-element.ts +0 -1
- package/backend/form-engine/element/select-tree-toolbar.ts +1 -6
- package/backend/form-engine-validation.ts +1 -0
- package/backend/live-search/element/result/result-container.ts +5 -0
- package/backend/live-search/element/result/result-pagination.ts +2 -1
- package/backend/localization/steps/content-record-selection-step.ts +2 -2
- package/backend/login.ts +5 -1
- package/backend/modal.ts +46 -11
- package/backend/module-menu.ts +4 -80
- package/backend/online-media.ts +9 -3
- package/backend/recordlist.ts +3 -3
- package/backend/security/element/csp-reports.ts +83 -4
- package/backend/settings/editor/editable-setting.ts +1 -1
- package/backend/settings/editor.ts +1 -0
- package/backend/toolbar/live-search.ts +11 -7
- package/backend/toolbar/shortcut-menu.ts +2 -2
- package/backend/toolbar.ts +8 -5
- package/backend/tree/file-storage-browser.ts +8 -13
- package/backend/tree/file-storage-tree-container.ts +12 -15
- package/backend/tree/page-browser.ts +12 -8
- package/backend/tree/page-tree-element.ts +89 -36
- package/backend/tree/tree-node.ts +1 -0
- package/backend/tree/tree-toolbar.ts +8 -4
- package/backend/tree/tree.ts +11 -4
- package/backend/user-settings-manager.ts +22 -1
- package/backend/utility/collapse-state-search.ts +5 -6
- package/backend/viewport/content-navigation-toggle.ts +277 -0
- package/backend/viewport/content-navigation.ts +470 -0
- package/backend/viewport/loader.ts +13 -5
- package/backend/viewport/navigation-container.ts +27 -20
- package/backend/viewport/scaffold-state.ts +268 -0
- package/backend/viewport/toolbar.ts +75 -0
- package/backend/wizard/move-page.ts +2 -2
- package/extensionmanager/main.ts +30 -15
- package/extensionmanager/repository.ts +21 -16
- package/extensionmanager/update.ts +13 -3
- package/filelist/browse-files.ts +0 -6
- package/filelist/file-list.ts +18 -8
- package/form/backend/form-editor/inspector-component.ts +6 -1
- package/form/backend/form-editor/stage-component.ts +6 -1
- package/form/backend/form-editor/tree-component.ts +3 -1
- package/form/backend/form-manager/main.ts +10 -11
- package/install/module/environment/folder-structure.ts +4 -1
- package/install/module/maintenance/reference-index.ts +1 -1
- package/install/module/password-strength.ts +2 -0
- package/install/module/settings/extension-configuration.ts +0 -2
- package/install/module/settings/local-configuration.ts +0 -4
- package/install/module/upgrade/upgrade-docs.ts +5 -4
- package/install/module/upgrade/upgrade-wizards.ts +3 -1
- package/install/router.ts +5 -29
- package/package.json +2 -2
- package/recycler/recycler.ts +30 -18
- package/redirects/element/qrcode-modal-button.ts +75 -0
- package/rte-ckeditor/plugin/typo3-link.ts +32 -0
- package/styleguide/element/theme-switcher-element.ts +2 -2
- package/styleguide/processing-indicator.ts +16 -7
- package/workspaces/backend.ts +8 -14
- package/workspaces/workspaces.ts +10 -4
- package/backend/viewport/resizable-navigation.ts +0 -176
- package/install/renderable/clearable.ts +0 -113
package/.last-synced-tag
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
v14.
|
|
1
|
+
v14.1.1
|
package/README-TYPO3.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# TYPO3 CMS
|
|
2
2
|
|
|
3
3
|
TYPO3 is an open source PHP based web content management system released
|
|
4
|
-
under the GNU GPL. TYPO3 is copyright © 1999-
|
|
4
|
+
under the GNU GPL. TYPO3 is copyright © 1999-2026 by Kasper Skårhøj.
|
|
5
5
|
|
|
6
6
|
This document provides a basic introduction to TYPO3.
|
|
7
7
|
|
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ npm install typo3-typescript-sources
|
|
|
16
16
|
|
|
17
17
|
- **Original Repository:** [TYPO3/typo3](https://github.com/TYPO3/typo3)
|
|
18
18
|
- **Source Path:** `Build/Sources/TypeScript/`
|
|
19
|
-
- **Current TYPO3 Version:** `v14.
|
|
19
|
+
- **Current TYPO3 Version:** `v14.1.1`
|
|
20
20
|
|
|
21
21
|
## 🌿 Branches
|
|
22
22
|
|
package/backend/clear-cache.ts
CHANGED
|
@@ -42,7 +42,7 @@ class ClearCache {
|
|
|
42
42
|
* @return Promise<AjaxResponse>
|
|
43
43
|
*/
|
|
44
44
|
private static sendClearCacheRequest(pageId: number): Promise<AjaxResponse> {
|
|
45
|
-
const request = new AjaxRequest(TYPO3.settings.ajaxUrls.
|
|
45
|
+
const request = new AjaxRequest(TYPO3.settings.ajaxUrls.records_clearpagecache).withQueryArguments({ id: pageId }).get({ cache: 'no-cache' });
|
|
46
46
|
request.then(async (response: AjaxResponse): Promise<void> => {
|
|
47
47
|
const data = await response.resolve();
|
|
48
48
|
if (data.success === true) {
|
|
@@ -117,7 +117,7 @@ class ContextMenuActions {
|
|
|
117
117
|
|
|
118
118
|
public static openListModule(table: string, uid: number, dataset: DOMStringMap): void {
|
|
119
119
|
const pageId = table === 'pages' ? uid : dataset.pageUid;
|
|
120
|
-
ModuleMenu.App.showModule('
|
|
120
|
+
ModuleMenu.App.showModule('records', 'id=' + pageId);
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
public static pagesSort(table: string, uid: number, dataset: DOMStringMap): void {
|
|
@@ -127,6 +127,20 @@ class ContextMenuActions {
|
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
+
public static openSiteSettings(table: string, uid: number, dataset: DOMStringMap): void {
|
|
131
|
+
const siteSettingsUrl = dataset.siteSettingsUrl;
|
|
132
|
+
if (siteSettingsUrl) {
|
|
133
|
+
Viewport.ContentContainer.setUrl(siteSettingsUrl + '&returnUrl=' + ContextMenuActions.getReturnUrl());
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
public static openSiteConfiguration(table: string, uid: number, dataset: DOMStringMap): void {
|
|
138
|
+
const siteConfigurationUrl = dataset.siteConfigurationUrl;
|
|
139
|
+
if (siteConfigurationUrl) {
|
|
140
|
+
Viewport.ContentContainer.setUrl(siteConfigurationUrl + '&returnUrl=' + ContextMenuActions.getReturnUrl());
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
130
144
|
public static pagesNewMultiple(table: string, uid: number, dataset: DOMStringMap): void {
|
|
131
145
|
const pagesSortUrl = dataset.pagesNewMultipleUrl;
|
|
132
146
|
if (pagesSortUrl) {
|
|
@@ -240,7 +254,7 @@ class ContextMenuActions {
|
|
|
240
254
|
* Clear cache for given page uid
|
|
241
255
|
*/
|
|
242
256
|
public static clearCache(table: string, uid: number): void {
|
|
243
|
-
(new AjaxRequest(TYPO3.settings.ajaxUrls.
|
|
257
|
+
(new AjaxRequest(TYPO3.settings.ajaxUrls.records_clearpagecache)).withQueryArguments({ id: uid }).get({ cache: 'no-cache' }).then(
|
|
244
258
|
async (response: AjaxResponse): Promise<void> => {
|
|
245
259
|
const data = await response.resolve();
|
|
246
260
|
if (data.success === true) {
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import flatpickr from 'flatpickr';
|
|
15
|
+
import Persistent from '@typo3/backend/storage/persistent';
|
|
15
16
|
import ShortcutButtonsPlugin from 'shortcut-buttons-flatpickr';
|
|
16
17
|
import { DateTime } from 'luxon';
|
|
17
18
|
import ThrottleEvent from '@typo3/core/event/throttle-event';
|
|
@@ -63,6 +64,20 @@ class DateTimePicker {
|
|
|
63
64
|
const scrollEvent = this.getScrollEvent();
|
|
64
65
|
const options = this.getDateOptions(inputElement);
|
|
65
66
|
options.locale = locale;
|
|
67
|
+
|
|
68
|
+
// Custom "first day of week" user preference
|
|
69
|
+
const dow = Persistent.get('dateTimeFirstDayOfWeek');
|
|
70
|
+
|
|
71
|
+
if (dow !== '') {
|
|
72
|
+
// stored number is 1-index based, convert to 0-index.
|
|
73
|
+
const dowNumber = parseInt(dow, 10) - 1;
|
|
74
|
+
|
|
75
|
+
// two entries need to be adjusted here for proper utilization
|
|
76
|
+
// in non-english localisations.
|
|
77
|
+
flatpickr.l10ns[locale].firstDayOfWeek = dowNumber;
|
|
78
|
+
flatpickr.l10ns.default.firstDayOfWeek = dowNumber;
|
|
79
|
+
}
|
|
80
|
+
|
|
66
81
|
options.onOpen = [
|
|
67
82
|
(): void => {
|
|
68
83
|
scrollEvent.bindTo(document.querySelector('.t3js-module-body'));
|
|
@@ -251,6 +266,11 @@ class DateTimePicker {
|
|
|
251
266
|
options.enableTime = true;
|
|
252
267
|
options.noCalendar = true;
|
|
253
268
|
break;
|
|
269
|
+
case 'datetimesec':
|
|
270
|
+
options.altFormat = format[0] + ' HH:mm:ss';
|
|
271
|
+
options.enableSeconds = true;
|
|
272
|
+
options.enableTime = true;
|
|
273
|
+
break;
|
|
254
274
|
case 'year':
|
|
255
275
|
options.altFormat = 'yyyy';
|
|
256
276
|
break;
|
package/backend/drag-uploader.ts
CHANGED
|
@@ -16,7 +16,6 @@ import { DateTime } from 'luxon';
|
|
|
16
16
|
import type { AjaxResponse } from '@typo3/core/ajax/ajax-response';
|
|
17
17
|
import { SeverityEnum } from './enum/severity';
|
|
18
18
|
import { MessageUtility } from './utility/message-utility';
|
|
19
|
-
import NProgress from 'nprogress';
|
|
20
19
|
import AjaxRequest from '@typo3/core/ajax/ajax-request';
|
|
21
20
|
import { default as Modal, type ModalElement, Sizes as ModalSizes } from './modal';
|
|
22
21
|
import Notification from './notification';
|
|
@@ -97,6 +96,7 @@ export default class DragUploader {
|
|
|
97
96
|
private askForOverride: Array<FileConflict> = [];
|
|
98
97
|
|
|
99
98
|
private percentagePerFile: number = 1;
|
|
99
|
+
private overallProgressBar: ProgressBarElement | null = null;
|
|
100
100
|
|
|
101
101
|
private readonly body: HTMLElement;
|
|
102
102
|
private readonly element: HTMLElement;
|
|
@@ -364,7 +364,9 @@ export default class DragUploader {
|
|
|
364
364
|
this.fileList.closest('.filelist-main')?.querySelector('.t3-filelist-info-container')?.setAttribute('hidden', 'hidden');
|
|
365
365
|
}
|
|
366
366
|
|
|
367
|
-
|
|
367
|
+
this.overallProgressBar = document.createElement('typo3-backend-progress-bar');
|
|
368
|
+
document.body.appendChild(this.overallProgressBar);
|
|
369
|
+
this.overallProgressBar.start();
|
|
368
370
|
this.percentagePerFile = 1 / files.length;
|
|
369
371
|
|
|
370
372
|
// Check for each file if is already exist before adding it to the queue
|
|
@@ -382,7 +384,9 @@ export default class DragUploader {
|
|
|
382
384
|
uploaded: file,
|
|
383
385
|
action: this.irreObjectUid ? Action.USE_EXISTING : this.defaultAction,
|
|
384
386
|
});
|
|
385
|
-
|
|
387
|
+
if (this.overallProgressBar) {
|
|
388
|
+
this.overallProgressBar.inc(this.percentagePerFile);
|
|
389
|
+
}
|
|
386
390
|
} else {
|
|
387
391
|
new FileQueueItem(this, file, Action.SKIP, this.fileList.dataset.mode === Mode.BROWSE ? Mode.BROWSE : Mode.MANAGE);
|
|
388
392
|
}
|
|
@@ -392,7 +396,9 @@ export default class DragUploader {
|
|
|
392
396
|
|
|
393
397
|
Promise.all(ajaxCalls).then((): void => {
|
|
394
398
|
this.drawOverrideModal();
|
|
395
|
-
|
|
399
|
+
if (this.overallProgressBar) {
|
|
400
|
+
this.overallProgressBar.done();
|
|
401
|
+
}
|
|
396
402
|
});
|
|
397
403
|
|
|
398
404
|
this.fileInput.value = '';
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* The TYPO3 project - inspiring people to share!
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import { css, html, LitElement, nothing, type TemplateResult } from 'lit';
|
|
14
|
+
import { css, html, LitElement, nothing, type PropertyValues, type TemplateResult } from 'lit';
|
|
15
15
|
import { customElement, property } from 'lit/decorators';
|
|
16
16
|
import { classMap } from 'lit/directives/class-map';
|
|
17
17
|
import { styleMap } from 'lit/directives/style-map.js';
|
|
@@ -23,6 +23,7 @@ import { SeverityEnum } from '@typo3/backend/enum/severity';
|
|
|
23
23
|
* @internal
|
|
24
24
|
*
|
|
25
25
|
* @example
|
|
26
|
+
* Instance usage:
|
|
26
27
|
* <typo3-backend-progress-bar></typo3-backend-progress-bar>
|
|
27
28
|
* + `value` can be any positive number value between and 0 and `max` or `undefined`. The latter will render an indeterminate state.
|
|
28
29
|
* + `max` represents the upper value range
|
|
@@ -42,6 +43,15 @@ export class ProgressBarElement extends LitElement {
|
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
45
|
|
|
46
|
+
@keyframes fade-out {
|
|
47
|
+
from {
|
|
48
|
+
opacity: 1;
|
|
49
|
+
}
|
|
50
|
+
to {
|
|
51
|
+
opacity: 0;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
45
55
|
:host {
|
|
46
56
|
--progress-bar-height: 4px;
|
|
47
57
|
--progress-bar-color-primary: var(--typo3-state-primary-border-color);
|
|
@@ -57,6 +67,14 @@ export class ProgressBarElement extends LitElement {
|
|
|
57
67
|
border-radius: var(--progress-border-radius);
|
|
58
68
|
}
|
|
59
69
|
|
|
70
|
+
:host([hidden]) {
|
|
71
|
+
display: none;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
:host([is-hiding]) {
|
|
75
|
+
animation: fade-out 0.3s ease-out forwards;
|
|
76
|
+
}
|
|
77
|
+
|
|
60
78
|
.progress {
|
|
61
79
|
position: relative;
|
|
62
80
|
overflow: hidden;
|
|
@@ -126,6 +144,99 @@ export class ProgressBarElement extends LitElement {
|
|
|
126
144
|
@property({ type: Number, reflect: true }) max: number = 100;
|
|
127
145
|
@property({ type: Number, reflect: true }) severity: SeverityEnum|undefined = undefined;
|
|
128
146
|
@property({ type: String, reflect: true }) label: string|undefined;
|
|
147
|
+
@property({ type: Boolean, reflect: true, attribute: 'hidden' }) isHidden: boolean = false;
|
|
148
|
+
@property({ type: Boolean, state: true }) isHiding: boolean = false;
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Used to cancel pending done/hide operations when the progress bar is reused.
|
|
152
|
+
* This prevents race conditions where a previous done() call could remove the
|
|
153
|
+
* element while a new start() has already begun.
|
|
154
|
+
*/
|
|
155
|
+
private abortController: AbortController = new AbortController();
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Start the progress bar. Sets value to 0 by default or undefined for indeterminate mode.
|
|
159
|
+
*
|
|
160
|
+
* @param indeterminate If true, shows indeterminate loading animation
|
|
161
|
+
*/
|
|
162
|
+
public start(indeterminate: boolean = false): void {
|
|
163
|
+
// Cancel any pending done/hide operations
|
|
164
|
+
this.abortController.abort();
|
|
165
|
+
this.abortController = new AbortController();
|
|
166
|
+
|
|
167
|
+
this.isHiding = false;
|
|
168
|
+
this.isHidden = false;
|
|
169
|
+
this.value = indeterminate ? undefined : 0;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Increment the progress bar by a specific amount (or auto-increment if no amount given).
|
|
174
|
+
*
|
|
175
|
+
* @param amount The amount to increment (default: 5)
|
|
176
|
+
*/
|
|
177
|
+
public inc(amount: number = 5): void {
|
|
178
|
+
let currentValue = this.value ?? 0;
|
|
179
|
+
currentValue = this.clamp(currentValue + amount, 0, this.max);
|
|
180
|
+
this.value = currentValue >= this.max ? this.max : currentValue;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Complete the progress bar and automatically hide it after the bar animation completes.
|
|
185
|
+
*/
|
|
186
|
+
public async done(): Promise<void> {
|
|
187
|
+
// Capture signal at start to detect if start() was called during async operations
|
|
188
|
+
const signal = this.abortController.signal;
|
|
189
|
+
|
|
190
|
+
const currentValue = this.value ?? 0;
|
|
191
|
+
if (currentValue >= this.max) {
|
|
192
|
+
this.hide();
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (isNaN(this.value)) {
|
|
197
|
+
this.value = 0;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
await this.updateComplete;
|
|
201
|
+
if (signal.aborted) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
await new Promise((resolve) => requestAnimationFrame(() => requestAnimationFrame(resolve)));
|
|
206
|
+
if (signal.aborted) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
this.value = this.max;
|
|
211
|
+
await this.updateComplete;
|
|
212
|
+
if (signal.aborted) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const bar = this.shadowRoot.querySelector('.bar');
|
|
217
|
+
bar.addEventListener('transitionend', () => {
|
|
218
|
+
this.hide();
|
|
219
|
+
}, { once: true, signal });
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Hide the progress bar with fade-out animation and remove from DOM.
|
|
224
|
+
*/
|
|
225
|
+
public hide(): void {
|
|
226
|
+
this.isHiding = true;
|
|
227
|
+
this.addEventListener('animationend', () => {
|
|
228
|
+
this.remove();
|
|
229
|
+
}, { once: true, signal: this.abortController.signal });
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
public override connectedCallback(): void {
|
|
233
|
+
super.connectedCallback();
|
|
234
|
+
this.updateHostClass();
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
public override disconnectedCallback(): void {
|
|
238
|
+
super.disconnectedCallback();
|
|
239
|
+
}
|
|
129
240
|
|
|
130
241
|
protected override render(): TemplateResult {
|
|
131
242
|
const labelIdentifier = 'progress-label-' + (Math.random() + 1).toString(36).substring(2);
|
|
@@ -160,6 +271,21 @@ export class ProgressBarElement extends LitElement {
|
|
|
160
271
|
`;
|
|
161
272
|
}
|
|
162
273
|
|
|
274
|
+
protected override updated(changedProperties: PropertyValues): void {
|
|
275
|
+
super.updated(changedProperties);
|
|
276
|
+
if (changedProperties.has('isHiding')) {
|
|
277
|
+
this.updateHostClass();
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
private updateHostClass(): void {
|
|
282
|
+
if (this.isHiding) {
|
|
283
|
+
this.setAttribute('is-hiding', '');
|
|
284
|
+
} else {
|
|
285
|
+
this.removeAttribute('is-hiding');
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
163
289
|
private clamp(value: number, min: number, max: number): number {
|
|
164
290
|
return Math.min(max, Math.max(min, value));
|
|
165
291
|
}
|
|
@@ -92,7 +92,7 @@ export class QrCodeElement extends LitElement {
|
|
|
92
92
|
</select>
|
|
93
93
|
</div>
|
|
94
94
|
<div class="form-group">
|
|
95
|
-
<button type="submit" class="btn btn-
|
|
95
|
+
<button type="submit" class="btn btn-primary">${downloadLabel}</button>
|
|
96
96
|
</div>
|
|
97
97
|
</div>
|
|
98
98
|
</form>`;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the TYPO3 CMS project.
|
|
3
|
+
*
|
|
4
|
+
* It is free software; you can redistribute it and/or modify it under
|
|
5
|
+
* the terms of the GNU General Public License, either version 2
|
|
6
|
+
* of the License, or any later version.
|
|
7
|
+
*
|
|
8
|
+
* For the full copyright and license information, please read the
|
|
9
|
+
* LICENSE.txt file that was distributed with this source code.
|
|
10
|
+
*
|
|
11
|
+
* The TYPO3 project - inspiring people to share!
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { html, css, type TemplateResult } from 'lit';
|
|
15
|
+
import { customElement, property, state } from 'lit/decorators';
|
|
16
|
+
import { PseudoButtonLitElement } from './pseudo-button';
|
|
17
|
+
import { ScaffoldState, ScaffoldSidebarToggleEvent } from '../viewport/scaffold-state';
|
|
18
|
+
import '@typo3/backend/element/icon-element';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Module: @typo3/backend/element/sidebar-toggle-element
|
|
22
|
+
*
|
|
23
|
+
* Sidebar toggle button that displays different icons and labels based on sidebar state.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* <typo3-backend-sidebar-toggle
|
|
27
|
+
* label-collapse="Collapse sidebar"
|
|
28
|
+
* label-expand="Expand sidebar"
|
|
29
|
+
* ></typo3-backend-sidebar-toggle>
|
|
30
|
+
*/
|
|
31
|
+
@customElement('typo3-backend-sidebar-toggle')
|
|
32
|
+
export class SidebarToggleElement extends PseudoButtonLitElement {
|
|
33
|
+
static override styles = [
|
|
34
|
+
...PseudoButtonLitElement.styles,
|
|
35
|
+
css`
|
|
36
|
+
:host {
|
|
37
|
+
display: inline-flex;
|
|
38
|
+
align-items: center;
|
|
39
|
+
justify-content: center;
|
|
40
|
+
user-select: none;
|
|
41
|
+
}
|
|
42
|
+
:host([disabled]) {
|
|
43
|
+
pointer-events: none;
|
|
44
|
+
opacity: 0.5;
|
|
45
|
+
cursor: default;
|
|
46
|
+
}
|
|
47
|
+
`
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
@property({ type: String, attribute: 'label-collapse' }) labelCollapse: string = 'Collapse sidebar';
|
|
51
|
+
@property({ type: String, attribute: 'label-expand' }) labelExpand: string = 'Expand sidebar';
|
|
52
|
+
@property({ type: Boolean, reflect: true }) disabled: boolean = false;
|
|
53
|
+
|
|
54
|
+
@state() private expanded: boolean = false;
|
|
55
|
+
|
|
56
|
+
public override connectedCallback(): void {
|
|
57
|
+
super.connectedCallback();
|
|
58
|
+
this.expanded = ScaffoldState.isLargeScreen() ? ScaffoldState.isSidebarExpanded() : ScaffoldState.isSidebarVisible();
|
|
59
|
+
this.updateLabels();
|
|
60
|
+
document.addEventListener(ScaffoldSidebarToggleEvent.eventName, this.handleSidebarToggle as EventListener);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
public override disconnectedCallback(): void {
|
|
64
|
+
super.disconnectedCallback();
|
|
65
|
+
document.removeEventListener(ScaffoldSidebarToggleEvent.eventName, this.handleSidebarToggle as EventListener);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
protected override updated(): void {
|
|
69
|
+
this.updateLabels();
|
|
70
|
+
this.updateDisabledState();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
protected override render(): TemplateResult {
|
|
74
|
+
const iconIdentifier = this.expanded ? 'actions-menu-sidebar-collapsed' : 'actions-menu-sidebar-expanded';
|
|
75
|
+
const overlay = this.disabled ? 'overlay-readonly' : null;
|
|
76
|
+
return html`<typo3-backend-icon identifier="${iconIdentifier}" size="small" overlay="${overlay}"></typo3-backend-icon>`;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
protected override buttonActivated(): void {
|
|
80
|
+
if (!this.disabled) {
|
|
81
|
+
ScaffoldState.toggleSidebar();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private readonly handleSidebarToggle = (event: ScaffoldSidebarToggleEvent): void => {
|
|
86
|
+
this.expanded = event.detail.expanded;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
private updateLabels(): void {
|
|
90
|
+
const label = this.expanded ? this.labelCollapse : this.labelExpand;
|
|
91
|
+
this.title = label;
|
|
92
|
+
this.setAttribute('aria-label', label);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
private updateDisabledState(): void {
|
|
96
|
+
if (this.disabled) {
|
|
97
|
+
this.setAttribute('aria-disabled', 'true');
|
|
98
|
+
this.tabIndex = -1;
|
|
99
|
+
} else {
|
|
100
|
+
this.removeAttribute('aria-disabled');
|
|
101
|
+
this.tabIndex = 0;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
declare global {
|
|
107
|
+
interface HTMLElementTagNameMap {
|
|
108
|
+
'typo3-backend-sidebar-toggle': SidebarToggleElement;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -11,14 +11,34 @@
|
|
|
11
11
|
* The TYPO3 project - inspiring people to share!
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
+
import { ContentNavigationSlotEnum, type ContentNavigation } from '@typo3/backend/viewport/content-navigation';
|
|
15
|
+
|
|
14
16
|
export enum ScaffoldIdentifierEnum {
|
|
15
17
|
scaffold = '.t3js-scaffold',
|
|
16
18
|
header = '.t3js-scaffold-header',
|
|
17
|
-
|
|
19
|
+
sidebar = '.t3js-scaffold-sidebar',
|
|
18
20
|
content = '.t3js-scaffold-content',
|
|
19
|
-
contentModule = '.t3js-scaffold-content-module',
|
|
20
21
|
contentModuleRouter = 'typo3-backend-module-router',
|
|
21
22
|
contentModuleIframe = '.t3js-scaffold-content-module-iframe',
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Helper to get scaffold content area elements scoped to the backend content navigation
|
|
27
|
+
*/
|
|
28
|
+
export class ScaffoldContentArea {
|
|
29
|
+
public static readonly selector = 'typo3-backend-content-navigation[identifier="backend"]';
|
|
30
|
+
|
|
31
|
+
public static getContentNavigation(): ContentNavigation | null {
|
|
32
|
+
return document.querySelector(this.selector) as ContentNavigation | null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public static getNavigationContainer(): HTMLElement | null {
|
|
36
|
+
const container = this.getContentNavigation();
|
|
37
|
+
return container?.querySelector(`[slot="${ContentNavigationSlotEnum.navigation}"]`) ?? null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public static getContentContainer(): HTMLElement | null {
|
|
41
|
+
const container = this.getContentNavigation();
|
|
42
|
+
return container?.querySelector(`[slot="${ContentNavigationSlotEnum.content}"]`) ?? null;
|
|
43
|
+
}
|
|
24
44
|
}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
import { MessageUtility } from '../../utility/message-utility';
|
|
15
15
|
import { AjaxDispatcher } from './../inline-relation/ajax-dispatcher';
|
|
16
|
-
import
|
|
16
|
+
import { ProgressBarElement } from '@typo3/backend/element/progress-bar-element';
|
|
17
17
|
import Sortable from 'sortablejs';
|
|
18
18
|
import FormEngine from '@typo3/backend/form-engine';
|
|
19
19
|
import FormEngineValidation from '@typo3/backend/form-engine-validation';
|
|
@@ -59,7 +59,7 @@ interface RequestQueue {
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
interface ProgressQueue {
|
|
62
|
-
[key: string]:
|
|
62
|
+
[key: string]: ProgressBarElement;
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
interface Appearance {
|
|
@@ -369,7 +369,7 @@ class FilesControlContainer extends HTMLElement {
|
|
|
369
369
|
const isLoaded = recordFieldsContainer !== null && !recordContainer.classList.contains(States.notLoaded);
|
|
370
370
|
|
|
371
371
|
if (!isLoaded) {
|
|
372
|
-
const progress = this.getProgress(objectId
|
|
372
|
+
const progress = this.getProgress(objectId);
|
|
373
373
|
|
|
374
374
|
if (!isLoading) {
|
|
375
375
|
const ajaxRequest = this.ajaxDispatcher.newRequest(this.ajaxDispatcher.getEndpoint('file_reference_details'));
|
|
@@ -582,15 +582,15 @@ class FilesControlContainer extends HTMLElement {
|
|
|
582
582
|
});
|
|
583
583
|
}
|
|
584
584
|
|
|
585
|
-
private getProgress(objectId: string
|
|
586
|
-
|
|
587
|
-
let progress: any;
|
|
585
|
+
private getProgress(objectId: string): ProgressBarElement {
|
|
586
|
+
let progress: ProgressBarElement;
|
|
588
587
|
|
|
589
588
|
if (typeof this.progressQueue[objectId] !== 'undefined') {
|
|
590
589
|
progress = this.progressQueue[objectId];
|
|
591
590
|
} else {
|
|
592
|
-
progress =
|
|
593
|
-
|
|
591
|
+
progress = document.createElement('typo3-backend-progress-bar');
|
|
592
|
+
const panel = document.querySelector<HTMLElement>(selector`[data-object-id="${objectId}"]`);
|
|
593
|
+
panel.insertBefore(progress, panel.firstChild);
|
|
594
594
|
this.progressQueue[objectId] = progress;
|
|
595
595
|
}
|
|
596
596
|
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
import { MessageUtility } from '../../utility/message-utility';
|
|
15
15
|
import { AjaxDispatcher } from './../inline-relation/ajax-dispatcher';
|
|
16
16
|
import DocumentService from '@typo3/core/document-service';
|
|
17
|
-
import
|
|
17
|
+
import { ProgressBarElement } from '@typo3/backend/element/progress-bar-element';
|
|
18
18
|
import Sortable from 'sortablejs';
|
|
19
19
|
import FormEngine from '@typo3/backend/form-engine';
|
|
20
20
|
import FormEngineValidation from '@typo3/backend/form-engine-validation';
|
|
@@ -64,7 +64,7 @@ interface RequestQueue {
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
interface ProgressQueue {
|
|
67
|
-
[key: string]:
|
|
67
|
+
[key: string]: ProgressBarElement;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
interface Appearance {
|
|
@@ -562,7 +562,7 @@ class InlineControlContainer {
|
|
|
562
562
|
const isLoaded = recordFieldsContainer !== null && !recordContainer.classList.contains(States.notLoaded);
|
|
563
563
|
|
|
564
564
|
if (!isLoaded) {
|
|
565
|
-
const progress = this.getProgress(objectId
|
|
565
|
+
const progress = this.getProgress(objectId);
|
|
566
566
|
|
|
567
567
|
if (!isLoading) {
|
|
568
568
|
const ajaxRequest = this.ajaxDispatcher.newRequest(this.ajaxDispatcher.getEndpoint('record_inline_details'));
|
|
@@ -804,19 +804,15 @@ class InlineControlContainer {
|
|
|
804
804
|
});
|
|
805
805
|
}
|
|
806
806
|
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
* @param {string} objectIdHash
|
|
810
|
-
*/
|
|
811
|
-
private getProgress(objectId: string, objectIdHash: string): any {
|
|
812
|
-
const headerIdentifier = '#' + objectIdHash + '_header';
|
|
813
|
-
let progress: any;
|
|
807
|
+
private getProgress(objectId: string): ProgressBarElement {
|
|
808
|
+
let progress: ProgressBarElement;
|
|
814
809
|
|
|
815
810
|
if (typeof this.progressQueue[objectId] !== 'undefined') {
|
|
816
811
|
progress = this.progressQueue[objectId];
|
|
817
812
|
} else {
|
|
818
|
-
progress =
|
|
819
|
-
|
|
813
|
+
progress = document.createElement('typo3-backend-progress-bar');
|
|
814
|
+
const panel = InlineControlContainer.getInlineRecordContainer(objectId);
|
|
815
|
+
panel.insertBefore(progress, panel.firstChild);
|
|
820
816
|
this.progressQueue[objectId] = progress;
|
|
821
817
|
}
|
|
822
818
|
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
import { MessageUtility } from '../../utility/message-utility';
|
|
15
15
|
import { AjaxDispatcher } from './../inline-relation/ajax-dispatcher';
|
|
16
|
-
import
|
|
16
|
+
import { ProgressBarElement } from '@typo3/backend/element/progress-bar-element';
|
|
17
17
|
import FormEngine from '@typo3/backend/form-engine';
|
|
18
18
|
import FormEngineValidation from '@typo3/backend/form-engine-validation';
|
|
19
19
|
import { default as Modal, type ModalElement } from '@typo3/backend/modal';
|
|
@@ -51,7 +51,7 @@ interface RequestQueue {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
interface ProgressQueue {
|
|
54
|
-
[key: string]:
|
|
54
|
+
[key: string]: ProgressBarElement;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
interface UniqueDefinition {
|
|
@@ -345,7 +345,7 @@ class SiteLanguageContainer extends HTMLElement {
|
|
|
345
345
|
const isLoaded = recordFieldsContainer !== null && !recordContainer.classList.contains(States.notLoaded);
|
|
346
346
|
|
|
347
347
|
if (!isLoaded) {
|
|
348
|
-
const progress = this.getProgress(objectId
|
|
348
|
+
const progress = this.getProgress(objectId);
|
|
349
349
|
|
|
350
350
|
if (!isLoading) {
|
|
351
351
|
const ajaxRequest = this.ajaxDispatcher.newRequest(this.ajaxDispatcher.getEndpoint('site_configuration_inline_details'));
|
|
@@ -460,15 +460,15 @@ class SiteLanguageContainer extends HTMLElement {
|
|
|
460
460
|
recordContainer.classList.add('form-irre-object--deleted');
|
|
461
461
|
}
|
|
462
462
|
|
|
463
|
-
private getProgress(objectId: string
|
|
464
|
-
|
|
465
|
-
let progress: any;
|
|
463
|
+
private getProgress(objectId: string): ProgressBarElement {
|
|
464
|
+
let progress: ProgressBarElement;
|
|
466
465
|
|
|
467
466
|
if (typeof this.progressQueue[objectId] !== 'undefined') {
|
|
468
467
|
progress = this.progressQueue[objectId];
|
|
469
468
|
} else {
|
|
470
|
-
progress =
|
|
471
|
-
|
|
469
|
+
progress = document.createElement('typo3-backend-progress-bar');
|
|
470
|
+
const panel = SiteLanguageContainer.getInlineRecordContainer(objectId);
|
|
471
|
+
panel.insertBefore(progress, panel.firstChild);
|
|
472
472
|
this.progressQueue[objectId] = progress;
|
|
473
473
|
}
|
|
474
474
|
|
|
@@ -51,7 +51,6 @@ class CategoryElement extends HTMLElement {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
this.tree = document.createElement('typo3-backend-form-selecttree') as SelectTree;
|
|
54
|
-
this.tree.classList.add('tree-wrapper');
|
|
55
54
|
this.tree.setup = {
|
|
56
55
|
id: this.treeWrapper.id,
|
|
57
56
|
dataUrl: this.generateDataUrl(),
|
|
@@ -56,6 +56,10 @@ class SelectBoxFilter {
|
|
|
56
56
|
this.filter((<HTMLInputElement>e.target).value);
|
|
57
57
|
}).delegateTo(wizardsElement, Selectors.filterTextFieldSelector);
|
|
58
58
|
|
|
59
|
+
new RegularEvent('search', (e: Event): void => {
|
|
60
|
+
this.filter((<HTMLInputElement>e.target).value);
|
|
61
|
+
}).delegateTo(wizardsElement, Selectors.filterTextFieldSelector);
|
|
62
|
+
|
|
59
63
|
new RegularEvent('change', (e: Event): void => {
|
|
60
64
|
this.filter((<HTMLInputElement>e.target).value);
|
|
61
65
|
}).delegateTo(wizardsElement, Selectors.filterSelectFieldSelector);
|