@mintplayer/ng-spark 22.23.0 → 22.25.0
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/README.md +196 -0
- package/fesm2022/mintplayer-ng-spark-attribute-description.mjs +100 -47
- package/fesm2022/mintplayer-ng-spark-attribute-description.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-client-operations.mjs +310 -329
- package/fesm2022/mintplayer-ng-spark-client-operations.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-column-filter.mjs +175 -135
- package/fesm2022/mintplayer-ng-spark-column-filter.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-contributions.mjs +721 -0
- package/fesm2022/mintplayer-ng-spark-contributions.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-grid.mjs +2385 -1118
- package/fesm2022/mintplayer-ng-spark-grid.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-history.mjs +598 -0
- package/fesm2022/mintplayer-ng-spark-history.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-icon.mjs +64 -27
- package/fesm2022/mintplayer-ng-spark-icon.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-models.mjs +405 -762
- package/fesm2022/mintplayer-ng-spark-models.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-moderation.mjs +1212 -0
- package/fesm2022/mintplayer-ng-spark-moderation.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-panels.mjs +60 -0
- package/fesm2022/mintplayer-ng-spark-panels.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-pipes.mjs +1158 -765
- package/fesm2022/mintplayer-ng-spark-pipes.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-create.mjs +273 -169
- package/fesm2022/mintplayer-ng-spark-po-create.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-detail.mjs +795 -410
- package/fesm2022/mintplayer-ng-spark-po-detail.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-edit.mjs +1196 -280
- package/fesm2022/mintplayer-ng-spark-po-edit.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-form.mjs +2244 -1224
- package/fesm2022/mintplayer-ng-spark-po-form.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-query-list.mjs +571 -303
- package/fesm2022/mintplayer-ng-spark-query-list.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-renderers.mjs +44 -55
- package/fesm2022/mintplayer-ng-spark-renderers.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-retry-action-modal.mjs +216 -177
- package/fesm2022/mintplayer-ng-spark-retry-action-modal.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-routes.mjs +24 -28
- package/fesm2022/mintplayer-ng-spark-routes.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-services.mjs +625 -640
- package/fesm2022/mintplayer-ng-spark-services.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-shell.mjs +1031 -397
- package/fesm2022/mintplayer-ng-spark-shell.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-soft-delete.mjs +294 -0
- package/fesm2022/mintplayer-ng-spark-soft-delete.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark.mjs +14 -48
- package/fesm2022/mintplayer-ng-spark.mjs.map +1 -1
- package/package.json +23 -2
- package/types/mintplayer-ng-spark-attribute-description.d.ts +25 -18
- package/types/mintplayer-ng-spark-client-operations.d.ts +139 -160
- package/types/mintplayer-ng-spark-column-filter.d.ts +73 -55
- package/types/mintplayer-ng-spark-contributions.d.ts +231 -0
- package/types/mintplayer-ng-spark-grid.d.ts +917 -448
- package/types/mintplayer-ng-spark-history.d.ts +216 -0
- package/types/mintplayer-ng-spark-icon.d.ts +15 -13
- package/types/mintplayer-ng-spark-models.d.ts +681 -573
- package/types/mintplayer-ng-spark-moderation.d.ts +402 -0
- package/types/mintplayer-ng-spark-panels.d.ts +143 -0
- package/types/mintplayer-ng-spark-pipes.d.ts +131 -149
- package/types/mintplayer-ng-spark-po-create.d.ts +46 -37
- package/types/mintplayer-ng-spark-po-detail.d.ts +180 -117
- package/types/mintplayer-ng-spark-po-edit.d.ts +367 -64
- package/types/mintplayer-ng-spark-po-form.d.ts +558 -373
- package/types/mintplayer-ng-spark-query-list.d.ts +143 -82
- package/types/mintplayer-ng-spark-renderers.d.ts +121 -85
- package/types/mintplayer-ng-spark-retry-action-modal.d.ts +31 -34
- package/types/mintplayer-ng-spark-routes.d.ts +7 -11
- package/types/mintplayer-ng-spark-services.d.ts +377 -261
- package/types/mintplayer-ng-spark-shell.d.ts +228 -132
- package/types/mintplayer-ng-spark-soft-delete.d.ts +90 -0
- package/types/mintplayer-ng-spark.d.ts +19 -12
|
@@ -0,0 +1,721 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
import { ChangeDetectionStrategy, Component, computed, effect, inject, input, signal, untracked } from "@angular/core";
|
|
3
|
+
import { SparkLanguageService, SparkService } from "@mintplayer/ng-spark/services";
|
|
4
|
+
import { TranslateKeyPipe } from "@mintplayer/ng-spark/pipes";
|
|
5
|
+
import { RouterLink } from "@angular/router";
|
|
6
|
+
import { provideSparkDetailActions, provideSparkQueryRowActions } from "@mintplayer/ng-spark/panels";
|
|
7
|
+
const MAX_CELLS = 4e6;
|
|
8
|
+
function splitLines(text) {
|
|
9
|
+
if (text === null || text === void 0 || text === "") return [];
|
|
10
|
+
return String(text).split(/\r\n|\r|\n/);
|
|
11
|
+
}
|
|
12
|
+
function lineDiff(oldText, newText) {
|
|
13
|
+
const a = splitLines(oldText);
|
|
14
|
+
const b = splitLines(newText);
|
|
15
|
+
let start = 0;
|
|
16
|
+
while (start < a.length && start < b.length && a[start] === b[start]) start++;
|
|
17
|
+
let endA = a.length;
|
|
18
|
+
let endB = b.length;
|
|
19
|
+
while (endA > start && endB > start && a[endA - 1] === b[endB - 1]) {
|
|
20
|
+
endA--;
|
|
21
|
+
endB--;
|
|
22
|
+
}
|
|
23
|
+
const head = a.slice(0, start).map((text) => ({
|
|
24
|
+
kind: "same",
|
|
25
|
+
text
|
|
26
|
+
}));
|
|
27
|
+
const tail = a.slice(endA).map((text) => ({
|
|
28
|
+
kind: "same",
|
|
29
|
+
text
|
|
30
|
+
}));
|
|
31
|
+
const midA = a.slice(start, endA);
|
|
32
|
+
const midB = b.slice(start, endB);
|
|
33
|
+
return [
|
|
34
|
+
...head,
|
|
35
|
+
...diffMiddle(midA, midB),
|
|
36
|
+
...tail
|
|
37
|
+
];
|
|
38
|
+
}
|
|
39
|
+
function diffMiddle(a, b) {
|
|
40
|
+
const n = a.length;
|
|
41
|
+
const m = b.length;
|
|
42
|
+
if (n === 0) return b.map((text) => ({
|
|
43
|
+
kind: "added",
|
|
44
|
+
text
|
|
45
|
+
}));
|
|
46
|
+
if (m === 0) return a.map((text) => ({
|
|
47
|
+
kind: "removed",
|
|
48
|
+
text
|
|
49
|
+
}));
|
|
50
|
+
if (n * m > MAX_CELLS) return [...a.map((text) => ({
|
|
51
|
+
kind: "removed",
|
|
52
|
+
text
|
|
53
|
+
})), ...b.map((text) => ({
|
|
54
|
+
kind: "added",
|
|
55
|
+
text
|
|
56
|
+
}))];
|
|
57
|
+
const stride = m + 1;
|
|
58
|
+
const lcs = new Uint32Array((n + 1) * stride);
|
|
59
|
+
for (let i = n - 1; i >= 0; i--) for (let j = m - 1; j >= 0; j--) lcs[i * stride + j] = a[i] === b[j] ? lcs[(i + 1) * stride + j + 1] + 1 : Math.max(lcs[(i + 1) * stride + j], lcs[i * stride + j + 1]);
|
|
60
|
+
const result = [];
|
|
61
|
+
let i = 0;
|
|
62
|
+
let j = 0;
|
|
63
|
+
while (i < n && j < m) if (a[i] === b[j]) {
|
|
64
|
+
result.push({
|
|
65
|
+
kind: "same",
|
|
66
|
+
text: a[i]
|
|
67
|
+
});
|
|
68
|
+
i++;
|
|
69
|
+
j++;
|
|
70
|
+
} else if (lcs[(i + 1) * stride + j] >= lcs[i * stride + j + 1]) result.push({
|
|
71
|
+
kind: "removed",
|
|
72
|
+
text: a[i++]
|
|
73
|
+
});
|
|
74
|
+
else result.push({
|
|
75
|
+
kind: "added",
|
|
76
|
+
text: b[j++]
|
|
77
|
+
});
|
|
78
|
+
while (i < n) result.push({
|
|
79
|
+
kind: "removed",
|
|
80
|
+
text: a[i++]
|
|
81
|
+
});
|
|
82
|
+
while (j < m) result.push({
|
|
83
|
+
kind: "added",
|
|
84
|
+
text: b[j++]
|
|
85
|
+
});
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
function diffHasChanges(lines) {
|
|
89
|
+
return lines.some((l) => l.kind !== "same");
|
|
90
|
+
}
|
|
91
|
+
function lineDiffSourceOf(options, item) {
|
|
92
|
+
if (!options || !item) return null;
|
|
93
|
+
const type = asText(options["compareType"]);
|
|
94
|
+
const attribute = asText(options["compareAttribute"]);
|
|
95
|
+
if (!type || !attribute) return null;
|
|
96
|
+
const idAttribute = asText(options["compareIdAttribute"]);
|
|
97
|
+
const id = idAttribute ? asText(item.attributes?.find((a) => a.name === idAttribute)?.value) : derive(item.id, options["compareIdPattern"], options["compareIdReplacement"]);
|
|
98
|
+
if (!id) return null;
|
|
99
|
+
const rowKeyPattern = options["compareRowKeyPattern"];
|
|
100
|
+
const rowKey = rowKeyPattern !== void 0 ? derive(item.id, rowKeyPattern, options["compareRowKeyReplacement"]) : void 0;
|
|
101
|
+
if (rowKeyPattern !== void 0 && rowKey === null) return null;
|
|
102
|
+
const rowAttribute = asText(options["compareRowAttribute"]) ?? void 0;
|
|
103
|
+
return {
|
|
104
|
+
type,
|
|
105
|
+
id,
|
|
106
|
+
attribute,
|
|
107
|
+
...rowKey !== void 0 && rowKey !== null ? { rowKey } : {},
|
|
108
|
+
...rowAttribute ? { rowAttribute } : {}
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function lineDiffTextOf(po, source) {
|
|
112
|
+
const attribute = po?.attributes?.find((a) => a.name === source.attribute);
|
|
113
|
+
if (!attribute) return null;
|
|
114
|
+
if (source.rowKey !== void 0) {
|
|
115
|
+
const row = attribute.objects?.find((o) => o.id === source.rowKey);
|
|
116
|
+
if (!row) return "";
|
|
117
|
+
return valueText(row.attributes?.find((a) => a.name === source.rowAttribute));
|
|
118
|
+
}
|
|
119
|
+
if (source.rowAttribute && attribute.object !== void 0) return attribute.object ? valueText(attribute.object.attributes?.find((a) => a.name === source.rowAttribute)) : "";
|
|
120
|
+
return valueText(attribute);
|
|
121
|
+
}
|
|
122
|
+
function valueText(attribute) {
|
|
123
|
+
if (!attribute) return null;
|
|
124
|
+
const value = attribute.value;
|
|
125
|
+
return value === null || value === void 0 ? "" : String(value);
|
|
126
|
+
}
|
|
127
|
+
function asText(value) {
|
|
128
|
+
return typeof value === "string" && value !== "" ? value : null;
|
|
129
|
+
}
|
|
130
|
+
function derive(id, pattern, replacement) {
|
|
131
|
+
if (!id || typeof pattern !== "string") return null;
|
|
132
|
+
let regex;
|
|
133
|
+
try {
|
|
134
|
+
regex = new RegExp(pattern);
|
|
135
|
+
} catch {
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
if (!regex.test(id)) return null;
|
|
139
|
+
return id.replace(regex, typeof replacement === "string" ? replacement : "");
|
|
140
|
+
}
|
|
141
|
+
var SparkLineDiffComponent = class SparkLineDiffComponent {
|
|
142
|
+
spark = inject(SparkService);
|
|
143
|
+
value = input(...ngDevMode ? [void 0, { debugName: "value" }] : /* istanbul ignore next */ []);
|
|
144
|
+
attribute = input(...ngDevMode ? [void 0, { debugName: "attribute" }] : /* istanbul ignore next */ []);
|
|
145
|
+
options = input(...ngDevMode ? [void 0, { debugName: "options" }] : /* istanbul ignore next */ []);
|
|
146
|
+
item = input(...ngDevMode ? [void 0, { debugName: "item" }] : /* istanbul ignore next */ []);
|
|
147
|
+
text = computed(() => {
|
|
148
|
+
const value = this.value();
|
|
149
|
+
return value === null || value === void 0 ? "" : String(value);
|
|
150
|
+
}, ...ngDevMode ? [{ debugName: "text" }] : /* istanbul ignore next */ []);
|
|
151
|
+
compared = signal(void 0, ...ngDevMode ? [{ debugName: "compared" }] : /* istanbul ignore next */ []);
|
|
152
|
+
state = computed(() => {
|
|
153
|
+
const compared = this.compared();
|
|
154
|
+
return compared === void 0 ? "loading" : compared === null ? "unavailable" : "diff";
|
|
155
|
+
}, ...ngDevMode ? [{ debugName: "state" }] : /* istanbul ignore next */ []);
|
|
156
|
+
lines = computed(() => lineDiff(this.compared() ?? "", this.text()), ...ngDevMode ? [{ debugName: "lines" }] : /* istanbul ignore next */ []);
|
|
157
|
+
changed = computed(() => diffHasChanges(this.lines()), ...ngDevMode ? [{ debugName: "changed" }] : /* istanbul ignore next */ []);
|
|
158
|
+
generation = 0;
|
|
159
|
+
constructor() {
|
|
160
|
+
effect(() => {
|
|
161
|
+
const source = lineDiffSourceOf(this.options(), this.item());
|
|
162
|
+
untracked(() => void this.load(source));
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
marker(line) {
|
|
166
|
+
return line.kind === "added" ? "+" : line.kind === "removed" ? "−" : " ";
|
|
167
|
+
}
|
|
168
|
+
async load(source) {
|
|
169
|
+
const generation = ++this.generation;
|
|
170
|
+
if (!source) {
|
|
171
|
+
this.compared.set(null);
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
this.compared.set(void 0);
|
|
175
|
+
try {
|
|
176
|
+
const type = await this.typeIdOf(source.type);
|
|
177
|
+
const po = await this.spark.get(type, source.id);
|
|
178
|
+
if (generation === this.generation) this.compared.set(lineDiffTextOf(po, source));
|
|
179
|
+
} catch {
|
|
180
|
+
if (generation === this.generation) this.compared.set(null);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
async typeIdOf(type) {
|
|
184
|
+
return (await this.spark.getEntityTypes()).find((t) => t.name === type || t.alias === type || t.id === type)?.id ?? type;
|
|
185
|
+
}
|
|
186
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
187
|
+
minVersion: "12.0.0",
|
|
188
|
+
version: "22.2.0",
|
|
189
|
+
ngImport: i0,
|
|
190
|
+
type: SparkLineDiffComponent,
|
|
191
|
+
deps: [],
|
|
192
|
+
target: i0.ɵɵFactoryTarget.Component
|
|
193
|
+
});
|
|
194
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({
|
|
195
|
+
minVersion: "17.0.0",
|
|
196
|
+
version: "22.2.0",
|
|
197
|
+
type: SparkLineDiffComponent,
|
|
198
|
+
isStandalone: true,
|
|
199
|
+
selector: "spark-line-diff",
|
|
200
|
+
inputs: {
|
|
201
|
+
value: {
|
|
202
|
+
classPropertyName: "value",
|
|
203
|
+
publicName: "value",
|
|
204
|
+
isSignal: true,
|
|
205
|
+
isRequired: false,
|
|
206
|
+
transformFunction: null
|
|
207
|
+
},
|
|
208
|
+
attribute: {
|
|
209
|
+
classPropertyName: "attribute",
|
|
210
|
+
publicName: "attribute",
|
|
211
|
+
isSignal: true,
|
|
212
|
+
isRequired: false,
|
|
213
|
+
transformFunction: null
|
|
214
|
+
},
|
|
215
|
+
options: {
|
|
216
|
+
classPropertyName: "options",
|
|
217
|
+
publicName: "options",
|
|
218
|
+
isSignal: true,
|
|
219
|
+
isRequired: false,
|
|
220
|
+
transformFunction: null
|
|
221
|
+
},
|
|
222
|
+
item: {
|
|
223
|
+
classPropertyName: "item",
|
|
224
|
+
publicName: "item",
|
|
225
|
+
isSignal: true,
|
|
226
|
+
isRequired: false,
|
|
227
|
+
transformFunction: null
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
ngImport: i0,
|
|
231
|
+
template: `
|
|
232
|
+
@switch (state()) {
|
|
233
|
+
@case ('loading') {
|
|
234
|
+
<pre class="spark-line-diff-plain mb-0">{{ text() }}</pre>
|
|
235
|
+
}
|
|
236
|
+
@case ('diff') {
|
|
237
|
+
@if (changed()) {
|
|
238
|
+
<div class="spark-line-diff" role="table" [attr.aria-label]="attribute()?.name">
|
|
239
|
+
@for (line of lines(); track $index) {
|
|
240
|
+
<div role="row" [class]="'spark-line-diff-line spark-line-diff-' + line.kind">
|
|
241
|
+
<span class="spark-line-diff-marker" role="cell"
|
|
242
|
+
[attr.aria-label]="line.kind === 'added' ? ('common.diffAdded' | t) : line.kind === 'removed' ? ('common.diffRemoved' | t) : null">{{ marker(line) }}</span>
|
|
243
|
+
<span class="spark-line-diff-text" role="cell">{{ line.text }}</span>
|
|
244
|
+
</div>
|
|
245
|
+
}
|
|
246
|
+
</div>
|
|
247
|
+
} @else {
|
|
248
|
+
<pre class="spark-line-diff-plain mb-1">{{ text() }}</pre>
|
|
249
|
+
<div class="small text-muted spark-line-diff-identical">{{ 'common.diffIdentical' | t }}</div>
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
@default {
|
|
253
|
+
<pre class="spark-line-diff-plain mb-1">{{ text() }}</pre>
|
|
254
|
+
<div class="small text-muted spark-line-diff-unavailable">{{ 'common.diffUnavailable' | t }}</div>
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
`,
|
|
258
|
+
isInline: true,
|
|
259
|
+
styles: [":host{display:block}.spark-line-diff-plain{white-space:pre-wrap;font-family:inherit}.spark-line-diff{font-family:var(--bs-font-monospace, monospace);font-size:.875em;border:1px solid var(--bs-border-color, #dee2e6);border-radius:var(--bs-border-radius, .375rem);overflow-x:auto}.spark-line-diff-line{display:flex;white-space:pre-wrap}.spark-line-diff-marker{flex:0 0 1.5rem;text-align:center;-webkit-user-select:none;user-select:none;color:var(--bs-secondary-color, #6c757d)}.spark-line-diff-text{flex:1 1 auto;min-width:0;padding-right:.5rem}.spark-line-diff-added{background:var(--bs-success-bg-subtle, #d1e7dd);color:var(--bs-success-text-emphasis, #0a3622)}.spark-line-diff-removed{background:var(--bs-danger-bg-subtle, #f8d7da);color:var(--bs-danger-text-emphasis, #58151c);text-decoration:line-through}\n"],
|
|
260
|
+
dependencies: [{
|
|
261
|
+
kind: "pipe",
|
|
262
|
+
type: TranslateKeyPipe,
|
|
263
|
+
name: "t"
|
|
264
|
+
}],
|
|
265
|
+
changeDetection: i0.ChangeDetectionStrategy.OnPush
|
|
266
|
+
});
|
|
267
|
+
};
|
|
268
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
269
|
+
minVersion: "12.0.0",
|
|
270
|
+
version: "22.2.0",
|
|
271
|
+
ngImport: i0,
|
|
272
|
+
type: SparkLineDiffComponent,
|
|
273
|
+
decorators: [{
|
|
274
|
+
type: Component,
|
|
275
|
+
args: [{
|
|
276
|
+
selector: "spark-line-diff",
|
|
277
|
+
imports: [TranslateKeyPipe],
|
|
278
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
279
|
+
template: `
|
|
280
|
+
@switch (state()) {
|
|
281
|
+
@case ('loading') {
|
|
282
|
+
<pre class="spark-line-diff-plain mb-0">{{ text() }}</pre>
|
|
283
|
+
}
|
|
284
|
+
@case ('diff') {
|
|
285
|
+
@if (changed()) {
|
|
286
|
+
<div class="spark-line-diff" role="table" [attr.aria-label]="attribute()?.name">
|
|
287
|
+
@for (line of lines(); track $index) {
|
|
288
|
+
<div role="row" [class]="'spark-line-diff-line spark-line-diff-' + line.kind">
|
|
289
|
+
<span class="spark-line-diff-marker" role="cell"
|
|
290
|
+
[attr.aria-label]="line.kind === 'added' ? ('common.diffAdded' | t) : line.kind === 'removed' ? ('common.diffRemoved' | t) : null">{{ marker(line) }}</span>
|
|
291
|
+
<span class="spark-line-diff-text" role="cell">{{ line.text }}</span>
|
|
292
|
+
</div>
|
|
293
|
+
}
|
|
294
|
+
</div>
|
|
295
|
+
} @else {
|
|
296
|
+
<pre class="spark-line-diff-plain mb-1">{{ text() }}</pre>
|
|
297
|
+
<div class="small text-muted spark-line-diff-identical">{{ 'common.diffIdentical' | t }}</div>
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
@default {
|
|
301
|
+
<pre class="spark-line-diff-plain mb-1">{{ text() }}</pre>
|
|
302
|
+
<div class="small text-muted spark-line-diff-unavailable">{{ 'common.diffUnavailable' | t }}</div>
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
`,
|
|
306
|
+
styles: [":host{display:block}.spark-line-diff-plain{white-space:pre-wrap;font-family:inherit}.spark-line-diff{font-family:var(--bs-font-monospace, monospace);font-size:.875em;border:1px solid var(--bs-border-color, #dee2e6);border-radius:var(--bs-border-radius, .375rem);overflow-x:auto}.spark-line-diff-line{display:flex;white-space:pre-wrap}.spark-line-diff-marker{flex:0 0 1.5rem;text-align:center;-webkit-user-select:none;user-select:none;color:var(--bs-secondary-color, #6c757d)}.spark-line-diff-text{flex:1 1 auto;min-width:0;padding-right:.5rem}.spark-line-diff-added{background:var(--bs-success-bg-subtle, #d1e7dd);color:var(--bs-success-text-emphasis, #0a3622)}.spark-line-diff-removed{background:var(--bs-danger-bg-subtle, #f8d7da);color:var(--bs-danger-text-emphasis, #58151c);text-decoration:line-through}\n"]
|
|
307
|
+
}]
|
|
308
|
+
}],
|
|
309
|
+
ctorParameters: () => [],
|
|
310
|
+
propDecorators: {
|
|
311
|
+
value: [{
|
|
312
|
+
type: i0.Input,
|
|
313
|
+
args: [{
|
|
314
|
+
isSignal: true,
|
|
315
|
+
alias: "value",
|
|
316
|
+
required: false
|
|
317
|
+
}]
|
|
318
|
+
}],
|
|
319
|
+
attribute: [{
|
|
320
|
+
type: i0.Input,
|
|
321
|
+
args: [{
|
|
322
|
+
isSignal: true,
|
|
323
|
+
alias: "attribute",
|
|
324
|
+
required: false
|
|
325
|
+
}]
|
|
326
|
+
}],
|
|
327
|
+
options: [{
|
|
328
|
+
type: i0.Input,
|
|
329
|
+
args: [{
|
|
330
|
+
isSignal: true,
|
|
331
|
+
alias: "options",
|
|
332
|
+
required: false
|
|
333
|
+
}]
|
|
334
|
+
}],
|
|
335
|
+
item: [{
|
|
336
|
+
type: i0.Input,
|
|
337
|
+
args: [{
|
|
338
|
+
isSignal: true,
|
|
339
|
+
alias: "item",
|
|
340
|
+
required: false
|
|
341
|
+
}]
|
|
342
|
+
}]
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
function contributionHistoryLink(options, row, ownerId) {
|
|
346
|
+
if (!options?.contributionsQuery || !options.targetType || !ownerId || !row) return null;
|
|
347
|
+
const queryParams = {
|
|
348
|
+
parentId: ownerId,
|
|
349
|
+
parentType: options.targetType
|
|
350
|
+
};
|
|
351
|
+
for (const slot of options.slots ?? []) {
|
|
352
|
+
const value = row[slot];
|
|
353
|
+
if (value === null || value === void 0 || value === "") return null;
|
|
354
|
+
queryParams[slot] = String(value);
|
|
355
|
+
}
|
|
356
|
+
return {
|
|
357
|
+
commands: ["/query", options.contributionsQuery],
|
|
358
|
+
queryParams
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
function relativeTime(value, language, now = Date.now()) {
|
|
362
|
+
if (typeof value !== "string" && !(value instanceof Date)) return null;
|
|
363
|
+
const time = new Date(value).getTime();
|
|
364
|
+
if (Number.isNaN(time)) return null;
|
|
365
|
+
const seconds = Math.round((time - now) / 1e3);
|
|
366
|
+
const units = [
|
|
367
|
+
["year", 31536e3],
|
|
368
|
+
["month", 2592e3],
|
|
369
|
+
["week", 604800],
|
|
370
|
+
["day", 86400],
|
|
371
|
+
["hour", 3600],
|
|
372
|
+
["minute", 60]
|
|
373
|
+
];
|
|
374
|
+
let format;
|
|
375
|
+
try {
|
|
376
|
+
format = new Intl.RelativeTimeFormat(language, { numeric: "auto" });
|
|
377
|
+
} catch {
|
|
378
|
+
format = new Intl.RelativeTimeFormat("en", { numeric: "auto" });
|
|
379
|
+
}
|
|
380
|
+
for (const [unit, size] of units) if (Math.abs(seconds) >= size) return format.format(Math.round(seconds / size), unit);
|
|
381
|
+
return format.format(seconds, "second");
|
|
382
|
+
}
|
|
383
|
+
var SparkContributionAttributionComponent = class SparkContributionAttributionComponent {
|
|
384
|
+
lang = inject(SparkLanguageService);
|
|
385
|
+
row = input({}, ...ngDevMode ? [{ debugName: "row" }] : /* istanbul ignore next */ []);
|
|
386
|
+
options = input(...ngDevMode ? [void 0, { debugName: "options" }] : /* istanbul ignore next */ []);
|
|
387
|
+
ownerId = input(...ngDevMode ? [void 0, { debugName: "ownerId" }] : /* istanbul ignore next */ []);
|
|
388
|
+
asked = computed(() => new Set(this.options()?.["attribution"] ?? [
|
|
389
|
+
"ContributorName",
|
|
390
|
+
"UpdatedAt",
|
|
391
|
+
"ContributionCount"
|
|
392
|
+
]), ...ngDevMode ? [{ debugName: "asked" }] : /* istanbul ignore next */ []);
|
|
393
|
+
historyLink = computed(() => contributionHistoryLink(this.options(), this.row(), this.ownerId()), ...ngDevMode ? [{ debugName: "historyLink" }] : /* istanbul ignore next */ []);
|
|
394
|
+
parts = computed(() => {
|
|
395
|
+
const row = this.row() ?? {};
|
|
396
|
+
const asked = this.asked();
|
|
397
|
+
const language = this.lang.language();
|
|
398
|
+
const parts = [];
|
|
399
|
+
const name = row["ContributorName"];
|
|
400
|
+
if (asked.has("ContributorName") && typeof name === "string" && name.trim() !== "") parts.push({
|
|
401
|
+
kind: "by",
|
|
402
|
+
text: this.lang.t("contributions.by").replace("{name}", name)
|
|
403
|
+
});
|
|
404
|
+
const at = row["UpdatedAt"];
|
|
405
|
+
const relative = asked.has("UpdatedAt") ? relativeTime(at, language) : null;
|
|
406
|
+
if (relative) {
|
|
407
|
+
const date = new Date(at);
|
|
408
|
+
parts.push({
|
|
409
|
+
kind: "at",
|
|
410
|
+
text: relative,
|
|
411
|
+
iso: date.toISOString(),
|
|
412
|
+
title: date.toLocaleString(language)
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
const count = row["ContributionCount"];
|
|
416
|
+
if (asked.has("ContributionCount") && typeof count === "number") parts.push({
|
|
417
|
+
kind: "history",
|
|
418
|
+
text: this.lang.t("contributions.history").replace("{count}", String(count))
|
|
419
|
+
});
|
|
420
|
+
return parts;
|
|
421
|
+
}, ...ngDevMode ? [{ debugName: "parts" }] : /* istanbul ignore next */ []);
|
|
422
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
423
|
+
minVersion: "12.0.0",
|
|
424
|
+
version: "22.2.0",
|
|
425
|
+
ngImport: i0,
|
|
426
|
+
type: SparkContributionAttributionComponent,
|
|
427
|
+
deps: [],
|
|
428
|
+
target: i0.ɵɵFactoryTarget.Component
|
|
429
|
+
});
|
|
430
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({
|
|
431
|
+
minVersion: "17.0.0",
|
|
432
|
+
version: "22.2.0",
|
|
433
|
+
type: SparkContributionAttributionComponent,
|
|
434
|
+
isStandalone: true,
|
|
435
|
+
selector: "spark-contribution-attribution",
|
|
436
|
+
inputs: {
|
|
437
|
+
row: {
|
|
438
|
+
classPropertyName: "row",
|
|
439
|
+
publicName: "row",
|
|
440
|
+
isSignal: true,
|
|
441
|
+
isRequired: false,
|
|
442
|
+
transformFunction: null
|
|
443
|
+
},
|
|
444
|
+
options: {
|
|
445
|
+
classPropertyName: "options",
|
|
446
|
+
publicName: "options",
|
|
447
|
+
isSignal: true,
|
|
448
|
+
isRequired: false,
|
|
449
|
+
transformFunction: null
|
|
450
|
+
},
|
|
451
|
+
ownerId: {
|
|
452
|
+
classPropertyName: "ownerId",
|
|
453
|
+
publicName: "ownerId",
|
|
454
|
+
isSignal: true,
|
|
455
|
+
isRequired: false,
|
|
456
|
+
transformFunction: null
|
|
457
|
+
}
|
|
458
|
+
},
|
|
459
|
+
ngImport: i0,
|
|
460
|
+
template: `
|
|
461
|
+
@if (parts().length) {
|
|
462
|
+
<span class="spark-contribution-attribution small text-muted">
|
|
463
|
+
@for (part of parts(); track part.kind; let last = $last) {
|
|
464
|
+
@switch (part.kind) {
|
|
465
|
+
@case ('by') { <span class="spark-contribution-by">{{ part.text }}</span> }
|
|
466
|
+
@case ('at') { <time class="spark-contribution-at" [attr.datetime]="part.iso" [attr.title]="part.title">{{ part.text }}</time> }
|
|
467
|
+
@case ('history') {
|
|
468
|
+
@if (historyLink(); as link) {
|
|
469
|
+
<a class="spark-contribution-history" [routerLink]="link.commands" [queryParams]="link.queryParams">{{ part.text }}</a>
|
|
470
|
+
} @else {
|
|
471
|
+
<span class="spark-contribution-history">{{ part.text }}</span>
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
@if (!last) { <span aria-hidden="true"> · </span> }
|
|
476
|
+
}
|
|
477
|
+
</span>
|
|
478
|
+
}
|
|
479
|
+
`,
|
|
480
|
+
isInline: true,
|
|
481
|
+
dependencies: [{
|
|
482
|
+
kind: "directive",
|
|
483
|
+
type: RouterLink,
|
|
484
|
+
selector: "[routerLink]",
|
|
485
|
+
inputs: [
|
|
486
|
+
"target",
|
|
487
|
+
"queryParams",
|
|
488
|
+
"fragment",
|
|
489
|
+
"queryParamsHandling",
|
|
490
|
+
"state",
|
|
491
|
+
"info",
|
|
492
|
+
"relativeTo",
|
|
493
|
+
"preserveFragment",
|
|
494
|
+
"skipLocationChange",
|
|
495
|
+
"replaceUrl",
|
|
496
|
+
"browserUrl",
|
|
497
|
+
"routerLink"
|
|
498
|
+
]
|
|
499
|
+
}],
|
|
500
|
+
changeDetection: i0.ChangeDetectionStrategy.OnPush
|
|
501
|
+
});
|
|
502
|
+
};
|
|
503
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
504
|
+
minVersion: "12.0.0",
|
|
505
|
+
version: "22.2.0",
|
|
506
|
+
ngImport: i0,
|
|
507
|
+
type: SparkContributionAttributionComponent,
|
|
508
|
+
decorators: [{
|
|
509
|
+
type: Component,
|
|
510
|
+
args: [{
|
|
511
|
+
selector: "spark-contribution-attribution",
|
|
512
|
+
imports: [RouterLink],
|
|
513
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
514
|
+
template: `
|
|
515
|
+
@if (parts().length) {
|
|
516
|
+
<span class="spark-contribution-attribution small text-muted">
|
|
517
|
+
@for (part of parts(); track part.kind; let last = $last) {
|
|
518
|
+
@switch (part.kind) {
|
|
519
|
+
@case ('by') { <span class="spark-contribution-by">{{ part.text }}</span> }
|
|
520
|
+
@case ('at') { <time class="spark-contribution-at" [attr.datetime]="part.iso" [attr.title]="part.title">{{ part.text }}</time> }
|
|
521
|
+
@case ('history') {
|
|
522
|
+
@if (historyLink(); as link) {
|
|
523
|
+
<a class="spark-contribution-history" [routerLink]="link.commands" [queryParams]="link.queryParams">{{ part.text }}</a>
|
|
524
|
+
} @else {
|
|
525
|
+
<span class="spark-contribution-history">{{ part.text }}</span>
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
@if (!last) { <span aria-hidden="true"> · </span> }
|
|
530
|
+
}
|
|
531
|
+
</span>
|
|
532
|
+
}
|
|
533
|
+
`
|
|
534
|
+
}]
|
|
535
|
+
}],
|
|
536
|
+
propDecorators: {
|
|
537
|
+
row: [{
|
|
538
|
+
type: i0.Input,
|
|
539
|
+
args: [{
|
|
540
|
+
isSignal: true,
|
|
541
|
+
alias: "row",
|
|
542
|
+
required: false
|
|
543
|
+
}]
|
|
544
|
+
}],
|
|
545
|
+
options: [{
|
|
546
|
+
type: i0.Input,
|
|
547
|
+
args: [{
|
|
548
|
+
isSignal: true,
|
|
549
|
+
alias: "options",
|
|
550
|
+
required: false
|
|
551
|
+
}]
|
|
552
|
+
}],
|
|
553
|
+
ownerId: [{
|
|
554
|
+
type: i0.Input,
|
|
555
|
+
args: [{
|
|
556
|
+
isSignal: true,
|
|
557
|
+
alias: "ownerId",
|
|
558
|
+
required: false
|
|
559
|
+
}]
|
|
560
|
+
}]
|
|
561
|
+
}
|
|
562
|
+
});
|
|
563
|
+
const SPARK_CONTRIBUTIONS_QUERY_SOURCE = "Custom.SparkContributionsOfTarget";
|
|
564
|
+
const SPARK_REVERT_CONTRIBUTION_PATH = "/po/revert-contribution";
|
|
565
|
+
function isContributionsQuery(query) {
|
|
566
|
+
return query?.source === SPARK_CONTRIBUTIONS_QUERY_SOURCE;
|
|
567
|
+
}
|
|
568
|
+
async function revertContribution(spark, objectTypeId, id) {
|
|
569
|
+
await spark.postEnvelope(SPARK_REVERT_CONTRIBUTION_PATH, {
|
|
570
|
+
objectTypeId,
|
|
571
|
+
id
|
|
572
|
+
});
|
|
573
|
+
}
|
|
574
|
+
const sparkRevertContributionRowAction = {
|
|
575
|
+
id: "spark-revert-contribution",
|
|
576
|
+
labelKey: "contributions.revert",
|
|
577
|
+
priority: 20,
|
|
578
|
+
isOffered: (scope) => scope.permissions?.canRevertContribution === true && isContributionsQuery(scope.query) && scope.deleted !== "only",
|
|
579
|
+
run: async (context) => {
|
|
580
|
+
const spark = inject(SparkService);
|
|
581
|
+
const lang = inject(SparkLanguageService);
|
|
582
|
+
if (!confirm(lang.t("contributions.confirmRevert"))) return;
|
|
583
|
+
await revertContribution(spark, context.entityType.id, context.row.id);
|
|
584
|
+
context.reload();
|
|
585
|
+
}
|
|
586
|
+
};
|
|
587
|
+
var SparkRevertContributionComponent = class SparkRevertContributionComponent {
|
|
588
|
+
spark = inject(SparkService);
|
|
589
|
+
lang = inject(SparkLanguageService);
|
|
590
|
+
context = input.required(...ngDevMode ? [{ debugName: "context" }] : /* istanbul ignore next */ []);
|
|
591
|
+
isContributionType = signal(false, ...ngDevMode ? [{ debugName: "isContributionType" }] : /* istanbul ignore next */ []);
|
|
592
|
+
offered = computed(() => {
|
|
593
|
+
const ctx = this.context();
|
|
594
|
+
return this.isContributionType() && ctx.permissions?.canRevertContribution === true && ctx.deleted !== "only";
|
|
595
|
+
}, ...ngDevMode ? [{ debugName: "offered" }] : /* istanbul ignore next */ []);
|
|
596
|
+
busy = signal(false, ...ngDevMode ? [{ debugName: "busy" }] : /* istanbul ignore next */ []);
|
|
597
|
+
error = signal(null, ...ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []);
|
|
598
|
+
constructor() {
|
|
599
|
+
effect(() => {
|
|
600
|
+
const ctx = this.context();
|
|
601
|
+
if (ctx.permissions?.canRevertContribution !== true || !ctx.entityType?.name) {
|
|
602
|
+
untracked(() => this.isContributionType.set(false));
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
const name = ctx.entityType.name;
|
|
606
|
+
untracked(() => void this.spark.getQueryByName(`${name}s`).then((query) => this.isContributionType.set(isContributionsQuery(query) && query?.entityType === name)).catch(() => this.isContributionType.set(false)));
|
|
607
|
+
});
|
|
608
|
+
}
|
|
609
|
+
async revert() {
|
|
610
|
+
if (this.busy()) return;
|
|
611
|
+
if (!confirm(this.lang.t("contributions.confirmRevert"))) return;
|
|
612
|
+
const ctx = this.context();
|
|
613
|
+
this.busy.set(true);
|
|
614
|
+
this.error.set(null);
|
|
615
|
+
try {
|
|
616
|
+
await revertContribution(this.spark, ctx.entityType.id, ctx.id);
|
|
617
|
+
await ctx.reload();
|
|
618
|
+
} catch (e) {
|
|
619
|
+
const err = e;
|
|
620
|
+
const first = err?.error?.result?.errors?.[0];
|
|
621
|
+
const validation = typeof first?.errorMessage === "string" ? first.errorMessage : first?.errorMessage ? this.lang.resolve(first.errorMessage) : "";
|
|
622
|
+
this.error.set(validation || err?.error?.result?.error || err?.error?.error || this.lang.t("common.actionFailed"));
|
|
623
|
+
} finally {
|
|
624
|
+
this.busy.set(false);
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
628
|
+
minVersion: "12.0.0",
|
|
629
|
+
version: "22.2.0",
|
|
630
|
+
ngImport: i0,
|
|
631
|
+
type: SparkRevertContributionComponent,
|
|
632
|
+
deps: [],
|
|
633
|
+
target: i0.ɵɵFactoryTarget.Component
|
|
634
|
+
});
|
|
635
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({
|
|
636
|
+
minVersion: "17.0.0",
|
|
637
|
+
version: "22.2.0",
|
|
638
|
+
type: SparkRevertContributionComponent,
|
|
639
|
+
isStandalone: true,
|
|
640
|
+
selector: "spark-revert-contribution",
|
|
641
|
+
inputs: { context: {
|
|
642
|
+
classPropertyName: "context",
|
|
643
|
+
publicName: "context",
|
|
644
|
+
isSignal: true,
|
|
645
|
+
isRequired: true,
|
|
646
|
+
transformFunction: null
|
|
647
|
+
} },
|
|
648
|
+
ngImport: i0,
|
|
649
|
+
template: `
|
|
650
|
+
@if (offered()) {
|
|
651
|
+
<span class="d-inline-flex gap-2 align-items-center">
|
|
652
|
+
<button type="button" class="btn btn-outline-primary spark-revert-contribution" [disabled]="busy()" (click)="revert()">
|
|
653
|
+
{{ 'contributions.revert' | t }}
|
|
654
|
+
</button>
|
|
655
|
+
@if (error(); as message) {
|
|
656
|
+
<span class="text-danger small spark-revert-contribution-error" role="alert">{{ message }}</span>
|
|
657
|
+
}
|
|
658
|
+
</span>
|
|
659
|
+
}
|
|
660
|
+
`,
|
|
661
|
+
isInline: true,
|
|
662
|
+
dependencies: [{
|
|
663
|
+
kind: "pipe",
|
|
664
|
+
type: TranslateKeyPipe,
|
|
665
|
+
name: "t"
|
|
666
|
+
}],
|
|
667
|
+
changeDetection: i0.ChangeDetectionStrategy.OnPush
|
|
668
|
+
});
|
|
669
|
+
};
|
|
670
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
671
|
+
minVersion: "12.0.0",
|
|
672
|
+
version: "22.2.0",
|
|
673
|
+
ngImport: i0,
|
|
674
|
+
type: SparkRevertContributionComponent,
|
|
675
|
+
decorators: [{
|
|
676
|
+
type: Component,
|
|
677
|
+
args: [{
|
|
678
|
+
selector: "spark-revert-contribution",
|
|
679
|
+
imports: [TranslateKeyPipe],
|
|
680
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
681
|
+
template: `
|
|
682
|
+
@if (offered()) {
|
|
683
|
+
<span class="d-inline-flex gap-2 align-items-center">
|
|
684
|
+
<button type="button" class="btn btn-outline-primary spark-revert-contribution" [disabled]="busy()" (click)="revert()">
|
|
685
|
+
{{ 'contributions.revert' | t }}
|
|
686
|
+
</button>
|
|
687
|
+
@if (error(); as message) {
|
|
688
|
+
<span class="text-danger small spark-revert-contribution-error" role="alert">{{ message }}</span>
|
|
689
|
+
}
|
|
690
|
+
</span>
|
|
691
|
+
}
|
|
692
|
+
`
|
|
693
|
+
}]
|
|
694
|
+
}],
|
|
695
|
+
ctorParameters: () => [],
|
|
696
|
+
propDecorators: { context: [{
|
|
697
|
+
type: i0.Input,
|
|
698
|
+
args: [{
|
|
699
|
+
isSignal: true,
|
|
700
|
+
alias: "context",
|
|
701
|
+
required: true
|
|
702
|
+
}]
|
|
703
|
+
}] }
|
|
704
|
+
});
|
|
705
|
+
function provideSparkContributions(options) {
|
|
706
|
+
return [...provideSparkQueryRowActions(sparkRevertContributionRowAction), ...provideSparkDetailActions({
|
|
707
|
+
id: "spark-revert-contribution",
|
|
708
|
+
component: SparkRevertContributionComponent,
|
|
709
|
+
priority: options?.detailActionPriority ?? 6
|
|
710
|
+
})];
|
|
711
|
+
}
|
|
712
|
+
const sparkContributionRenderers = [{
|
|
713
|
+
name: "contributionAttribution",
|
|
714
|
+
rowComponent: SparkContributionAttributionComponent
|
|
715
|
+
}, {
|
|
716
|
+
name: "lineDiff",
|
|
717
|
+
detailComponent: SparkLineDiffComponent
|
|
718
|
+
}];
|
|
719
|
+
export { SPARK_CONTRIBUTIONS_QUERY_SOURCE, SPARK_REVERT_CONTRIBUTION_PATH, SparkContributionAttributionComponent, SparkLineDiffComponent, SparkRevertContributionComponent, contributionHistoryLink, diffHasChanges, isContributionsQuery, lineDiff, lineDiffSourceOf, lineDiffTextOf, provideSparkContributions, relativeTime, revertContribution, sparkContributionRenderers, sparkRevertContributionRowAction, splitLines };
|
|
720
|
+
|
|
721
|
+
//# sourceMappingURL=mintplayer-ng-spark-contributions.mjs.map
|