@lesliechan721/aw 0.1.0-beta.52 → 0.1.0-beta.54
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/dist/src/tui/config-leaf-editor.d.ts +4 -1
- package/dist/src/tui/config-leaf-editor.js +10 -4
- package/dist/src/tui/config-leaf-editor.js.map +1 -1
- package/dist/src/tui/config-references.d.ts +34 -0
- package/dist/src/tui/config-references.js +70 -0
- package/dist/src/tui/config-references.js.map +1 -0
- package/dist/src/tui/console-app-v4.js +223 -50
- package/dist/src/tui/console-app-v4.js.map +1 -1
- package/dist/src/tui/controller-runtime.js +58 -1
- package/dist/src/tui/controller-runtime.js.map +1 -1
- package/dist/src/tui/controller.d.ts +3 -0
- package/dist/src/tui/controller.js +7 -0
- package/dist/src/tui/controller.js.map +1 -1
- package/dist/src/utils/runtime-skill-closure.js +47 -6
- package/dist/src/utils/runtime-skill-closure.js.map +1 -1
- package/package.json +3 -3
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { configReferenceKey, configReferenceValues, configReferenceScalars, configReferenceSelection, configReferenceMessage, configCrossLayerDependencies } from './config-references.js';
|
|
2
3
|
import { arrayDraftChanged, arrayDraftValue, createConfigArrayDraft, editConfigArrayDraft } from './config-array-draft.js';
|
|
3
4
|
import { PLUGIN_CONFIG_ARRAY_MAX_ITEMS } from '@lesliechan721/aw-plugin-core';
|
|
4
5
|
import { presentConfigValue, safeConfigText } from './config-value-presentation.js';
|
|
@@ -1013,6 +1014,8 @@ export function ConsoleAppV4(props) {
|
|
|
1013
1014
|
const [configLayerCounts, setConfigLayerCounts] = useState({});
|
|
1014
1015
|
const [configLayerPages, setConfigLayerPages] = useState({});
|
|
1015
1016
|
const [configDrafts, setConfigDrafts] = useState({});
|
|
1017
|
+
const [referenceContexts, setReferenceContexts] = useState({});
|
|
1018
|
+
const [referenceContextError, setReferenceContextError] = useState();
|
|
1016
1019
|
const [configCandidate, setConfigCandidate] = useState();
|
|
1017
1020
|
const [arrayDrafts, setArrayDrafts] = useState({});
|
|
1018
1021
|
const [arrayToolsOpen, setArrayToolsOpen] = useState(false);
|
|
@@ -1092,7 +1095,8 @@ export function ConsoleAppV4(props) {
|
|
|
1092
1095
|
const draft = configDrafts[draftScope];
|
|
1093
1096
|
return count + Object.keys(draft?.updates ?? {}).length + (draft?.removes.length ?? 0);
|
|
1094
1097
|
}, 0);
|
|
1095
|
-
const
|
|
1098
|
+
const editingScope = 'layer' in route && route.layer && route.layer.scope !== 'effective' ? route.layer.scope : undefined;
|
|
1099
|
+
const draftUpdates = editingScope ? configDrafts[editingScope]?.updates ?? {} : {
|
|
1096
1100
|
...(configDrafts.user?.updates ?? {}),
|
|
1097
1101
|
...(configDrafts.project?.updates ?? {}),
|
|
1098
1102
|
};
|
|
@@ -1380,7 +1384,7 @@ export function ConsoleAppV4(props) {
|
|
|
1380
1384
|
if (currentFlowId && sourceDraft)
|
|
1381
1385
|
externalDraftFlowIds.current.set(sourceDraft.owner, currentFlowId);
|
|
1382
1386
|
const drafts = [];
|
|
1383
|
-
if ((dirty || configCandidate || nestedPropertyRevision || objectVariantPreview || Object.values(arrayDrafts).some((draft) => draft.initial === undefined ? draft.rows.length > 0 : arrayDraftChanged(draft)) || changedObjectDraftKeys.length > 0) && draftOwner) {
|
|
1387
|
+
if ((dirty || configCandidate && !configCandidate.selectingScope || nestedPropertyRevision || objectVariantPreview || Object.values(arrayDrafts).some((draft) => draft.initial === undefined ? draft.rows.length > 0 : arrayDraftChanged(draft)) || changedObjectDraftKeys.length > 0) && draftOwner) {
|
|
1384
1388
|
const flowId = externalDraftFlowIds.current.get(draftOwner);
|
|
1385
1389
|
drafts.push({
|
|
1386
1390
|
kind: 'configDraft', owner: draftOwner, revision: externalDraftRevision.current.config,
|
|
@@ -1406,7 +1410,30 @@ export function ConsoleAppV4(props) {
|
|
|
1406
1410
|
configDrafts, configCandidate, arrayDrafts, objectDrafts, nestedPropertyRevision, objectVariantPreview, route.name, snapshot.router.currentFlowId, sourceDraft,
|
|
1407
1411
|
]);
|
|
1408
1412
|
useEffect(() => () => props.controller.setExternalDraftState(), [props.controller]);
|
|
1409
|
-
const currentConfigPage = configPageMatches(configPage, configRoute) ? configPage
|
|
1413
|
+
const currentConfigPage = configPageMatches(configPage, configRoute) ? configPage
|
|
1414
|
+
: configRoute && configRoute.layer.scope !== 'effective' ? configLayerPages[configRoute.layer.scope] : undefined;
|
|
1415
|
+
const hasReferenceFields = (configPage ?? configLayerPages.user ?? configLayerPages.project)?.groups
|
|
1416
|
+
.some((group) => group.fields.some((field) => configReferenceScalars(field.definition).length > 0)) ?? false;
|
|
1417
|
+
useEffect(() => {
|
|
1418
|
+
if (!configFlowPluginId || !hasReferenceFields)
|
|
1419
|
+
return;
|
|
1420
|
+
const abort = new AbortController();
|
|
1421
|
+
setReferenceContexts({});
|
|
1422
|
+
setReferenceContextError(undefined);
|
|
1423
|
+
void Promise.allSettled(['user', 'project'].map(async (scope) => ({ scope,
|
|
1424
|
+
context: await props.controller.getConfigReferenceContext(configFlowPluginId, scope, configDrafts[scope] ?? { updates: {}, removes: [] }, abort.signal),
|
|
1425
|
+
}))).then((results) => {
|
|
1426
|
+
if (abort.signal.aborted)
|
|
1427
|
+
return;
|
|
1428
|
+
setReferenceContexts(Object.fromEntries(results.flatMap((result) => result.status === 'fulfilled'
|
|
1429
|
+
? [[result.value.scope, result.value.context]] : [])));
|
|
1430
|
+
if (results.some((result) => result.status === 'rejected'))
|
|
1431
|
+
setReferenceContextError('引用来源读取失败。请返回修复来源配置后重新打开设置。');
|
|
1432
|
+
});
|
|
1433
|
+
return () => abort.abort();
|
|
1434
|
+
}, [props.controller, configFlowPluginId, configDrafts, editingScope, hasReferenceFields]);
|
|
1435
|
+
const crossLayerDependencies = configCrossLayerDependencies(Object.fromEntries((configPage?.groups ?? []).flatMap((group) => group.fields.map((field) => [field.key, field.definition]))), configDrafts, referenceContexts);
|
|
1436
|
+
const referenceContext = editingScope ? referenceContexts[editingScope] : undefined;
|
|
1410
1437
|
const configDraftIssues = (() => {
|
|
1411
1438
|
const issues = [];
|
|
1412
1439
|
for (const draftScope of ['project', 'user']) {
|
|
@@ -1744,9 +1771,11 @@ export function ConsoleAppV4(props) {
|
|
|
1744
1771
|
useEffect(() => {
|
|
1745
1772
|
if (!activeArrayKey || activeArrayDraft || !activeTopField || route.name !== 'configFieldEditor')
|
|
1746
1773
|
return;
|
|
1774
|
+
if (route.layer.scope === 'effective' && configReferenceScalars(activeTopField.definition).length)
|
|
1775
|
+
return;
|
|
1747
1776
|
const value = draftUpdates[activeTopField.key] ?? activeTopField.draftValue ?? activeTopField.value;
|
|
1748
1777
|
setArrayDrafts((current) => ({ ...current, [activeArrayKey]: { ...createConfigArrayDraft(Array.isArray(value) ? value : undefined), evidence: currentConfigPage?.editEvidence } }));
|
|
1749
|
-
}, [activeArrayKey, activeArrayDraft, activeTopField, route.name]);
|
|
1778
|
+
}, [activeArrayKey, activeArrayDraft, activeTopField, route.name, editingScope]);
|
|
1750
1779
|
useEffect(() => {
|
|
1751
1780
|
if (route.name !== 'configFieldEditor' || route.editor !== 'array' || !activeArrayKey || !activeArrayDraft)
|
|
1752
1781
|
return;
|
|
@@ -1811,6 +1840,15 @@ export function ConsoleAppV4(props) {
|
|
|
1811
1840
|
|| activePropertyDefinition?.sensitive === true;
|
|
1812
1841
|
const activeFieldIsConst = activeField && 'const' in activeField.definition && activeField.definition.const !== undefined;
|
|
1813
1842
|
const activePropertyIsConst = activePropertyDefinition && 'const' in activePropertyDefinition && activePropertyDefinition.const !== undefined;
|
|
1843
|
+
const referenceNotice = (scalar, value) => {
|
|
1844
|
+
const selection = referenceContext?.selections[configReferenceKey(scalar)];
|
|
1845
|
+
const message = referenceContextError && !selection ? referenceContextError : configReferenceMessage(scalar, selection, value);
|
|
1846
|
+
const source = 'valueRef' in scalar ? scalar.valueRef.field : '';
|
|
1847
|
+
const pendingSource = editingScope === 'project' && selection?.source !== 'project'
|
|
1848
|
+
&& (Object.hasOwn(configDrafts.user?.updates ?? {}, source) || configDrafts.user?.removes.includes(source));
|
|
1849
|
+
return [message, pendingSource ? `来源 ${source} 在个人默认有未保存修改。请先保存来源配置,再编辑或保存引用配置。` : undefined]
|
|
1850
|
+
.filter(Boolean).join(' ') || undefined;
|
|
1851
|
+
};
|
|
1814
1852
|
useEffect(() => {
|
|
1815
1853
|
if (route.name !== 'configFieldEditor' || !activeField)
|
|
1816
1854
|
return;
|
|
@@ -2973,8 +3011,8 @@ export function ConsoleAppV4(props) {
|
|
|
2973
3011
|
const fieldEditor = (field) => {
|
|
2974
3012
|
return field.type;
|
|
2975
3013
|
};
|
|
2976
|
-
const fieldEditorMode = (field) => (field.choices?.length ?? 0) > 0 ? { mode: 'choices' } : {};
|
|
2977
|
-
const openConfigTarget = (candidate) => {
|
|
3014
|
+
const fieldEditorMode = (field) => (field.choices?.length ?? 0) > 0 || 'valueRef' in field.definition && field.definition.valueRef ? { mode: 'choices' } : {};
|
|
3015
|
+
const openConfigTarget = (candidate, replace = false) => {
|
|
2978
3016
|
const currentFlowId = snapshot.router.currentFlowId;
|
|
2979
3017
|
const storedAnchor = configOverviewAnchors.current.get(candidate.pluginId);
|
|
2980
3018
|
const storedOverviewFrameId = storedAnchor && storedAnchor.flowId === currentFlowId
|
|
@@ -2986,18 +3024,32 @@ export function ConsoleAppV4(props) {
|
|
|
2986
3024
|
...(currentFlowId ? { flowId: currentFlowId } : {}),
|
|
2987
3025
|
...(overviewFrameId ? { overviewFrameId } : {}),
|
|
2988
3026
|
});
|
|
2989
|
-
|
|
3027
|
+
const targetRoute = {
|
|
2990
3028
|
name: 'configLayer',
|
|
2991
3029
|
pluginId: candidate.pluginId,
|
|
2992
3030
|
...(candidate.fieldKey ? { fieldKey: candidate.fieldKey } : {}),
|
|
2993
3031
|
...(candidate.groupId ? { groupId: candidate.groupId } : {}),
|
|
2994
3032
|
...(candidate.presetId ? { presetId: candidate.presetId } : {}),
|
|
2995
|
-
}
|
|
3033
|
+
};
|
|
3034
|
+
if (replace)
|
|
3035
|
+
props.controller.replace(targetRoute);
|
|
3036
|
+
else
|
|
3037
|
+
go(targetRoute);
|
|
2996
3038
|
};
|
|
2997
3039
|
const updateDraft = (key, value) => {
|
|
2998
3040
|
if (!configRoute || !currentConfigPage)
|
|
2999
3041
|
return;
|
|
3000
3042
|
setConfigActionError(undefined);
|
|
3043
|
+
if (activeField && editingScope) {
|
|
3044
|
+
for (const { scalar, value: referencedValue } of configReferenceValues(activeField.definition, value)) {
|
|
3045
|
+
const selected = referenceContext?.selections[configReferenceKey(scalar)];
|
|
3046
|
+
if (!selected || selected.issues.length || !selected.choices.some((choice) => choice.value === referencedValue)) {
|
|
3047
|
+
setObjectError(referenceNotice(scalar, referencedValue));
|
|
3048
|
+
setInputError(referenceNotice(scalar, referencedValue));
|
|
3049
|
+
return;
|
|
3050
|
+
}
|
|
3051
|
+
}
|
|
3052
|
+
}
|
|
3001
3053
|
if (arrayItem && activeArrayKey && activeArrayDraft && activeField) {
|
|
3002
3054
|
const issues = validatePluginConfigValue(activeField.definition, value, key);
|
|
3003
3055
|
if (issues.length) {
|
|
@@ -3021,13 +3073,18 @@ export function ConsoleAppV4(props) {
|
|
|
3021
3073
|
back();
|
|
3022
3074
|
return;
|
|
3023
3075
|
}
|
|
3024
|
-
|
|
3076
|
+
const candidate = {
|
|
3025
3077
|
pluginId: configRoute.pluginId,
|
|
3026
3078
|
fieldKey: key,
|
|
3027
3079
|
groupId: snapshot.router.current.context.configGroupId,
|
|
3028
3080
|
mutations: { [key]: { kind: 'set', value } },
|
|
3029
3081
|
...(activeArrayDraft?.evidence ? { editEvidence: activeArrayDraft.evidence } : {}),
|
|
3030
|
-
}
|
|
3082
|
+
};
|
|
3083
|
+
if (editingScope && activeTopField && configReferenceScalars(activeTopField.definition).length) {
|
|
3084
|
+
openConfigLayerTarget({ scope: editingScope }, candidate);
|
|
3085
|
+
}
|
|
3086
|
+
else
|
|
3087
|
+
openConfigTarget(candidate);
|
|
3031
3088
|
};
|
|
3032
3089
|
const editArray = (edit) => {
|
|
3033
3090
|
if (!activeArrayKey || !activeArrayDraft)
|
|
@@ -3046,7 +3103,7 @@ export function ConsoleAppV4(props) {
|
|
|
3046
3103
|
go({
|
|
3047
3104
|
name: 'configFieldEditor', pluginId: configRoute.pluginId, layer: configRoute.layer,
|
|
3048
3105
|
fieldKey: activeField.key, editor: activeField.definition.items.type,
|
|
3049
|
-
...(activeField.definition.items.choices ? { mode: 'choices' } : {}),
|
|
3106
|
+
...(activeField.definition.items.choices || 'valueRef' in activeField.definition.items && activeField.definition.items.valueRef ? { mode: 'choices' } : {}),
|
|
3050
3107
|
arrayItem: { rowId },
|
|
3051
3108
|
});
|
|
3052
3109
|
};
|
|
@@ -3070,12 +3127,16 @@ export function ConsoleAppV4(props) {
|
|
|
3070
3127
|
if (!configRoute)
|
|
3071
3128
|
return;
|
|
3072
3129
|
setConfigActionError(undefined);
|
|
3073
|
-
|
|
3130
|
+
const candidate = {
|
|
3074
3131
|
pluginId: configRoute.pluginId,
|
|
3075
3132
|
fieldKey: key,
|
|
3076
3133
|
groupId: snapshot.router.current.context.configGroupId,
|
|
3077
3134
|
mutations: { [key]: { kind: 'unset' } },
|
|
3078
|
-
}
|
|
3135
|
+
};
|
|
3136
|
+
if (editingScope && activeTopField && configReferenceScalars(activeTopField.definition).length)
|
|
3137
|
+
openConfigLayerTarget({ scope: editingScope }, candidate);
|
|
3138
|
+
else
|
|
3139
|
+
openConfigTarget(candidate);
|
|
3079
3140
|
};
|
|
3080
3141
|
const updateObjectDraft = (value) => {
|
|
3081
3142
|
if (!activeObjectKey)
|
|
@@ -3110,7 +3171,7 @@ export function ConsoleAppV4(props) {
|
|
|
3110
3171
|
setChangedObjectDraftKeys((current) => current.filter((key) => key !== activeObjectKey));
|
|
3111
3172
|
}
|
|
3112
3173
|
};
|
|
3113
|
-
const objectPropertyStage = (definition) => definition.type === 'boolean' || definition.choices ? 'choices' : 'custom';
|
|
3174
|
+
const objectPropertyStage = (definition) => definition.type === 'boolean' || definition.choices || 'valueRef' in definition && definition.valueRef ? 'choices' : 'custom';
|
|
3114
3175
|
const openObjectProperty = (propertyKey, dynamic) => {
|
|
3115
3176
|
if (!activeField || activeField.definition.type !== 'object')
|
|
3116
3177
|
return;
|
|
@@ -3118,13 +3179,13 @@ export function ConsoleAppV4(props) {
|
|
|
3118
3179
|
?? (activeField.definition.additionalProperties === false
|
|
3119
3180
|
? undefined
|
|
3120
3181
|
: activeField.definition.additionalProperties);
|
|
3121
|
-
if (!definition || 'const' in definition && definition.const !== undefined)
|
|
3182
|
+
if (!definition || 'const' in definition && definition.const !== undefined && !('valueRef' in definition && definition.valueRef))
|
|
3122
3183
|
return;
|
|
3123
3184
|
const exists = activeObjectDraft && Object.hasOwn(activeObjectDraft, propertyKey);
|
|
3124
3185
|
go({
|
|
3125
3186
|
name: 'configObjectPropertyEditor',
|
|
3126
3187
|
pluginId: configRoute.pluginId,
|
|
3127
|
-
layer:
|
|
3188
|
+
layer: configRoute.layer,
|
|
3128
3189
|
fieldKey: activeField.key,
|
|
3129
3190
|
propertyKey,
|
|
3130
3191
|
dynamic,
|
|
@@ -3207,17 +3268,45 @@ export function ConsoleAppV4(props) {
|
|
|
3207
3268
|
mutations,
|
|
3208
3269
|
});
|
|
3209
3270
|
};
|
|
3210
|
-
const openConfigLayerTarget = (layer) => {
|
|
3211
|
-
|
|
3271
|
+
const openConfigLayerTarget = (layer, explicitCandidate) => {
|
|
3272
|
+
const candidate = explicitCandidate ?? configCandidate;
|
|
3273
|
+
if (!candidate)
|
|
3212
3274
|
return;
|
|
3213
|
-
|
|
3275
|
+
const selectedCandidate = { ...candidate,
|
|
3276
|
+
flowId: candidate.flowId ?? snapshot.router.currentFlowId,
|
|
3277
|
+
overviewFrameId: candidate.overviewFrameId ?? configOverviewAnchors.current.get(candidate.pluginId)?.overviewFrameId,
|
|
3278
|
+
};
|
|
3279
|
+
if (selectedCandidate.selectingScope) {
|
|
3280
|
+
const field = configLayerPages[layer.scope]?.groups.flatMap((group) => group.fields).find((field) => field.key === selectedCandidate.fieldKey);
|
|
3281
|
+
if (!field || !configFieldCanSet(field))
|
|
3282
|
+
return;
|
|
3283
|
+
if (field.definition.type === 'array') {
|
|
3284
|
+
const owner = `${candidate.pluginId}\0${field.key}`;
|
|
3285
|
+
const working = arrayDrafts[owner];
|
|
3286
|
+
if (working) {
|
|
3287
|
+
const stored = configDrafts[layer.scope]?.updates[field.key] ?? field.draftValue ?? field.value;
|
|
3288
|
+
setArrayDrafts((current) => ({ ...current, [owner]: { ...working,
|
|
3289
|
+
initial: Array.isArray(stored) ? structuredClone(stored) : undefined,
|
|
3290
|
+
evidence: configLayerPages[layer.scope]?.editEvidence,
|
|
3291
|
+
} }));
|
|
3292
|
+
}
|
|
3293
|
+
}
|
|
3294
|
+
const available = ['user', 'project'].filter((scope) => configLayerPages[scope]?.groups
|
|
3295
|
+
.flatMap((group) => group.fields).some((entry) => entry.key === field.key && configFieldCanSet(entry)));
|
|
3296
|
+
const next = { name: 'configFieldEditor', pluginId: candidate.pluginId, layer, fieldKey: field.key,
|
|
3297
|
+
editor: fieldEditor(field), ...fieldEditorMode(field) };
|
|
3298
|
+
if (available.length === 1)
|
|
3299
|
+
props.controller.replace(next);
|
|
3300
|
+
else
|
|
3301
|
+
go(next);
|
|
3214
3302
|
return;
|
|
3303
|
+
}
|
|
3215
3304
|
const page = configLayerPages[layer.scope];
|
|
3216
3305
|
if (!page)
|
|
3217
3306
|
return;
|
|
3218
3307
|
const fields = new Map(page.groups.flatMap((group) => group.fields)
|
|
3219
3308
|
.map((field) => [field.key, field]));
|
|
3220
|
-
const valid = Object.entries(
|
|
3309
|
+
const valid = Object.entries(selectedCandidate.mutations).every(([key, mutation]) => {
|
|
3221
3310
|
const field = fields.get(key);
|
|
3222
3311
|
return Boolean(field && (mutation.kind === 'set' ? configFieldCanSet(field) : configFieldCanUnset(field)));
|
|
3223
3312
|
});
|
|
@@ -3229,10 +3318,10 @@ export function ConsoleAppV4(props) {
|
|
|
3229
3318
|
const updates = { ...previous.updates };
|
|
3230
3319
|
const removes = new Set(previous.removes);
|
|
3231
3320
|
const editEvidence = { ...previous.editEvidence };
|
|
3232
|
-
for (const [key, mutation] of Object.entries(
|
|
3321
|
+
for (const [key, mutation] of Object.entries(selectedCandidate.mutations)) {
|
|
3233
3322
|
const field = fields.get(key);
|
|
3234
|
-
if (
|
|
3235
|
-
editEvidence[key] =
|
|
3323
|
+
if (selectedCandidate.editEvidence)
|
|
3324
|
+
editEvidence[key] = selectedCandidate.editEvidence;
|
|
3236
3325
|
else
|
|
3237
3326
|
delete editEvidence[key];
|
|
3238
3327
|
if (mutation.kind === 'set') {
|
|
@@ -3255,20 +3344,23 @@ export function ConsoleAppV4(props) {
|
|
|
3255
3344
|
const next = { ...configDrafts, [layer.scope]: { updates, removes: [...removes], editEvidence } };
|
|
3256
3345
|
if (Object.keys(updates).length === 0 && removes.size === 0)
|
|
3257
3346
|
delete next[layer.scope];
|
|
3258
|
-
const target =
|
|
3259
|
-
? configFieldTarget(configPage ?? page,
|
|
3260
|
-
:
|
|
3261
|
-
const returned = props.controller.returnToConfigOverview(
|
|
3347
|
+
const target = selectedCandidate.fieldKey
|
|
3348
|
+
? configFieldTarget(configPage ?? page, selectedCandidate.fieldKey)
|
|
3349
|
+
: selectedCandidate.groupId ? { groupId: selectedCandidate.groupId, focusIndex: 0 } : undefined;
|
|
3350
|
+
const returned = props.controller.returnToConfigOverview(selectedCandidate.flowId, selectedCandidate.overviewFrameId, selectedCandidate.pluginId, target ? { configGroupId: target.groupId, focusIndex: target.focusIndex, scrollOffset: 0 } : undefined);
|
|
3262
3351
|
if (!returned) {
|
|
3263
3352
|
setConfigActionError('设置总览已变化。请返回插件详情后重新打开设置。');
|
|
3264
3353
|
return;
|
|
3265
3354
|
}
|
|
3266
|
-
if (!
|
|
3267
|
-
props.controller.replace({ name: 'configFields', pluginId:
|
|
3355
|
+
if (!selectedCandidate.flowId) {
|
|
3356
|
+
props.controller.replace({ name: 'configFields', pluginId: selectedCandidate.pluginId, layer: { scope: 'effective' } }, target ? { configGroupId: target.groupId, focusIndex: target.focusIndex, scrollOffset: 0 } : undefined);
|
|
3268
3357
|
}
|
|
3269
|
-
if (
|
|
3270
|
-
const owner = `${
|
|
3358
|
+
if (selectedCandidate.fieldKey) {
|
|
3359
|
+
const owner = `${selectedCandidate.pluginId}\0${selectedCandidate.fieldKey}`;
|
|
3360
|
+
const belongsToField = (key) => key === owner || key.startsWith(`${owner}\0`);
|
|
3271
3361
|
setArrayDrafts((current) => Object.fromEntries(Object.entries(current).filter(([key]) => key !== owner)));
|
|
3362
|
+
setObjectDrafts((current) => Object.fromEntries(Object.entries(current).filter(([key]) => !belongsToField(key))));
|
|
3363
|
+
setChangedObjectDraftKeys((current) => current.filter((key) => !belongsToField(key)));
|
|
3272
3364
|
}
|
|
3273
3365
|
setConfigDrafts(next);
|
|
3274
3366
|
setDirty(Object.keys(next).length > 0);
|
|
@@ -3284,6 +3376,8 @@ export function ConsoleAppV4(props) {
|
|
|
3284
3376
|
if (!page)
|
|
3285
3377
|
return false;
|
|
3286
3378
|
const fields = page.groups.flatMap((group) => group.fields);
|
|
3379
|
+
if (configCandidate.selectingScope)
|
|
3380
|
+
return fields.some((field) => field.key === configCandidate.fieldKey && configFieldCanSet(field));
|
|
3287
3381
|
return Object.entries(configCandidate.mutations).every(([key, mutation]) => {
|
|
3288
3382
|
const field = fields.find((entry) => entry.key === key);
|
|
3289
3383
|
return field && (mutation.kind === 'set' ? configFieldCanSet(field) : configFieldCanUnset(field));
|
|
@@ -3291,9 +3385,16 @@ export function ConsoleAppV4(props) {
|
|
|
3291
3385
|
});
|
|
3292
3386
|
if (scopes.length === 1) {
|
|
3293
3387
|
openConfigLayerTarget({ scope: scopes[0] });
|
|
3294
|
-
|
|
3388
|
+
if (!configCandidate.selectingScope)
|
|
3389
|
+
setConfigActionError(`仅可保存到${configLayerLabel({ scope: scopes[0] })};已加入待保存修改。`);
|
|
3295
3390
|
}
|
|
3296
3391
|
}, [route.name, configCandidate, configLayerPages]);
|
|
3392
|
+
useEffect(() => {
|
|
3393
|
+
if (route.name !== 'configFieldEditor' || route.layer.scope !== 'effective' || arrayItem || !activeTopField
|
|
3394
|
+
|| !configReferenceScalars(activeTopField.definition).length)
|
|
3395
|
+
return;
|
|
3396
|
+
openConfigTarget({ pluginId: route.pluginId, fieldKey: activeTopField.key, selectingScope: true, mutations: {} }, true);
|
|
3397
|
+
}, [route.name, route.name === 'configFieldEditor' ? route.layer.scope : '', activeTopField?.key]);
|
|
3297
3398
|
const configChanges = (page, draft) => {
|
|
3298
3399
|
const fields = page.groups.flatMap((group) => group.fields);
|
|
3299
3400
|
return [...Object.keys(draft.updates), ...draft.removes.filter((key) => !Object.hasOwn(draft.updates, key))]
|
|
@@ -3427,6 +3528,16 @@ export function ConsoleAppV4(props) {
|
|
|
3427
3528
|
};
|
|
3428
3529
|
};
|
|
3429
3530
|
const beginConfigSave = async (apply) => {
|
|
3531
|
+
if (crossLayerDependencies.length) {
|
|
3532
|
+
setConfigActionError(`请先保存来源配置,再编辑或保存引用配置:${[...new Set(crossLayerDependencies.map((entry) => entry.source))].join('、')}(个人默认)。请取消相关引用草稿后保存来源。`);
|
|
3533
|
+
return;
|
|
3534
|
+
}
|
|
3535
|
+
if (['user', 'project'].some((scope) => !referenceContexts[scope]
|
|
3536
|
+
&& Object.keys(configDrafts[scope]?.updates ?? {}).some((key) => configPage?.groups.flatMap((group) => group.fields)
|
|
3537
|
+
.some((field) => field.key === key && configReferenceScalars(field.definition).length)))) {
|
|
3538
|
+
setConfigActionError(referenceContextError ?? '正在读取引用来源,请稍后保存。');
|
|
3539
|
+
return;
|
|
3540
|
+
}
|
|
3430
3541
|
if (configDraftIssues.length > 0) {
|
|
3431
3542
|
setConfigActionError('字段已变化。请先放弃失效草稿,或返回继续检查来源。');
|
|
3432
3543
|
return;
|
|
@@ -4494,7 +4605,7 @@ export function ConsoleAppV4(props) {
|
|
|
4494
4605
|
{ label: '自动选择可用 Agent', description: '按当前环境确定可用 Agent,不承诺全部 Agent 可用', meta: '默认', selected: snapshot.portableDraft.agentMode === 'automatic', run: () => { props.controller.setPortableAgentMode('automatic'); go({ name: 'portableScope', pluginId: plugin.pluginId }); } },
|
|
4495
4606
|
{ label: '指定 Agent', description: '输入一个或多个 Agent ID', selected: snapshot.portableDraft.agentMode === 'explicit', run: () => go({ name: 'portableAgentInput', pluginId: plugin.pluginId }) },
|
|
4496
4607
|
];
|
|
4497
|
-
content = _jsx(SemanticRows, { actions: actions, focus: focus, kind: "choice", compact: policy.mode === 'compact' });
|
|
4608
|
+
content = _jsx(SemanticRows, { actions: [...actions], focus: focus, kind: "choice", compact: policy.mode === 'compact' });
|
|
4498
4609
|
}
|
|
4499
4610
|
else if (route.name === 'portableAgentInput' && plugin) {
|
|
4500
4611
|
breadcrumb = `${plugin.displayName} / 通用 Skills / Agent`;
|
|
@@ -5748,7 +5859,7 @@ export function ConsoleAppV4(props) {
|
|
|
5748
5859
|
: candidateSummaryLines[0];
|
|
5749
5860
|
title = selectedField ? `“${selectedField.title}”保存到哪里?`
|
|
5750
5861
|
: selectedPreset ? `“${selectedPreset.title}”保存到哪里?` : '这个值保存到哪里?';
|
|
5751
|
-
description = selectedField
|
|
5862
|
+
description = configCandidate?.selectingScope ? '先选择保存位置,再按该层配置选择引用值。' : selectedField
|
|
5752
5863
|
? `${selectedField.sensitive ? '敏感值只能保存到个人设置。' : '选择后回到分组总览;磁盘尚未改变。'}`
|
|
5753
5864
|
: selectedPreset ? '选择后回到分组总览;磁盘尚未改变。' : '请返回重新选择值。';
|
|
5754
5865
|
if (configActionError)
|
|
@@ -5759,6 +5870,8 @@ export function ConsoleAppV4(props) {
|
|
|
5759
5870
|
if (!page || !configCandidate)
|
|
5760
5871
|
return false;
|
|
5761
5872
|
const fields = page.groups.flatMap((group) => group.fields);
|
|
5873
|
+
if (configCandidate.selectingScope)
|
|
5874
|
+
return fields.some((field) => field.key === configCandidate.fieldKey && configFieldCanSet(field));
|
|
5762
5875
|
return Object.entries(configCandidate.mutations).every(([key, mutation]) => {
|
|
5763
5876
|
const field = fields.find((candidate) => candidate.key === key);
|
|
5764
5877
|
return Boolean(field && (mutation.kind === 'set' ? configFieldCanSet(field) : configFieldCanUnset(field)));
|
|
@@ -5834,12 +5947,31 @@ export function ConsoleAppV4(props) {
|
|
|
5834
5947
|
};
|
|
5835
5948
|
})(),
|
|
5836
5949
|
configKey: field.key,
|
|
5837
|
-
run: () =>
|
|
5838
|
-
|
|
5839
|
-
|
|
5840
|
-
|
|
5950
|
+
run: () => configReferenceScalars(field.definition).length
|
|
5951
|
+
? openConfigTarget({ pluginId: plugin.pluginId, fieldKey: field.key, selectingScope: true, mutations: {} })
|
|
5952
|
+
: go({ name: 'configFieldEditor', pluginId: plugin.pluginId, layer: mutableLayer,
|
|
5953
|
+
fieldKey: field.key, editor: fieldEditor(field), ...fieldEditorMode(field) }),
|
|
5841
5954
|
}));
|
|
5842
5955
|
const operationActions = [
|
|
5956
|
+
...(crossLayerDependencies.length ? [{
|
|
5957
|
+
label: '取消跨层引用草稿,保留来源修改',
|
|
5958
|
+
description: '先保存个人默认来源,再重新编辑当前项目引用。',
|
|
5959
|
+
run: () => {
|
|
5960
|
+
const keys = new Set(crossLayerDependencies.map((entry) => entry.key));
|
|
5961
|
+
const next = { ...configDrafts };
|
|
5962
|
+
const project = next.project;
|
|
5963
|
+
const updates = Object.fromEntries(Object.entries(project.updates).filter(([key]) => !keys.has(key)));
|
|
5964
|
+
if (Object.keys(updates).length || project.removes.length)
|
|
5965
|
+
next.project = { ...project, updates };
|
|
5966
|
+
else
|
|
5967
|
+
delete next.project;
|
|
5968
|
+
setConfigDrafts(next);
|
|
5969
|
+
setObjectDrafts({});
|
|
5970
|
+
setArrayDrafts({});
|
|
5971
|
+
setChangedObjectDraftKeys([]);
|
|
5972
|
+
setConfigActionError('已取消相关引用草稿。请先保存来源,再重新编辑引用。');
|
|
5973
|
+
},
|
|
5974
|
+
}] : []),
|
|
5843
5975
|
...(configDraftIssues.length > 0 ? [{
|
|
5844
5976
|
label: '放弃无法保存的修改',
|
|
5845
5977
|
description: `${configDraftIssues.length} 项未保存修改已不再适用于当前插件设置;放弃后不会修改已保存设置。`,
|
|
@@ -5882,7 +6014,7 @@ export function ConsoleAppV4(props) {
|
|
|
5882
6014
|
beginConfigSave(true);
|
|
5883
6015
|
},
|
|
5884
6016
|
};
|
|
5885
|
-
bottomActions = [configSaveAction, {
|
|
6017
|
+
bottomActions = [configSaveAction, ...(crossLayerDependencies.length ? operationActions.slice(0, 1) : []), {
|
|
5886
6018
|
label: '设置选项', run: () => go({ ...route, view: 'options' }),
|
|
5887
6019
|
}];
|
|
5888
6020
|
actions = [...tabActions, ...bottomActions];
|
|
@@ -5993,7 +6125,8 @@ export function ConsoleAppV4(props) {
|
|
|
5993
6125
|
}
|
|
5994
6126
|
else if (route.name === 'configFieldEditor' && plugin && activeField) {
|
|
5995
6127
|
breadcrumb = `${plugin.displayName} / 设置 / ${activeField.title}`;
|
|
5996
|
-
const
|
|
6128
|
+
const scalarReference = 'valueRef' in activeField.definition && activeField.definition.valueRef ? activeField.definition : undefined;
|
|
6129
|
+
const showChoices = Boolean(scalarReference) || (activeField.choices?.length ?? 0) > 0 && route.mode !== 'custom';
|
|
5997
6130
|
const targetFields = ['project', 'user'].flatMap((scope) => configLayerPages[scope]?.groups.flatMap((group) => group.fields).filter((field) => field.key === activeField.key) ?? []);
|
|
5998
6131
|
const canSet = targetFields.some(configFieldCanSet);
|
|
5999
6132
|
const canUnset = !arrayItem && targetFields.some(configFieldCanUnset);
|
|
@@ -6003,6 +6136,16 @@ export function ConsoleAppV4(props) {
|
|
|
6003
6136
|
actions = canUnset ? [{ label: '删除此覆盖并恢复继承', run: () => removeDraft(activeField.key) }] : [];
|
|
6004
6137
|
content = _jsxs(Box, { flexDirection: "column", children: [_jsx(StatusCard, { status: "warning", title: "\u4EC5\u53EF\u5220\u9664\u65E7\u503C", description: description }), _jsx(SemanticRows, { actions: actions, focus: focus, kind: "action", compact: true })] });
|
|
6005
6138
|
}
|
|
6139
|
+
else if (scalarReference) {
|
|
6140
|
+
const selection = configReferenceSelection(referenceContext, scalarReference);
|
|
6141
|
+
const current = arrayItem ? itemValue : draftUpdates[activeField.key] ?? activeField.draftValue ?? activeField.value;
|
|
6142
|
+
title = `选择${activeField.title}`;
|
|
6143
|
+
description = referenceNotice(scalarReference, current) ?? `选项来自 ${scalarReference.valueRef.field};保存到${editingScope === 'user' ? '个人默认' : '当前项目'}。`;
|
|
6144
|
+
help = '↑↓ 移动 · Enter 使用 · Esc 返回修复来源';
|
|
6145
|
+
actions = selection.choices.map((choice) => ({ label: safeConfigText(choice.title), selected: choice.value === current,
|
|
6146
|
+
run: () => updateDraft(activeField.key, choice.value) }));
|
|
6147
|
+
content = _jsx(SemanticRows, { actions: [...actions], focus: focus, kind: "choice", compact: policy.mode === 'compact' });
|
|
6148
|
+
}
|
|
6006
6149
|
else if ('const' in activeField.definition && activeField.definition.const !== undefined) {
|
|
6007
6150
|
title = activeField.title;
|
|
6008
6151
|
description = '这个值由插件固定,不能编辑。';
|
|
@@ -6047,7 +6190,7 @@ export function ConsoleAppV4(props) {
|
|
|
6047
6190
|
},
|
|
6048
6191
|
}] : []),
|
|
6049
6192
|
];
|
|
6050
|
-
content = _jsx(SemanticRows, { actions: actions, focus: focus, kind: "choice", compact: policy.mode === 'compact' });
|
|
6193
|
+
content = _jsx(SemanticRows, { actions: [...actions], focus: focus, kind: "choice", compact: policy.mode === 'compact' });
|
|
6051
6194
|
}
|
|
6052
6195
|
else if (route.editor === 'array' && activeField.definition.type === 'array') {
|
|
6053
6196
|
title = activeField.title;
|
|
@@ -6079,7 +6222,7 @@ export function ConsoleAppV4(props) {
|
|
|
6079
6222
|
? activeCandidateMutation.value
|
|
6080
6223
|
: (arrayItem ? itemValue : draftUpdates[activeField.key]) ?? activeField.value;
|
|
6081
6224
|
actions = [{ label: '开启', selected: !activeField.sensitive && current === true, run: () => updateDraft(activeField.key, true) }, { label: '关闭', selected: !activeField.sensitive && current === false, run: () => updateDraft(activeField.key, false) }];
|
|
6082
|
-
content = _jsx(SemanticRows, { actions: actions, focus: focus, kind: "choice", compact: policy.mode === 'compact' });
|
|
6225
|
+
content = _jsx(SemanticRows, { actions: [...actions], focus: focus, kind: "choice", compact: policy.mode === 'compact' });
|
|
6083
6226
|
}
|
|
6084
6227
|
else if (route.editor === 'object' && activeField.definition.type === 'object' && activeObjectDraft) {
|
|
6085
6228
|
const objectDefinition = activeField.definition;
|
|
@@ -6112,10 +6255,10 @@ export function ConsoleAppV4(props) {
|
|
|
6112
6255
|
label: definition.title ?? property,
|
|
6113
6256
|
description: definition.description,
|
|
6114
6257
|
meta: propertySummary(property, definition),
|
|
6115
|
-
disabled: 'const' in definition && definition.const !== undefined
|
|
6258
|
+
disabled: 'const' in definition && definition.const !== undefined && !('valueRef' in definition && definition.valueRef)
|
|
6116
6259
|
&& !(definition.required && !Object.hasOwn(activeObjectDraft, property)) ? '插件固定值,不能编辑' : undefined,
|
|
6117
6260
|
run: () => {
|
|
6118
|
-
if ('const' in definition && definition.const !== undefined) {
|
|
6261
|
+
if ('const' in definition && definition.const !== undefined && !('valueRef' in definition && definition.valueRef)) {
|
|
6119
6262
|
updateObjectDraft({ ...activeObjectDraft, [property]: definition.const });
|
|
6120
6263
|
}
|
|
6121
6264
|
else
|
|
@@ -6182,6 +6325,10 @@ export function ConsoleAppV4(props) {
|
|
|
6182
6325
|
: activeField.sensitive ? '当前值不会回显;留空不会自动删除旧值。' : activeField.description ?? '';
|
|
6183
6326
|
content = _jsx(InputCard, { focused: true, title: _jsx(InputDisplay, { value: inputValue, sensitive: activeField.sensitive, placeholder: activeField.placeholder, columns: Math.max(8, size.columns - 8) }), description: inputError ?? (activeField.sensitive ? '输入已隐藏。' : activeField.placeholder ?? '按 Enter 使用输入值。'), status: inputError ? 'error' : undefined });
|
|
6184
6327
|
}
|
|
6328
|
+
if (editingScope === 'user' && activeTopField && configReferenceScalars(activeTopField.definition).length
|
|
6329
|
+
&& configLayerPages.project?.groups.flatMap((group) => group.fields).some((field) => field.key === activeTopField.key && field.configured)) {
|
|
6330
|
+
description = `${description ?? ''} 个人默认在当前项目被覆盖。`;
|
|
6331
|
+
}
|
|
6185
6332
|
if (canUnset) {
|
|
6186
6333
|
const unset = { label: '恢复继承', description: '选择要删除覆盖值的位置', run: () => removeDraft(activeField.key) };
|
|
6187
6334
|
const inputEditor = canSet && !showChoices && (route.editor === 'number' || route.editor === 'string');
|
|
@@ -6218,6 +6365,18 @@ export function ConsoleAppV4(props) {
|
|
|
6218
6365
|
} }, { label: '取消切换', run: () => { setObjectVariantPreview(undefined); back(); } }];
|
|
6219
6366
|
content = _jsxs(Box, { flexDirection: "column", children: [readingPage(readingText, size.columns - 2, Math.max(1, pageActionBudget(4))), _jsx(SemanticRows, { actions: actions, focus: focus, kind: "action", compact: true })] });
|
|
6220
6367
|
}
|
|
6368
|
+
else if (property !== undefined && definition && 'valueRef' in definition && definition.valueRef
|
|
6369
|
+
&& route.stage !== 'action' && route.stage !== 'key') {
|
|
6370
|
+
const selection = configReferenceSelection(referenceContext, definition);
|
|
6371
|
+
const current = activeObjectDraft[property];
|
|
6372
|
+
title = `选择${propertyTitle}`;
|
|
6373
|
+
description = referenceNotice(definition, current) ?? `选项来自 ${definition.valueRef.field}。`;
|
|
6374
|
+
help = '↑↓ 移动 · Enter 使用 · Esc 返回修复来源';
|
|
6375
|
+
actions = selection.choices.map((choice) => ({ label: safeConfigText(choice.title), selected: choice.value === current,
|
|
6376
|
+
run: () => { if (updateObjectProperty(property, choice.value))
|
|
6377
|
+
back(); } }));
|
|
6378
|
+
content = _jsx(SemanticRows, { actions: [...actions], focus: focus, kind: "choice", compact: policy.mode === 'compact' });
|
|
6379
|
+
}
|
|
6221
6380
|
else if (property !== undefined && definition && 'const' in definition && definition.const !== undefined) {
|
|
6222
6381
|
title = propertyTitle;
|
|
6223
6382
|
description = '这个值由插件固定,不能编辑。';
|
|
@@ -6312,13 +6471,13 @@ export function ConsoleAppV4(props) {
|
|
|
6312
6471
|
},
|
|
6313
6472
|
}] : []),
|
|
6314
6473
|
];
|
|
6315
|
-
content = _jsx(SemanticRows, { actions: actions, focus: focus, kind: "choice", compact: policy.mode === 'compact' });
|
|
6474
|
+
content = _jsx(SemanticRows, { actions: [...actions], focus: focus, kind: "choice", compact: policy.mode === 'compact' });
|
|
6316
6475
|
}
|
|
6317
6476
|
else if (property !== undefined && definition && (definition.type === 'array' || definition.type === 'object')) {
|
|
6318
6477
|
title = `编辑${propertyTitle}`;
|
|
6319
6478
|
description = '确认后更新当前对象草稿;Esc 取消此属性的全部修改。';
|
|
6320
6479
|
help = '↑↓ 移动 · Enter 编辑 · a 操作 · c 使用 · Esc 取消';
|
|
6321
|
-
content = _jsx(ConfigLeafEditor, { definition: definition, value: activeObjectDraft[property], propertyKey: property, columns: size.columns, rowBudget: pageActionBudget(1), active: !overlay && !tooSmall && !busy, error: inputError, onDraftChange: setNestedPropertyRevision, onCancel: back, onConfirm: (value) => { if (!updateObjectProperty(property, value))
|
|
6480
|
+
content = _jsx(ConfigLeafEditor, { definition: definition, value: activeObjectDraft[property], propertyKey: property, referenceContext: referenceContext, referenceNotice: referenceNotice, columns: size.columns, rowBudget: pageActionBudget(1), active: !overlay && !tooSmall && !busy, error: inputError, onDraftChange: setNestedPropertyRevision, onCancel: back, onConfirm: (value) => { if (!updateObjectProperty(property, value))
|
|
6322
6481
|
return false; back(); return true; } }, `${snapshot.router.currentFrameId}:${property}`);
|
|
6323
6482
|
}
|
|
6324
6483
|
else if (property !== undefined && definition) {
|
|
@@ -6886,7 +7045,7 @@ export function ConsoleAppV4(props) {
|
|
|
6886
7045
|
{ label: 'Git 仓库', description: '使用现有自动检查默认值;可在修改汇总前单独更改', run: () => selectType('git') },
|
|
6887
7046
|
{ label: '本地目录', description: '使用现有自动检查默认值;可在修改汇总前单独更改', run: () => selectType('path') },
|
|
6888
7047
|
];
|
|
6889
|
-
content = _jsx(SemanticRows, { actions: actions, focus: focus, kind: "choice", compact: policy.mode === 'compact' });
|
|
7048
|
+
content = _jsx(SemanticRows, { actions: [...actions], focus: focus, kind: "choice", compact: policy.mode === 'compact' });
|
|
6890
7049
|
}
|
|
6891
7050
|
else if (route.step === 'refPolicy') {
|
|
6892
7051
|
title = '选择版本来源';
|
|
@@ -9976,6 +10135,7 @@ export function ConsoleAppV4(props) {
|
|
|
9976
10135
|
}
|
|
9977
10136
|
if (route.name === 'configFieldEditor'
|
|
9978
10137
|
&& !activeFieldIsConst
|
|
10138
|
+
&& !(activeField && 'valueRef' in activeField.definition && activeField.definition.valueRef)
|
|
9979
10139
|
&& (route.editor === 'string' || route.editor === 'number')
|
|
9980
10140
|
&& ((activeField?.choices?.length ?? 0) === 0 || route.mode === 'custom')
|
|
9981
10141
|
&& ['project', 'user'].some((scope) => configLayerPages[scope]?.groups.flatMap((group) => group.fields)
|
|
@@ -10024,6 +10184,7 @@ export function ConsoleAppV4(props) {
|
|
|
10024
10184
|
&& (route.stage === 'key' || route.stage === 'custom')
|
|
10025
10185
|
&& !activeVariantPreview
|
|
10026
10186
|
&& !activePropertyIsConst
|
|
10187
|
+
&& !(activePropertyDefinition && 'valueRef' in activePropertyDefinition && activePropertyDefinition.valueRef && route.stage !== 'key')
|
|
10027
10188
|
&& activeField?.definition.type === 'object'
|
|
10028
10189
|
&& activeObjectDraft) {
|
|
10029
10190
|
if (key.escape) {
|
|
@@ -10302,6 +10463,13 @@ export function ConsoleAppV4(props) {
|
|
|
10302
10463
|
back();
|
|
10303
10464
|
}
|
|
10304
10465
|
else if (globalAction === 'back' && route.name === 'configLayer') {
|
|
10466
|
+
if (configCandidate?.selectingScope) {
|
|
10467
|
+
setConfigCandidate(undefined);
|
|
10468
|
+
const owner = `${route.pluginId}\0${route.fieldKey}`;
|
|
10469
|
+
setObjectDrafts((current) => Object.fromEntries(Object.entries(current).filter(([key]) => !key.startsWith(owner))));
|
|
10470
|
+
setArrayDrafts((current) => Object.fromEntries(Object.entries(current).filter(([key]) => key !== owner)));
|
|
10471
|
+
setChangedObjectDraftKeys((current) => current.filter((key) => !key.startsWith(owner)));
|
|
10472
|
+
}
|
|
10305
10473
|
back();
|
|
10306
10474
|
}
|
|
10307
10475
|
else if (globalAction === 'back'
|
|
@@ -10310,12 +10478,17 @@ export function ConsoleAppV4(props) {
|
|
|
10310
10478
|
}
|
|
10311
10479
|
else if (globalAction === 'back'
|
|
10312
10480
|
&& (route.name === 'configFieldEditor' || route.name === 'configFieldAction')) {
|
|
10313
|
-
|
|
10314
|
-
|
|
10481
|
+
const returnToReferenceScope = !arrayItem && editingScope && activeTopField
|
|
10482
|
+
&& configReferenceScalars(activeTopField.definition).length > 0
|
|
10483
|
+
&& ['user', 'project'].filter((scope) => configLayerPages[scope]?.groups.flatMap((group) => group.fields)
|
|
10484
|
+
.some((field) => field.key === activeTopField.key && configFieldCanSet(field))).length > 1;
|
|
10485
|
+
if (!returnToReferenceScope)
|
|
10486
|
+
setConfigCandidate(undefined);
|
|
10487
|
+
if (activeArrayKey && !arrayItem && !returnToReferenceScope) {
|
|
10315
10488
|
setArrayDrafts((current) => Object.fromEntries(Object.entries(current).filter(([key]) => key !== activeArrayKey)));
|
|
10316
10489
|
setObjectError(undefined);
|
|
10317
10490
|
}
|
|
10318
|
-
if (activeObjectKey) {
|
|
10491
|
+
if (activeObjectKey && !returnToReferenceScope) {
|
|
10319
10492
|
setObjectDrafts((current) => Object.fromEntries(Object.entries(current)
|
|
10320
10493
|
.filter(([key]) => key !== activeObjectKey)));
|
|
10321
10494
|
setChangedObjectDraftKeys((current) => current.filter((key) => key !== activeObjectKey));
|