typo3-typescript-sources 14.3.6 → 14.3.7
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/element/contextual-record-edit-trigger.ts +9 -1
- package/backend/form-engine/element/extra/select-box-filter.ts +8 -5
- package/backend/form-engine/element/select-tree.ts +16 -2
- package/backend/form-engine/field-control/add-record.ts +27 -1
- package/backend/form-engine.ts +80 -1
- package/backend/localization/localization-wizard.ts +3 -0
- package/backend/localization/steps/handler-selection-step.ts +12 -17
- package/backend/localization/steps/mode-step.ts +9 -14
- package/backend/localization/steps/source-language-step.ts +8 -13
- package/backend/localization/steps/target-language-step.ts +12 -17
- package/backend/modal.ts +124 -1
- package/backend/tests/form-engine/element/extra/select-box-filter-test.ts +215 -0
- package/backend/tests/form-engine/element/select-tree-test.ts +121 -0
- package/backend/wizard/steps/finisher-step.ts +2 -2
- package/backend/wizard/wizard.ts +11 -4
- package/core/ajax/ajax-request.ts +18 -0
- package/core/tests/ajax/ajax-request-test.ts +1 -1
- package/core/tests/utility/text-normalizer-test.ts +138 -0
- package/core/utility/text-normalizer.ts +98 -0
- package/form/backend/form-editor/view-model.ts +1 -1
- package/form/backend/form-wizard/steps/settings-step.ts +6 -3
- package/package.json +2 -2
- package/workspaces/backend.ts +7 -2
- package/workspaces/renderable/comment-view.ts +4 -2
- package/workspaces/renderable/record-table.ts +41 -4
- package/workspaces/workspaces.ts +65 -12
|
@@ -184,6 +184,11 @@ export class SettingsStep implements WizardStepInterface, WizardStepValueInterfa
|
|
|
184
184
|
|
|
185
185
|
let templatesFormGroup: TemplateResult | typeof nothing = nothing;
|
|
186
186
|
if (templates.length > 0) {
|
|
187
|
+
// Auto-select first template if none selected yet
|
|
188
|
+
if (!this.data.template) {
|
|
189
|
+
this.setValue({ template: templates[0].value });
|
|
190
|
+
}
|
|
191
|
+
|
|
187
192
|
templatesFormGroup = html `
|
|
188
193
|
<div class="form-group">
|
|
189
194
|
<label class="form-label" for="new-form-template">${formManagerLabels.get('formManager.form_template')}</label>
|
|
@@ -226,11 +231,9 @@ export class SettingsStep implements WizardStepInterface, WizardStepValueInterfa
|
|
|
226
231
|
}
|
|
227
232
|
|
|
228
233
|
private setPrototype(currentPrototype: string ): void {
|
|
229
|
-
const currentTemplates = this.context.formManager.getTemplatesForPrototype(currentPrototype);
|
|
230
|
-
|
|
231
234
|
this.setValue({
|
|
232
235
|
prototype: currentPrototype,
|
|
233
|
-
template:
|
|
236
|
+
template: ''
|
|
234
237
|
});
|
|
235
238
|
}
|
|
236
239
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "typo3-typescript-sources",
|
|
3
|
-
"version": "14.3.
|
|
3
|
+
"version": "14.3.7",
|
|
4
4
|
"description": "TYPO3 Core TypeScript Sources - Extracted from TYPO3/typo3 repository",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
},
|
|
29
29
|
"typo3": {
|
|
30
30
|
"sourceRepository": "https://github.com/TYPO3/typo3",
|
|
31
|
-
"sourceTag": "v14.3.
|
|
31
|
+
"sourceTag": "v14.3.7",
|
|
32
32
|
"sourcePath": "Build/Sources/TypeScript"
|
|
33
33
|
}
|
|
34
34
|
}
|
package/workspaces/backend.ts
CHANGED
|
@@ -469,6 +469,7 @@ class Backend extends Workspaces {
|
|
|
469
469
|
}
|
|
470
470
|
|
|
471
471
|
const workspacesRecordTable = document.querySelector('typo3-workspaces-record-table');
|
|
472
|
+
workspacesRecordTable.additionalColumns = result.additionalColumns ?? {};
|
|
472
473
|
workspacesRecordTable.results = result.data;
|
|
473
474
|
}
|
|
474
475
|
|
|
@@ -517,9 +518,13 @@ class Backend extends Workspaces {
|
|
|
517
518
|
filterFields: true
|
|
518
519
|
}),
|
|
519
520
|
).then(async (response: AjaxResponse): Promise<void> => {
|
|
520
|
-
const
|
|
521
|
-
const
|
|
521
|
+
const details = await response.resolve();
|
|
522
|
+
const item = details[0]?.result.data[0];
|
|
523
|
+
if (item === undefined) {
|
|
524
|
+
return;
|
|
525
|
+
}
|
|
522
526
|
|
|
527
|
+
const modalButtons = [];
|
|
523
528
|
const content = document.createElement('typo3-workspaces-record-information');
|
|
524
529
|
content.record = item;
|
|
525
530
|
|
|
@@ -16,12 +16,13 @@ import { html, LitElement, nothing, type TemplateResult } from 'lit';
|
|
|
16
16
|
import { repeat } from 'lit/directives/repeat.js';
|
|
17
17
|
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
|
|
18
18
|
import { nl2br } from '@typo3/core/directive/nl2br';
|
|
19
|
+
import labels from '~labels/workspaces.messages';
|
|
19
20
|
|
|
20
21
|
type Comment = {
|
|
21
22
|
user_comment: string;
|
|
22
23
|
previous_stage_title: string;
|
|
23
24
|
stage_title: string;
|
|
24
|
-
tstamp:
|
|
25
|
+
tstamp: string;
|
|
25
26
|
user_username: string;
|
|
26
27
|
user_avatar: string
|
|
27
28
|
};
|
|
@@ -64,7 +65,8 @@ export class CommentViewElement extends LitElement {
|
|
|
64
65
|
${comment.previous_stage_title} ⇾ ${comment.stage_title}
|
|
65
66
|
</span>
|
|
66
67
|
<span class="badge badge-info">
|
|
67
|
-
${comment.tstamp}
|
|
68
|
+
${comment.tstamp ? labels.get('comment.tstamp.value', { tstamp: new Date(comment.tstamp) }) : nothing}
|
|
69
|
+
</span>
|
|
68
70
|
</div>
|
|
69
71
|
</div>
|
|
70
72
|
</div>
|
|
@@ -24,6 +24,14 @@ import '@typo3/backend/element/icon-element';
|
|
|
24
24
|
import '@typo3/backend/element/qrcode-modal-button';
|
|
25
25
|
import 'bootstrap'; // for data-bs-toggle="dropdown"
|
|
26
26
|
|
|
27
|
+
export type AdditionalColumnValue = {
|
|
28
|
+
label?: string,
|
|
29
|
+
value?: string,
|
|
30
|
+
icon?: string,
|
|
31
|
+
title?: string,
|
|
32
|
+
url?: string
|
|
33
|
+
};
|
|
34
|
+
|
|
27
35
|
export type RecordData = {
|
|
28
36
|
table: string,
|
|
29
37
|
id: string,
|
|
@@ -38,7 +46,7 @@ export type RecordData = {
|
|
|
38
46
|
value_nextStage: number,
|
|
39
47
|
value_prevStage: number,
|
|
40
48
|
path_Workspace: string,
|
|
41
|
-
|
|
49
|
+
lastChanged: string,
|
|
42
50
|
lastEditorId: number,
|
|
43
51
|
lastEditorName: string,
|
|
44
52
|
lastEditorRealName: string,
|
|
@@ -67,7 +75,8 @@ export type RecordData = {
|
|
|
67
75
|
integrity: {
|
|
68
76
|
status: string,
|
|
69
77
|
messages: string
|
|
70
|
-
}
|
|
78
|
+
},
|
|
79
|
+
additional?: Record<string, AdditionalColumnValue>
|
|
71
80
|
};
|
|
72
81
|
|
|
73
82
|
@customElement('typo3-workspaces-record-table')
|
|
@@ -75,6 +84,12 @@ export class RecordTableElement extends LitElement {
|
|
|
75
84
|
@property({ type: Array })
|
|
76
85
|
public results: RecordData[] = [];
|
|
77
86
|
|
|
87
|
+
/**
|
|
88
|
+
* Labels of columns added by third party extensions, indexed by column identifier.
|
|
89
|
+
*/
|
|
90
|
+
@property({ type: Object })
|
|
91
|
+
public additionalColumns: Record<string, string> = {};
|
|
92
|
+
|
|
78
93
|
private latestPath: string | null = null;
|
|
79
94
|
|
|
80
95
|
protected override createRenderRoot(): HTMLElement | ShadowRoot {
|
|
@@ -139,6 +154,7 @@ export class RecordTableElement extends LitElement {
|
|
|
139
154
|
<th class="col-state">${labels.get('column.wsStateAction')}</th>
|
|
140
155
|
<th class="col-state">${labels.get('column.integrity')}</th>
|
|
141
156
|
<th>${labels.get('column.stage')}</th>
|
|
157
|
+
${Object.values(this.additionalColumns).map((label: string) => html`<th>${label}</th>`)}
|
|
142
158
|
<th class="col-control nowrap">
|
|
143
159
|
<span class="visually-hidden">${coreLabels.get('labels._CONTROL_')}</span>
|
|
144
160
|
</th>
|
|
@@ -200,7 +216,7 @@ export class RecordTableElement extends LitElement {
|
|
|
200
216
|
return html`
|
|
201
217
|
${latestPathChanged ? html`
|
|
202
218
|
<tr>
|
|
203
|
-
<th colspan
|
|
219
|
+
<th colspan=${8 + Object.keys(this.additionalColumns).length} class="col-white-space-normal">
|
|
204
220
|
<a href=${data.urlToPage}>${data.path_Workspace}</a>
|
|
205
221
|
</th>
|
|
206
222
|
</tr>
|
|
@@ -251,7 +267,7 @@ export class RecordTableElement extends LitElement {
|
|
|
251
267
|
` : html`
|
|
252
268
|
<span class="text-variant">${labels.get('column.editor.unknown')}</span>
|
|
253
269
|
`}
|
|
254
|
-
${data.
|
|
270
|
+
${data.lastChanged ? labels.get('column.last_change.value', { last_change: new Date(data.lastChanged) }) : nothing}
|
|
255
271
|
</div>
|
|
256
272
|
</td>
|
|
257
273
|
<td class="col-state">
|
|
@@ -263,6 +279,7 @@ export class RecordTableElement extends LitElement {
|
|
|
263
279
|
</span>
|
|
264
280
|
` : nothing}</td>
|
|
265
281
|
<td>${data.label_Stage}</td>
|
|
282
|
+
${Object.keys(this.additionalColumns).map((identifier: string) => this.renderAdditionalColumn(data, identifier))}
|
|
266
283
|
<td class="col-control nowrap">
|
|
267
284
|
<div class="btn-group">${this.renderElementActions(data)}</div>
|
|
268
285
|
<div class="btn-group">${this.renderVersioningActions(data)}</div>
|
|
@@ -271,6 +288,26 @@ export class RecordTableElement extends LitElement {
|
|
|
271
288
|
`;
|
|
272
289
|
}
|
|
273
290
|
|
|
291
|
+
protected renderAdditionalColumn(data: RecordData, identifier: string): TemplateResult {
|
|
292
|
+
const column = data.additional?.[identifier];
|
|
293
|
+
if (column === undefined) {
|
|
294
|
+
return html`<td></td>`;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const content = html`
|
|
298
|
+
${column.icon ? html`
|
|
299
|
+
<typo3-backend-icon identifier=${column.icon} size="small"></typo3-backend-icon>
|
|
300
|
+
` : nothing}
|
|
301
|
+
${column.value ?? ''}
|
|
302
|
+
`;
|
|
303
|
+
|
|
304
|
+
return html`
|
|
305
|
+
<td title=${ifDefined(column.title || undefined)}>
|
|
306
|
+
${column.url ? html`<a href=${column.url}>${content}</a>` : content}
|
|
307
|
+
</td>
|
|
308
|
+
`;
|
|
309
|
+
}
|
|
310
|
+
|
|
274
311
|
protected renderIndent(level: number) {
|
|
275
312
|
return html`<span class="indent indent-inline-block" style="--indent-level: ${level}"></span>`;
|
|
276
313
|
}
|
package/workspaces/workspaces.ts
CHANGED
|
@@ -11,14 +11,28 @@
|
|
|
11
11
|
* The TYPO3 project - inspiring people to share!
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import
|
|
14
|
+
import { AjaxResponse } from '@typo3/core/ajax/ajax-response';
|
|
15
15
|
import AjaxRequest from '@typo3/core/ajax/ajax-request';
|
|
16
16
|
import { SeverityEnum } from '@typo3/backend/enum/severity';
|
|
17
17
|
import { ProgressBarElement } from '@typo3/backend/element/progress-bar-element';
|
|
18
|
+
import Notification from '@typo3/backend/notification';
|
|
18
19
|
import { default as Modal, type ModalElement } from '@typo3/backend/modal';
|
|
19
20
|
import { html } from 'lit';
|
|
20
21
|
import labels from '~labels/workspaces.messages';
|
|
21
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Result of a single call of a dispatched call stack, carrying either
|
|
25
|
+
* `result` if the call succeeded, or `error` if it did not.
|
|
26
|
+
*/
|
|
27
|
+
interface RemoteCallResult {
|
|
28
|
+
method: string;
|
|
29
|
+
result?: unknown;
|
|
30
|
+
error?: {
|
|
31
|
+
message: string;
|
|
32
|
+
code: number;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
22
36
|
export default class Workspaces {
|
|
23
37
|
protected readonly ajaxRoute: string = 'workspace_dispatch';
|
|
24
38
|
protected progressBar: ProgressBarElement | null = null;
|
|
@@ -73,18 +87,22 @@ export default class Workspaces {
|
|
|
73
87
|
this.progressBar = document.createElement('typo3-backend-progress-bar');
|
|
74
88
|
document.querySelector(progressContainer).prepend(this.progressBar);
|
|
75
89
|
this.progressBar.start();
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
90
|
+
const headers = {
|
|
91
|
+
'Content-Type': 'application/json; charset=utf-8'
|
|
92
|
+
};
|
|
93
|
+
return new AjaxRequest(TYPO3.settings.ajaxUrls[this.ajaxRoute])
|
|
94
|
+
.post(payload, { headers })
|
|
95
|
+
.catch(async (reason: unknown): Promise<never> => {
|
|
96
|
+
await this.notifyRequestFailure(reason);
|
|
97
|
+
// Rejection is kept up, so that callers do not continue with a payload
|
|
98
|
+
// that carries errors instead of the results they are written for.
|
|
99
|
+
throw reason;
|
|
100
|
+
})
|
|
101
|
+
.finally(() => {
|
|
102
|
+
if (this.progressBar) {
|
|
103
|
+
this.progressBar.done();
|
|
81
104
|
}
|
|
82
|
-
}
|
|
83
|
-
).finally(() => {
|
|
84
|
-
if (this.progressBar) {
|
|
85
|
-
this.progressBar.done();
|
|
86
|
-
}
|
|
87
|
-
});
|
|
105
|
+
});
|
|
88
106
|
}
|
|
89
107
|
|
|
90
108
|
/**
|
|
@@ -105,4 +123,39 @@ export default class Workspaces {
|
|
|
105
123
|
method: method,
|
|
106
124
|
};
|
|
107
125
|
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Reports a failed request to the user. The server describes failing calls in the
|
|
129
|
+
* JSON body, anything else - an unreachable server, a session timeout redirect or
|
|
130
|
+
* an error page that is no JSON at all - can only be reported in a generic way.
|
|
131
|
+
*/
|
|
132
|
+
private async notifyRequestFailure(reason: unknown): Promise<void> {
|
|
133
|
+
const title = labels.get('error.dispatch.title');
|
|
134
|
+
if (!(reason instanceof AjaxResponse)) {
|
|
135
|
+
Notification.error(title, labels.get('error.dispatch.unavailable'));
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
let details: unknown;
|
|
140
|
+
try {
|
|
141
|
+
details = await reason.resolve('json');
|
|
142
|
+
} catch {
|
|
143
|
+
Notification.error(title, labels.get('error.dispatch.unavailable'));
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const messages: string[] = [];
|
|
148
|
+
if (Array.isArray(details)) {
|
|
149
|
+
for (const item of details as RemoteCallResult[]) {
|
|
150
|
+
if (item?.error?.message) {
|
|
151
|
+
messages.push(item.error.message);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (messages.length === 0) {
|
|
156
|
+
Notification.error(title, labels.get('error.dispatch.unknown'));
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
messages.forEach((message: string): void => Notification.error(title, message));
|
|
160
|
+
}
|
|
108
161
|
}
|