@case-framework/survey-core 0.4.0 → 0.4.2
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 +31 -34
- package/build/editor.d.mts +34 -90
- package/build/editor.d.mts.map +1 -1
- package/build/editor.mjs +93 -312
- package/build/editor.mjs.map +1 -1
- package/build/index.d.mts +41 -11
- package/build/index.d.mts.map +1 -1
- package/build/index.mjs +176 -2
- package/build/index.mjs.map +1 -1
- package/build/package.json +26 -26
- package/build/{survey-DShEOjyz.d.mts → survey-DZ3RHkd2.d.mts} +38 -29
- package/build/survey-DZ3RHkd2.d.mts.map +1 -0
- package/build/{survey-yXdl8xkf.mjs → survey-Dxt6iolo.mjs} +24 -2
- package/build/survey-Dxt6iolo.mjs.map +1 -0
- package/package.json +21 -21
- package/build/survey-DShEOjyz.d.mts.map +0 -1
- package/build/survey-yXdl8xkf.mjs.map +0 -1
package/build/editor.mjs
CHANGED
|
@@ -1,302 +1,4 @@
|
|
|
1
|
-
import { $ as generateId,
|
|
2
|
-
//#region src/editor/ai-context.ts
|
|
3
|
-
const DEFAULT_SCOPE_LIMITS = {
|
|
4
|
-
tiny: 40,
|
|
5
|
-
focused: 150,
|
|
6
|
-
full: 500
|
|
7
|
-
};
|
|
8
|
-
const DEFAULT_FOCUS_TREE_LIMIT = 120;
|
|
9
|
-
const DEFAULT_TRANSLATION_SNIPPETS_PER_ITEM = 8;
|
|
10
|
-
const DEFAULT_TRANSLATION_SNIPPET_TEXT_LIMIT = 120;
|
|
11
|
-
const PURPOSE_DEFAULTS = {
|
|
12
|
-
generic: {
|
|
13
|
-
scope: "tiny",
|
|
14
|
-
includeRawSurvey: false,
|
|
15
|
-
includeIndexes: false,
|
|
16
|
-
includeFocusItemTree: false
|
|
17
|
-
},
|
|
18
|
-
"key-suggestion": {
|
|
19
|
-
scope: "tiny",
|
|
20
|
-
includeRawSurvey: false,
|
|
21
|
-
includeIndexes: false,
|
|
22
|
-
includeFocusItemTree: true
|
|
23
|
-
},
|
|
24
|
-
"label-suggestion": {
|
|
25
|
-
scope: "tiny",
|
|
26
|
-
includeRawSurvey: false,
|
|
27
|
-
includeIndexes: false,
|
|
28
|
-
includeFocusItemTree: true
|
|
29
|
-
},
|
|
30
|
-
"item-generation": {
|
|
31
|
-
scope: "focused",
|
|
32
|
-
includeRawSurvey: false,
|
|
33
|
-
includeIndexes: true,
|
|
34
|
-
includeFocusItemTree: true
|
|
35
|
-
},
|
|
36
|
-
translation: {
|
|
37
|
-
scope: "focused",
|
|
38
|
-
includeRawSurvey: false,
|
|
39
|
-
includeIndexes: true,
|
|
40
|
-
includeFocusItemTree: true
|
|
41
|
-
},
|
|
42
|
-
"condition-management": {
|
|
43
|
-
scope: "full",
|
|
44
|
-
includeRawSurvey: true,
|
|
45
|
-
includeIndexes: true,
|
|
46
|
-
includeFocusItemTree: true
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
const sortByItemId = (items) => [...items].sort((a, b) => a.itemId.localeCompare(b.itemId));
|
|
50
|
-
function getChildIds(survey, itemId) {
|
|
51
|
-
const item = survey.surveyItems.get(itemId);
|
|
52
|
-
if (!(item instanceof GroupItemCore)) return [];
|
|
53
|
-
return [...item.items ?? []];
|
|
54
|
-
}
|
|
55
|
-
function buildParentLookup(survey) {
|
|
56
|
-
const lookup = /* @__PURE__ */ new Map();
|
|
57
|
-
for (const item of survey.surveyItems.values()) {
|
|
58
|
-
if (!(item instanceof GroupItemCore)) continue;
|
|
59
|
-
for (const childId of item.items ?? []) lookup.set(childId, item.id);
|
|
60
|
-
}
|
|
61
|
-
return lookup;
|
|
62
|
-
}
|
|
63
|
-
function createFullKeyGetter(survey, parentLookup) {
|
|
64
|
-
const fullKeyCache = /* @__PURE__ */ new Map();
|
|
65
|
-
const getFullKey = (itemId, stack = /* @__PURE__ */ new Set()) => {
|
|
66
|
-
const cached = fullKeyCache.get(itemId);
|
|
67
|
-
if (cached) return cached;
|
|
68
|
-
const item = survey.surveyItems.get(itemId);
|
|
69
|
-
if (!item) return itemId;
|
|
70
|
-
if (stack.has(itemId)) return item.key;
|
|
71
|
-
const parentId = parentLookup.get(itemId);
|
|
72
|
-
if (!parentId) {
|
|
73
|
-
fullKeyCache.set(itemId, item.key);
|
|
74
|
-
return item.key;
|
|
75
|
-
}
|
|
76
|
-
stack.add(itemId);
|
|
77
|
-
const parentFullKey = getFullKey(parentId, stack);
|
|
78
|
-
stack.delete(itemId);
|
|
79
|
-
const fullKey = `${parentFullKey}.${item.key}`;
|
|
80
|
-
fullKeyCache.set(itemId, fullKey);
|
|
81
|
-
return fullKey;
|
|
82
|
-
};
|
|
83
|
-
return getFullKey;
|
|
84
|
-
}
|
|
85
|
-
function buildFullOutline(survey, parentLookup, getFullKey) {
|
|
86
|
-
const outline = [];
|
|
87
|
-
const visited = /* @__PURE__ */ new Set();
|
|
88
|
-
const toNode = (itemId, depth) => {
|
|
89
|
-
const item = survey.surveyItems.get(itemId);
|
|
90
|
-
if (!item) return;
|
|
91
|
-
const childCount = item instanceof GroupItemCore ? item.items.length : 0;
|
|
92
|
-
return {
|
|
93
|
-
itemId,
|
|
94
|
-
parentId: parentLookup.get(itemId),
|
|
95
|
-
depth,
|
|
96
|
-
itemType: item.type,
|
|
97
|
-
key: item.key,
|
|
98
|
-
fullKey: getFullKey(itemId),
|
|
99
|
-
itemLabel: item.metadata?.itemLabel,
|
|
100
|
-
childCount
|
|
101
|
-
};
|
|
102
|
-
};
|
|
103
|
-
const visit = (itemId, depth) => {
|
|
104
|
-
if (visited.has(itemId)) return;
|
|
105
|
-
visited.add(itemId);
|
|
106
|
-
const node = toNode(itemId, depth);
|
|
107
|
-
if (node) outline.push(node);
|
|
108
|
-
for (const childId of getChildIds(survey, itemId)) visit(childId, depth + 1);
|
|
109
|
-
};
|
|
110
|
-
const root = survey.rootItem;
|
|
111
|
-
if (root) visit(root.id, 0);
|
|
112
|
-
const remaining = sortByItemId(Array.from(survey.surveyItems.values()).filter((item) => !visited.has(item.id)).map((item) => ({ itemId: item.id })));
|
|
113
|
-
for (const item of remaining) visit(item.itemId, 0);
|
|
114
|
-
return outline;
|
|
115
|
-
}
|
|
116
|
-
function collectTinyScopeIds(survey, focusItemId) {
|
|
117
|
-
const ids = /* @__PURE__ */ new Set();
|
|
118
|
-
const rootItem = survey.rootItem;
|
|
119
|
-
if (rootItem) ids.add(rootItem.id);
|
|
120
|
-
ids.add(focusItemId);
|
|
121
|
-
for (const id of survey.getItemPath(focusItemId)) ids.add(id);
|
|
122
|
-
for (const sibling of survey.getSiblings(focusItemId)) ids.add(sibling.id);
|
|
123
|
-
for (const childId of getChildIds(survey, focusItemId)) ids.add(childId);
|
|
124
|
-
return ids;
|
|
125
|
-
}
|
|
126
|
-
function addDescendants(survey, itemId, set, maxDepth) {
|
|
127
|
-
const queue = [{
|
|
128
|
-
id: itemId,
|
|
129
|
-
depth: 0
|
|
130
|
-
}];
|
|
131
|
-
while (queue.length > 0) {
|
|
132
|
-
const current = queue.shift();
|
|
133
|
-
if (!current) continue;
|
|
134
|
-
if (current.depth >= maxDepth) continue;
|
|
135
|
-
for (const childId of getChildIds(survey, current.id)) {
|
|
136
|
-
set.add(childId);
|
|
137
|
-
queue.push({
|
|
138
|
-
id: childId,
|
|
139
|
-
depth: current.depth + 1
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
function collectFocusedScopeIds(survey, focusItemId) {
|
|
145
|
-
const ids = collectTinyScopeIds(survey, focusItemId);
|
|
146
|
-
const ancestors = survey.getItemPath(focusItemId);
|
|
147
|
-
addDescendants(survey, focusItemId, ids, 2);
|
|
148
|
-
for (const sibling of survey.getSiblings(focusItemId)) {
|
|
149
|
-
if (sibling.id === focusItemId) continue;
|
|
150
|
-
ids.add(sibling.id);
|
|
151
|
-
addDescendants(survey, sibling.id, ids, 1);
|
|
152
|
-
}
|
|
153
|
-
for (const ancestorId of ancestors) {
|
|
154
|
-
const siblingIds = (survey.getParentItem(ancestorId)?.items ?? []).filter((id) => id !== ancestorId);
|
|
155
|
-
for (const siblingId of siblingIds) {
|
|
156
|
-
ids.add(siblingId);
|
|
157
|
-
addDescendants(survey, siblingId, ids, 1);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
return ids;
|
|
161
|
-
}
|
|
162
|
-
function buildFocusInfo(survey, focusItemId) {
|
|
163
|
-
if (!survey.surveyItems.has(focusItemId)) return;
|
|
164
|
-
const pathItemIds = [...survey.getItemPath(focusItemId), focusItemId];
|
|
165
|
-
return {
|
|
166
|
-
focusItemId,
|
|
167
|
-
parentItemId: survey.getParentItem(focusItemId)?.id,
|
|
168
|
-
pathItemIds,
|
|
169
|
-
siblingItemIds: survey.getSiblings(focusItemId).filter((item) => item.id !== focusItemId).map((item) => item.id),
|
|
170
|
-
childItemIds: getChildIds(survey, focusItemId)
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
const normalizeSnippetText = (text, maxChars) => {
|
|
174
|
-
return text.trim().replace(/\s+/g, " ").slice(0, maxChars);
|
|
175
|
-
};
|
|
176
|
-
const getContentText = (content, maxChars) => {
|
|
177
|
-
const normalized = normalizeSnippetText(getContentPlainText(content), maxChars);
|
|
178
|
-
return normalized.length > 0 ? normalized : null;
|
|
179
|
-
};
|
|
180
|
-
function getItemTranslationSnippets(survey, itemId, maxSnippets, textLimit) {
|
|
181
|
-
const snippets = [];
|
|
182
|
-
const translations = survey.getItemTranslations(itemId);
|
|
183
|
-
if (!translations) return snippets;
|
|
184
|
-
for (const locale of translations.locales) {
|
|
185
|
-
const localeContent = translations.getAllForLocale(locale);
|
|
186
|
-
if (!localeContent) continue;
|
|
187
|
-
for (const [contentKey, content] of Object.entries(localeContent)) {
|
|
188
|
-
const text = getContentText(content, textLimit);
|
|
189
|
-
if (!text) continue;
|
|
190
|
-
snippets.push({
|
|
191
|
-
locale,
|
|
192
|
-
contentKey,
|
|
193
|
-
text
|
|
194
|
-
});
|
|
195
|
-
if (snippets.length >= maxSnippets) return snippets;
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
return snippets;
|
|
199
|
-
}
|
|
200
|
-
function buildFocusItemTree(survey, focusItemId, getFullKey, options) {
|
|
201
|
-
if (!survey.surveyItems.has(focusItemId)) return { truncated: false };
|
|
202
|
-
let remainingBudget = options.treeLimit;
|
|
203
|
-
let truncated = false;
|
|
204
|
-
const visit = (itemId) => {
|
|
205
|
-
if (remainingBudget <= 0) {
|
|
206
|
-
truncated = true;
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
|
-
const item = survey.surveyItems.get(itemId);
|
|
210
|
-
if (!item) return;
|
|
211
|
-
remainingBudget -= 1;
|
|
212
|
-
const siblingKeys = survey.getSiblings(itemId).filter((sibling) => sibling.id !== itemId).map((sibling) => sibling.key);
|
|
213
|
-
const descendants = [];
|
|
214
|
-
if (item instanceof GroupItemCore) for (const childId of item.items) {
|
|
215
|
-
const childNode = visit(childId);
|
|
216
|
-
if (childNode) descendants.push(childNode);
|
|
217
|
-
}
|
|
218
|
-
return {
|
|
219
|
-
itemId: item.id,
|
|
220
|
-
itemType: item.type,
|
|
221
|
-
itemKey: item.key,
|
|
222
|
-
fullKey: getFullKey(item.id),
|
|
223
|
-
itemLabel: item.metadata?.itemLabel,
|
|
224
|
-
siblingKeys,
|
|
225
|
-
translations: getItemTranslationSnippets(survey, item.id, options.snippetsPerItem, options.snippetTextLimit),
|
|
226
|
-
descendants
|
|
227
|
-
};
|
|
228
|
-
};
|
|
229
|
-
return {
|
|
230
|
-
focusItem: visit(focusItemId),
|
|
231
|
-
truncated
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
function buildContextIndexes(survey, fullOutline, purpose) {
|
|
235
|
-
const indexes = { keyIndex: fullOutline.map((node) => ({
|
|
236
|
-
itemId: node.itemId,
|
|
237
|
-
itemType: node.itemType,
|
|
238
|
-
key: node.key,
|
|
239
|
-
fullKey: node.fullKey,
|
|
240
|
-
itemLabel: node.itemLabel,
|
|
241
|
-
path: node.fullKey.split(".").slice(0, -1)
|
|
242
|
-
})) };
|
|
243
|
-
if (purpose === "condition-management") indexes.responseSlots = Object.keys(survey.getAvailableResponseValueSlots());
|
|
244
|
-
return indexes;
|
|
245
|
-
}
|
|
246
|
-
function buildSurveyAIContextPack(survey, options = {}) {
|
|
247
|
-
const purpose = options.purpose ?? "generic";
|
|
248
|
-
const purposeDefaults = PURPOSE_DEFAULTS[purpose];
|
|
249
|
-
const scope = options.scope ?? purposeDefaults.scope;
|
|
250
|
-
const defaultLimit = DEFAULT_SCOPE_LIMITS[scope];
|
|
251
|
-
const outlineLimit = Math.max(1, options.outlineLimit ?? defaultLimit);
|
|
252
|
-
const includeRawSurvey = options.includeRawSurvey ?? purposeDefaults.includeRawSurvey;
|
|
253
|
-
const includeIndexes = options.includeIndexes ?? purposeDefaults.includeIndexes;
|
|
254
|
-
const includeFocusItemTree = options.includeFocusItemTree ?? purposeDefaults.includeFocusItemTree;
|
|
255
|
-
const focusItemId = options.focusItemId;
|
|
256
|
-
const focusExists = Boolean(focusItemId && survey.surveyItems.has(focusItemId));
|
|
257
|
-
const parentLookup = buildParentLookup(survey);
|
|
258
|
-
const getFullKey = createFullKeyGetter(survey, parentLookup);
|
|
259
|
-
const fullOutline = buildFullOutline(survey, parentLookup, getFullKey);
|
|
260
|
-
let scopedOutline = fullOutline;
|
|
261
|
-
if (scope === "tiny" && focusItemId && focusExists) {
|
|
262
|
-
const includedIds = collectTinyScopeIds(survey, focusItemId);
|
|
263
|
-
scopedOutline = fullOutline.filter((node) => includedIds.has(node.itemId));
|
|
264
|
-
} else if (scope === "focused" && focusItemId && focusExists) {
|
|
265
|
-
const includedIds = collectFocusedScopeIds(survey, focusItemId);
|
|
266
|
-
scopedOutline = fullOutline.filter((node) => includedIds.has(node.itemId));
|
|
267
|
-
}
|
|
268
|
-
const outlineTruncated = scopedOutline.length > outlineLimit;
|
|
269
|
-
const outline = outlineTruncated ? scopedOutline.slice(0, outlineLimit) : scopedOutline;
|
|
270
|
-
let focusItemTreeTruncated = false;
|
|
271
|
-
let focusItem;
|
|
272
|
-
if (includeFocusItemTree && focusItemId && focusExists) {
|
|
273
|
-
const focusTreeResult = buildFocusItemTree(survey, focusItemId, getFullKey, {
|
|
274
|
-
treeLimit: Math.max(1, options.focusItemTreeLimit ?? DEFAULT_FOCUS_TREE_LIMIT),
|
|
275
|
-
snippetsPerItem: Math.max(1, options.translationSnippetsPerItemLimit ?? DEFAULT_TRANSLATION_SNIPPETS_PER_ITEM),
|
|
276
|
-
snippetTextLimit: Math.max(1, options.translationSnippetTextLimit ?? DEFAULT_TRANSLATION_SNIPPET_TEXT_LIMIT)
|
|
277
|
-
});
|
|
278
|
-
focusItemTreeTruncated = focusTreeResult.truncated;
|
|
279
|
-
focusItem = focusTreeResult.focusItem;
|
|
280
|
-
}
|
|
281
|
-
return {
|
|
282
|
-
purpose,
|
|
283
|
-
scope,
|
|
284
|
-
surveyKey: survey.surveyKey,
|
|
285
|
-
locales: [...survey.locales],
|
|
286
|
-
itemCount: survey.surveyItems.size,
|
|
287
|
-
outline,
|
|
288
|
-
focus: focusItemId ? buildFocusInfo(survey, focusItemId) : void 0,
|
|
289
|
-
focusItem,
|
|
290
|
-
indexes: includeIndexes ? buildContextIndexes(survey, fullOutline, purpose) : void 0,
|
|
291
|
-
flags: {
|
|
292
|
-
outlineTruncated,
|
|
293
|
-
rawSurveyIncluded: includeRawSurvey,
|
|
294
|
-
focusItemTreeTruncated
|
|
295
|
-
},
|
|
296
|
-
rawSurvey: includeRawSurvey ? survey.serialize() : void 0
|
|
297
|
-
};
|
|
298
|
-
}
|
|
299
|
-
//#endregion
|
|
1
|
+
import { $ as generateId, nt as structuredCloneMethod, t as Survey, u as SurveyItemTranslations, v as GroupItemCore } from "./survey-Dxt6iolo.mjs";
|
|
300
2
|
//#region src/editor/item-copy-paste.ts
|
|
301
3
|
var ItemCopyPaste = class ItemCopyPaste {
|
|
302
4
|
survey;
|
|
@@ -499,14 +201,16 @@ var ItemCopyPaste = class ItemCopyPaste {
|
|
|
499
201
|
static isValidClipboardData(data) {
|
|
500
202
|
if (typeof data !== "object" || data === null || data === void 0) return false;
|
|
501
203
|
const clipboardData = data;
|
|
502
|
-
|
|
204
|
+
if (clipboardData.rootItemId === void 0 || typeof clipboardData.rootItemId !== "string" || !Array.isArray(clipboardData.items) || clipboardData.items.length === 0 || typeof clipboardData.translations !== "object" || clipboardData.translations === null || Array.isArray(clipboardData.translations)) return false;
|
|
205
|
+
return clipboardData.type === "survey-item" && clipboardData.version === "1.0.0" && clipboardData.items.every((item) => typeof item === "object" && item !== null && typeof item.itemId === "string" && item.itemId.length > 0 && typeof item.itemData === "object" && item.itemData !== null && !Array.isArray(item.itemData) && typeof item.itemData.itemType === "string") && clipboardData.items.some((item) => item.itemId === clipboardData.rootItemId);
|
|
503
206
|
}
|
|
504
207
|
};
|
|
505
208
|
//#endregion
|
|
506
209
|
//#region src/editor/undo-redo.ts
|
|
507
210
|
const CommitSource = {
|
|
508
211
|
USER: "user",
|
|
509
|
-
SYSTEM: "system"
|
|
212
|
+
SYSTEM: "system",
|
|
213
|
+
ASSISTANT: "assistant"
|
|
510
214
|
};
|
|
511
215
|
var MemoryCalculator = class {
|
|
512
216
|
static encoder = new TextEncoder();
|
|
@@ -724,6 +428,25 @@ var SurveyEditorUndoRedo = class SurveyEditorUndoRedo {
|
|
|
724
428
|
}));
|
|
725
429
|
}
|
|
726
430
|
/**
|
|
431
|
+
* Get committed history entries after the initial state up to the current index.
|
|
432
|
+
*
|
|
433
|
+
* Redo-only future entries are intentionally omitted so the returned list describes the active
|
|
434
|
+
* change chain from the initial state to the current editor state.
|
|
435
|
+
*/
|
|
436
|
+
getCommitsSinceInitial() {
|
|
437
|
+
return this.history.slice(1, this.currentIndex + 1).map((entry, offset) => {
|
|
438
|
+
const index = offset + 1;
|
|
439
|
+
return {
|
|
440
|
+
index,
|
|
441
|
+
kind: entry.kind,
|
|
442
|
+
meta: entry.meta,
|
|
443
|
+
timestamp: entry.timestamp,
|
|
444
|
+
memorySize: entry.memorySize,
|
|
445
|
+
isCurrent: index === this.currentIndex
|
|
446
|
+
};
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
727
450
|
* Get the current index in the history
|
|
728
451
|
*/
|
|
729
452
|
getCurrentIndex() {
|
|
@@ -911,6 +634,12 @@ var SurveyEditor = class SurveyEditor {
|
|
|
911
634
|
return this._undoRedo.getConfig();
|
|
912
635
|
}
|
|
913
636
|
/**
|
|
637
|
+
* Get committed changes after the initial editor state up to the current undo/redo position.
|
|
638
|
+
*/
|
|
639
|
+
getCommitsSinceInitial() {
|
|
640
|
+
return this._undoRedo.getCommitsSinceInitial();
|
|
641
|
+
}
|
|
642
|
+
/**
|
|
914
643
|
* Serialize the SurveyEditor state to JSON
|
|
915
644
|
* @returns A JSON-serializable object containing the complete editor state
|
|
916
645
|
*/
|
|
@@ -947,8 +676,17 @@ var SurveyEditor = class SurveyEditor {
|
|
|
947
676
|
markAsModified() {
|
|
948
677
|
this._hasUncommittedChanges = true;
|
|
949
678
|
}
|
|
679
|
+
createEditorTimestamp() {
|
|
680
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
681
|
+
}
|
|
682
|
+
touchItemModifiedMetadata(itemId, timestamp = this.createEditorTimestamp()) {
|
|
683
|
+
const item = this._survey.surveyItems.get(itemId);
|
|
684
|
+
if (!item) return;
|
|
685
|
+
item.setModifiedAt(timestamp);
|
|
686
|
+
}
|
|
950
687
|
addItem(target, item, content) {
|
|
951
688
|
this.markAsModified();
|
|
689
|
+
const timestamp = this.createEditorTimestamp();
|
|
952
690
|
let parentGroup;
|
|
953
691
|
if (!target) {
|
|
954
692
|
const rootItem = this._survey.rootItem;
|
|
@@ -964,19 +702,29 @@ var SurveyEditor = class SurveyEditor {
|
|
|
964
702
|
if (parentGroup.hasChild(item.id)) throw new Error(`Item ${item.id} already in this group`);
|
|
965
703
|
const siblings = Array.from(this._survey.surveyItems.values()).filter((sItem) => parentGroup.items?.includes(sItem.id));
|
|
966
704
|
let counter = 1;
|
|
967
|
-
|
|
968
|
-
|
|
705
|
+
const originalKey = item.key;
|
|
706
|
+
let uniqueKey = originalKey;
|
|
707
|
+
while (siblings.some((sibling) => sibling.key === uniqueKey)) {
|
|
708
|
+
uniqueKey = `${originalKey}_${counter}`;
|
|
969
709
|
counter++;
|
|
970
710
|
}
|
|
971
711
|
let insertIndex;
|
|
972
712
|
if (target?.index !== void 0) insertIndex = Math.min(target.index, parentGroup.items.length);
|
|
973
713
|
else insertIndex = parentGroup.items.length;
|
|
714
|
+
item.updateRawItem({
|
|
715
|
+
...item.rawItem,
|
|
716
|
+
key: uniqueKey
|
|
717
|
+
});
|
|
718
|
+
item.setCreatedAt(timestamp);
|
|
719
|
+
item.setModifiedAt(timestamp);
|
|
974
720
|
this._survey.surveyItems.set(item.id, item);
|
|
975
721
|
parentGroup.addChild(item.id, insertIndex);
|
|
722
|
+
this.touchItemModifiedMetadata(parentGroup.id, timestamp);
|
|
976
723
|
if (content) this._survey.translations.setItemTranslations(item.id, content);
|
|
977
724
|
}
|
|
978
725
|
removeItem(itemId, nested = false) {
|
|
979
726
|
this.markAsModified();
|
|
727
|
+
const timestamp = this.createEditorTimestamp();
|
|
980
728
|
const item = this._survey.surveyItems.get(itemId);
|
|
981
729
|
if (!item) return false;
|
|
982
730
|
const parentItem = this._survey.getParentItem(itemId);
|
|
@@ -984,11 +732,15 @@ var SurveyEditor = class SurveyEditor {
|
|
|
984
732
|
if (item instanceof GroupItemCore) for (const childId of item.getChildrenIds()) this.removeItem(childId, true);
|
|
985
733
|
this._survey.surveyItems.delete(itemId);
|
|
986
734
|
this._survey.translations?.onItemDeleted(itemId);
|
|
987
|
-
if (!nested)
|
|
735
|
+
if (!nested) {
|
|
736
|
+
parentItem.removeChild(itemId);
|
|
737
|
+
this.touchItemModifiedMetadata(parentItem.id, timestamp);
|
|
738
|
+
}
|
|
988
739
|
return true;
|
|
989
740
|
}
|
|
990
741
|
moveItem(itemId, newTarget) {
|
|
991
742
|
this.markAsModified();
|
|
743
|
+
const timestamp = this.createEditorTimestamp();
|
|
992
744
|
const item = this._survey.surveyItems.get(itemId);
|
|
993
745
|
if (!item) throw new Error(`Item with id '${itemId}' not found`);
|
|
994
746
|
const targetItem = this._survey.surveyItems.get(newTarget.parentId);
|
|
@@ -997,16 +749,27 @@ var SurveyEditor = class SurveyEditor {
|
|
|
997
749
|
if (this._survey.isDescendantOf(newTarget.parentId, itemId)) throw new Error(`Cannot move item '${itemId}' to its descendant '${newTarget.parentId}'`);
|
|
998
750
|
const currentParentItem = this._survey.getParentItem(itemId);
|
|
999
751
|
if (currentParentItem?.id === newTarget.parentId) throw new Error(`Item '${itemId}' is already in the target parent '${newTarget.parentId}'`);
|
|
1000
|
-
if (currentParentItem)
|
|
752
|
+
if (currentParentItem) {
|
|
753
|
+
const currentParentGroup = currentParentItem;
|
|
754
|
+
currentParentGroup.removeChild(itemId);
|
|
755
|
+
this.touchItemModifiedMetadata(currentParentGroup.id, timestamp);
|
|
756
|
+
}
|
|
1001
757
|
const targetGroup = targetItem;
|
|
1002
758
|
const siblings = Array.from(this._survey.surveyItems.values()).filter((sItem) => targetGroup.hasChild(sItem.id));
|
|
1003
759
|
let counter = 1;
|
|
1004
|
-
|
|
1005
|
-
|
|
760
|
+
let uniqueKey = item.key;
|
|
761
|
+
while (siblings.some((sibling) => sibling.key === uniqueKey)) {
|
|
762
|
+
uniqueKey = `${item.key}_${counter}`;
|
|
1006
763
|
counter++;
|
|
1007
764
|
}
|
|
765
|
+
if (uniqueKey !== item.key) item.updateRawItem({
|
|
766
|
+
...item.rawItem,
|
|
767
|
+
key: uniqueKey
|
|
768
|
+
});
|
|
1008
769
|
const insertIndex = newTarget.index !== void 0 ? Math.min(newTarget.index, targetGroup.items.length) : targetGroup.items.length;
|
|
1009
|
-
targetGroup.
|
|
770
|
+
targetGroup.addChild(itemId, insertIndex);
|
|
771
|
+
this.touchItemModifiedMetadata(targetGroup.id, timestamp);
|
|
772
|
+
this.touchItemModifiedMetadata(itemId, timestamp);
|
|
1010
773
|
return true;
|
|
1011
774
|
}
|
|
1012
775
|
/**
|
|
@@ -1050,13 +813,19 @@ var SurveyEditor = class SurveyEditor {
|
|
|
1050
813
|
const siblingWithSameKey = (parentGroup.items ?? []).filter((id) => id !== itemId).map((id) => this._survey.surveyItems.get(id)).find((s) => s !== void 0 && s.key === newKey);
|
|
1051
814
|
if (siblingWithSameKey) throw new Error(`Key '${newKey}' is already in use by sibling item '${siblingWithSameKey.id}'`);
|
|
1052
815
|
}
|
|
1053
|
-
const newItem = this._survey.createItemFromRaw(
|
|
816
|
+
const newItem = this._survey.createItemFromRaw({
|
|
817
|
+
...merged,
|
|
818
|
+
editorMetadata: existingItem.rawItem.editorMetadata
|
|
819
|
+
});
|
|
820
|
+
newItem.setModifiedAt(this.createEditorTimestamp());
|
|
1054
821
|
this._survey.surveyItems.set(itemId, newItem);
|
|
1055
822
|
this.markAsModified();
|
|
1056
823
|
}
|
|
1057
824
|
updateItemTranslations(itemId, updatedContent) {
|
|
1058
|
-
|
|
825
|
+
const item = this._survey.surveyItems.get(itemId);
|
|
826
|
+
if (!item) return false;
|
|
1059
827
|
this.markAsModified();
|
|
828
|
+
item.setModifiedAt(this.createEditorTimestamp());
|
|
1060
829
|
this._survey.translations.setItemTranslations(itemId, updatedContent);
|
|
1061
830
|
return true;
|
|
1062
831
|
}
|
|
@@ -1190,10 +959,22 @@ var SurveyEditor = class SurveyEditor {
|
|
|
1190
959
|
*/
|
|
1191
960
|
pasteItem(clipboardData, target) {
|
|
1192
961
|
this.markAsModified();
|
|
1193
|
-
|
|
962
|
+
const timestamp = this.createEditorTimestamp();
|
|
963
|
+
const itemIdsBeforePaste = new Set(this._survey.surveyItems.keys());
|
|
964
|
+
const newItemId = new ItemCopyPaste(this._survey).pasteItem(clipboardData, target);
|
|
965
|
+
const pastedItemIds = Array.from(this._survey.surveyItems.keys()).filter((itemId) => !itemIdsBeforePaste.has(itemId));
|
|
966
|
+
for (const itemId of pastedItemIds) {
|
|
967
|
+
const item = this._survey.surveyItems.get(itemId);
|
|
968
|
+
if (item) {
|
|
969
|
+
item.setCreatedAt(timestamp);
|
|
970
|
+
item.setModifiedAt(timestamp);
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
this.touchItemModifiedMetadata(target.parentId, timestamp);
|
|
974
|
+
return newItemId;
|
|
1194
975
|
}
|
|
1195
976
|
};
|
|
1196
977
|
//#endregion
|
|
1197
|
-
export { CommitSource, ItemCopyPaste, SurveyEditor, SurveyEditorUndoRedo
|
|
978
|
+
export { CommitSource, ItemCopyPaste, SurveyEditor, SurveyEditorUndoRedo };
|
|
1198
979
|
|
|
1199
980
|
//# sourceMappingURL=editor.mjs.map
|