@fgv/ts-res-ui-components 5.0.0-10
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/.rush/temp/03c8b056281d9db0a97d8a6e25eea798a160d393.tar.log +271 -0
- package/.rush/temp/chunked-rush-logs/ts-res-ui-components.build.chunks.jsonl +9 -0
- package/.rush/temp/operation/build/all.log +9 -0
- package/.rush/temp/operation/build/log-chunks.jsonl +9 -0
- package/.rush/temp/operation/build/state.json +3 -0
- package/.rush/temp/shrinkwrap-deps.json +1111 -0
- package/README.md +18 -0
- package/REFACTORING_PLAN.md +171 -0
- package/config/jest.config.json +16 -0
- package/config/jest.setup.js +64 -0
- package/config/rig.json +16 -0
- package/lib/components/common/QualifierContextControl.d.ts +14 -0
- package/lib/components/common/QualifierContextControl.d.ts.map +1 -0
- package/lib/components/common/QualifierContextControl.js +78 -0
- package/lib/components/common/QualifierContextControl.js.map +1 -0
- package/lib/components/common/ResourceListView.d.ts +11 -0
- package/lib/components/common/ResourceListView.d.ts.map +1 -0
- package/lib/components/common/ResourceListView.js +20 -0
- package/lib/components/common/ResourceListView.js.map +1 -0
- package/lib/components/common/ResourceTreeView.d.ts +12 -0
- package/lib/components/common/ResourceTreeView.d.ts.map +1 -0
- package/lib/components/common/ResourceTreeView.js +162 -0
- package/lib/components/common/ResourceTreeView.js.map +1 -0
- package/lib/components/forms/HierarchyEditor.d.ts +10 -0
- package/lib/components/forms/HierarchyEditor.d.ts.map +1 -0
- package/lib/components/forms/HierarchyEditor.js +106 -0
- package/lib/components/forms/HierarchyEditor.js.map +1 -0
- package/lib/components/forms/QualifierEditForm.d.ts +11 -0
- package/lib/components/forms/QualifierEditForm.d.ts.map +1 -0
- package/lib/components/forms/QualifierEditForm.js +181 -0
- package/lib/components/forms/QualifierEditForm.js.map +1 -0
- package/lib/components/forms/QualifierTypeEditForm.d.ts +10 -0
- package/lib/components/forms/QualifierTypeEditForm.d.ts.map +1 -0
- package/lib/components/forms/QualifierTypeEditForm.js +172 -0
- package/lib/components/forms/QualifierTypeEditForm.js.map +1 -0
- package/lib/components/forms/ResourceTypeEditForm.d.ts +10 -0
- package/lib/components/forms/ResourceTypeEditForm.d.ts.map +1 -0
- package/lib/components/forms/ResourceTypeEditForm.js +188 -0
- package/lib/components/forms/ResourceTypeEditForm.js.map +1 -0
- package/lib/components/forms/index.d.ts +9 -0
- package/lib/components/forms/index.d.ts.map +1 -0
- package/lib/components/forms/index.js +5 -0
- package/lib/components/forms/index.js.map +1 -0
- package/lib/components/orchestrator/ResourceOrchestrator.d.ts +14 -0
- package/lib/components/orchestrator/ResourceOrchestrator.d.ts.map +1 -0
- package/lib/components/orchestrator/ResourceOrchestrator.js +278 -0
- package/lib/components/orchestrator/ResourceOrchestrator.js.map +1 -0
- package/lib/components/views/CompiledView/index.d.ts +5 -0
- package/lib/components/views/CompiledView/index.d.ts.map +1 -0
- package/lib/components/views/CompiledView/index.js +595 -0
- package/lib/components/views/CompiledView/index.js.map +1 -0
- package/lib/components/views/ConfigurationView/index.d.ts +5 -0
- package/lib/components/views/ConfigurationView/index.d.ts.map +1 -0
- package/lib/components/views/ConfigurationView/index.js +363 -0
- package/lib/components/views/ConfigurationView/index.js.map +1 -0
- package/lib/components/views/FilterView/index.d.ts +5 -0
- package/lib/components/views/FilterView/index.d.ts.map +1 -0
- package/lib/components/views/FilterView/index.js +463 -0
- package/lib/components/views/FilterView/index.js.map +1 -0
- package/lib/components/views/ImportView/index.d.ts +5 -0
- package/lib/components/views/ImportView/index.d.ts.map +1 -0
- package/lib/components/views/ImportView/index.js +514 -0
- package/lib/components/views/ImportView/index.js.map +1 -0
- package/lib/components/views/ResolutionView/EditableJsonView.d.ts +21 -0
- package/lib/components/views/ResolutionView/EditableJsonView.d.ts.map +1 -0
- package/lib/components/views/ResolutionView/EditableJsonView.js +109 -0
- package/lib/components/views/ResolutionView/EditableJsonView.js.map +1 -0
- package/lib/components/views/ResolutionView/ResolutionEditControls.d.ts +19 -0
- package/lib/components/views/ResolutionView/ResolutionEditControls.d.ts.map +1 -0
- package/lib/components/views/ResolutionView/ResolutionEditControls.js +82 -0
- package/lib/components/views/ResolutionView/ResolutionEditControls.js.map +1 -0
- package/lib/components/views/ResolutionView/index.d.ts +5 -0
- package/lib/components/views/ResolutionView/index.d.ts.map +1 -0
- package/lib/components/views/ResolutionView/index.js +255 -0
- package/lib/components/views/ResolutionView/index.js.map +1 -0
- package/lib/components/views/SourceView/index.d.ts +5 -0
- package/lib/components/views/SourceView/index.d.ts.map +1 -0
- package/lib/components/views/SourceView/index.js +316 -0
- package/lib/components/views/SourceView/index.js.map +1 -0
- package/lib/components/views/ZipLoaderView/index.d.ts +5 -0
- package/lib/components/views/ZipLoaderView/index.d.ts.map +1 -0
- package/lib/components/views/ZipLoaderView/index.js +313 -0
- package/lib/components/views/ZipLoaderView/index.js.map +1 -0
- package/lib/hooks/useConfigurationState.d.ts +46 -0
- package/lib/hooks/useConfigurationState.d.ts.map +1 -0
- package/lib/hooks/useConfigurationState.js +239 -0
- package/lib/hooks/useConfigurationState.js.map +1 -0
- package/lib/hooks/useFilterState.d.ts +7 -0
- package/lib/hooks/useFilterState.d.ts.map +1 -0
- package/lib/hooks/useFilterState.js +80 -0
- package/lib/hooks/useFilterState.js.map +1 -0
- package/lib/hooks/useResolutionState.d.ts +8 -0
- package/lib/hooks/useResolutionState.d.ts.map +1 -0
- package/lib/hooks/useResolutionState.js +253 -0
- package/lib/hooks/useResolutionState.js.map +1 -0
- package/lib/hooks/useResourceData.d.ts +19 -0
- package/lib/hooks/useResourceData.d.ts.map +1 -0
- package/lib/hooks/useResourceData.js +368 -0
- package/lib/hooks/useResourceData.js.map +1 -0
- package/lib/hooks/useViewState.d.ts +10 -0
- package/lib/hooks/useViewState.d.ts.map +1 -0
- package/lib/hooks/useViewState.js +29 -0
- package/lib/hooks/useViewState.js.map +1 -0
- package/lib/index.d.ts +27 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +34 -0
- package/lib/index.js.map +1 -0
- package/lib/test/helpers/testDataLoader.d.ts +37 -0
- package/lib/test/helpers/testDataLoader.d.ts.map +1 -0
- package/lib/test/helpers/testDataLoader.js +171 -0
- package/lib/test/helpers/testDataLoader.js.map +1 -0
- package/lib/test/unit/utils/configurationUtils.test.d.ts +2 -0
- package/lib/test/unit/utils/configurationUtils.test.d.ts.map +1 -0
- package/lib/test/unit/utils/configurationUtils.test.js +497 -0
- package/lib/test/unit/utils/configurationUtils.test.js.map +1 -0
- package/lib/test/unit/utils/fileProcessing.test.d.ts +2 -0
- package/lib/test/unit/utils/fileProcessing.test.d.ts.map +1 -0
- package/lib/test/unit/utils/fileProcessing.test.js +321 -0
- package/lib/test/unit/utils/fileProcessing.test.js.map +1 -0
- package/lib/test/unit/utils/filterResources.test.d.ts +2 -0
- package/lib/test/unit/utils/filterResources.test.d.ts.map +1 -0
- package/lib/test/unit/utils/filterResources.test.js +403 -0
- package/lib/test/unit/utils/filterResources.test.js.map +1 -0
- package/lib/test/unit/utils/resolutionEditing.test.d.ts +2 -0
- package/lib/test/unit/utils/resolutionEditing.test.d.ts.map +1 -0
- package/lib/test/unit/utils/resolutionEditing.test.js +439 -0
- package/lib/test/unit/utils/resolutionEditing.test.js.map +1 -0
- package/lib/test/unit/utils/resolutionUtils.test.d.ts +2 -0
- package/lib/test/unit/utils/resolutionUtils.test.d.ts.map +1 -0
- package/lib/test/unit/utils/resolutionUtils.test.js +397 -0
- package/lib/test/unit/utils/resolutionUtils.test.js.map +1 -0
- package/lib/test/unit/utils/tsResIntegration.test.d.ts +2 -0
- package/lib/test/unit/utils/tsResIntegration.test.d.ts.map +1 -0
- package/lib/test/unit/utils/tsResIntegration.test.js +376 -0
- package/lib/test/unit/utils/tsResIntegration.test.js.map +1 -0
- package/lib/types/index.d.ts +251 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/index.js +2 -0
- package/lib/types/index.js.map +1 -0
- package/lib/utils/configurationUtils.d.ts +74 -0
- package/lib/utils/configurationUtils.d.ts.map +1 -0
- package/lib/utils/configurationUtils.js +359 -0
- package/lib/utils/configurationUtils.js.map +1 -0
- package/lib/utils/fileProcessing.d.ts +18 -0
- package/lib/utils/fileProcessing.d.ts.map +1 -0
- package/lib/utils/fileProcessing.js +142 -0
- package/lib/utils/fileProcessing.js.map +1 -0
- package/lib/utils/filterResources.d.ts +38 -0
- package/lib/utils/filterResources.d.ts.map +1 -0
- package/lib/utils/filterResources.js +153 -0
- package/lib/utils/filterResources.js.map +1 -0
- package/lib/utils/resolutionEditing.d.ts +58 -0
- package/lib/utils/resolutionEditing.d.ts.map +1 -0
- package/lib/utils/resolutionEditing.js +246 -0
- package/lib/utils/resolutionEditing.js.map +1 -0
- package/lib/utils/resolutionUtils.d.ts +28 -0
- package/lib/utils/resolutionUtils.d.ts.map +1 -0
- package/lib/utils/resolutionUtils.js +216 -0
- package/lib/utils/resolutionUtils.js.map +1 -0
- package/lib/utils/tsResIntegration.d.ts +71 -0
- package/lib/utils/tsResIntegration.d.ts.map +1 -0
- package/lib/utils/tsResIntegration.js +294 -0
- package/lib/utils/tsResIntegration.js.map +1 -0
- package/lib/utils/zipLoader/browserZipLoader.d.ts +48 -0
- package/lib/utils/zipLoader/browserZipLoader.d.ts.map +1 -0
- package/lib/utils/zipLoader/browserZipLoader.js +247 -0
- package/lib/utils/zipLoader/browserZipLoader.js.map +1 -0
- package/lib/utils/zipLoader/index.d.ts +8 -0
- package/lib/utils/zipLoader/index.d.ts.map +1 -0
- package/lib/utils/zipLoader/index.js +13 -0
- package/lib/utils/zipLoader/index.js.map +1 -0
- package/lib/utils/zipLoader/nodeZipBuilder.d.ts +55 -0
- package/lib/utils/zipLoader/nodeZipBuilder.d.ts.map +1 -0
- package/lib/utils/zipLoader/nodeZipBuilder.js +98 -0
- package/lib/utils/zipLoader/nodeZipBuilder.js.map +1 -0
- package/lib/utils/zipLoader/types.d.ts +139 -0
- package/lib/utils/zipLoader/types.d.ts.map +1 -0
- package/lib/utils/zipLoader/types.js +2 -0
- package/lib/utils/zipLoader/types.js.map +1 -0
- package/lib/utils/zipLoader/zipUtils.d.ts +53 -0
- package/lib/utils/zipLoader/zipUtils.d.ts.map +1 -0
- package/lib/utils/zipLoader/zipUtils.js +229 -0
- package/lib/utils/zipLoader/zipUtils.js.map +1 -0
- package/package.json +69 -0
- package/rush-logs/ts-res-ui-components.build.cache.log +3 -0
- package/rush-logs/ts-res-ui-components.build.log +9 -0
- package/src/components/common/QualifierContextControl.tsx +151 -0
- package/src/components/common/ResourceListView.tsx +63 -0
- package/src/components/common/ResourceTreeView.tsx +271 -0
- package/src/components/forms/HierarchyEditor.tsx +204 -0
- package/src/components/forms/QualifierEditForm.tsx +355 -0
- package/src/components/forms/QualifierTypeEditForm.tsx +347 -0
- package/src/components/forms/ResourceTypeEditForm.tsx +331 -0
- package/src/components/forms/index.ts +11 -0
- package/src/components/orchestrator/ResourceOrchestrator.tsx +372 -0
- package/src/components/views/CompiledView/index.tsx +922 -0
- package/src/components/views/ConfigurationView/index.tsx +800 -0
- package/src/components/views/FilterView/index.tsx +825 -0
- package/src/components/views/ImportView/index.tsx +717 -0
- package/src/components/views/ResolutionView/EditableJsonView.tsx +214 -0
- package/src/components/views/ResolutionView/ResolutionEditControls.tsx +170 -0
- package/src/components/views/ResolutionView/index.tsx +591 -0
- package/src/components/views/SourceView/index.tsx +536 -0
- package/src/components/views/ZipLoaderView/index.tsx +485 -0
- package/src/hooks/useConfigurationState.ts +374 -0
- package/src/hooks/useFilterState.ts +97 -0
- package/src/hooks/useResolutionState.ts +355 -0
- package/src/hooks/useResourceData.ts +467 -0
- package/src/hooks/useViewState.ts +44 -0
- package/src/index.ts +45 -0
- package/src/test/helpers/testDataLoader.ts +195 -0
- package/src/test/unit/utils/configurationUtils.test.ts +630 -0
- package/src/test/unit/utils/fileProcessing.test.ts +391 -0
- package/src/test/unit/utils/filterResources.test.ts +574 -0
- package/src/test/unit/utils/resolutionEditing.test.ts +556 -0
- package/src/test/unit/utils/resolutionUtils.test.ts +521 -0
- package/src/test/unit/utils/tsResIntegration.test.ts +433 -0
- package/src/types/index.ts +322 -0
- package/src/utils/configurationUtils.ts +424 -0
- package/src/utils/fileProcessing.ts +160 -0
- package/src/utils/filterResources.ts +206 -0
- package/src/utils/resolutionEditing.ts +319 -0
- package/src/utils/resolutionUtils.ts +289 -0
- package/src/utils/tsResIntegration.ts +440 -0
- package/src/utils/zipLoader/browserZipLoader.ts +319 -0
- package/src/utils/zipLoader/index.ts +26 -0
- package/src/utils/zipLoader/nodeZipBuilder.ts +153 -0
- package/src/utils/zipLoader/types.ts +175 -0
- package/src/utils/zipLoader/zipUtils.ts +266 -0
- package/temp/build/typescript/ts_gZid87Hu.json +1 -0
- package/tsconfig.json +15 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import React, { useState, useCallback, useMemo } from 'react';
|
|
2
|
+
import { JsonEditor } from 'json-edit-react';
|
|
3
|
+
import { PencilIcon, CheckIcon, XMarkIcon } from '@heroicons/react/24/outline';
|
|
4
|
+
import { validateEditedResource } from '../../../utils/resolutionEditing';
|
|
5
|
+
export const EditableJsonView = ({ value, resourceId, isEdited = false, editedValue, onSave, onCancel, disabled = false, className = '' }) => {
|
|
6
|
+
const [isEditing, setIsEditing] = useState(false);
|
|
7
|
+
const [currentEditValue, setCurrentEditValue] = useState(null);
|
|
8
|
+
const [validationErrors, setValidationErrors] = useState([]);
|
|
9
|
+
// The display value is either the edited value or the original value
|
|
10
|
+
const displayValue = useMemo(() => {
|
|
11
|
+
if (isEdited && editedValue !== undefined) {
|
|
12
|
+
return editedValue;
|
|
13
|
+
}
|
|
14
|
+
return value;
|
|
15
|
+
}, [value, editedValue, isEdited]);
|
|
16
|
+
// Handle starting an edit
|
|
17
|
+
const handleStartEdit = useCallback(() => {
|
|
18
|
+
if (disabled)
|
|
19
|
+
return;
|
|
20
|
+
setCurrentEditValue(displayValue);
|
|
21
|
+
setIsEditing(true);
|
|
22
|
+
setValidationErrors([]);
|
|
23
|
+
}, [displayValue, disabled]);
|
|
24
|
+
// Handle canceling an edit
|
|
25
|
+
const handleCancelEdit = useCallback(() => {
|
|
26
|
+
setIsEditing(false);
|
|
27
|
+
setCurrentEditValue(null);
|
|
28
|
+
setValidationErrors([]);
|
|
29
|
+
onCancel?.(resourceId);
|
|
30
|
+
}, [resourceId, onCancel]);
|
|
31
|
+
// Handle saving an edit
|
|
32
|
+
const handleSaveEdit = useCallback(() => {
|
|
33
|
+
if (!onSave || currentEditValue === null)
|
|
34
|
+
return;
|
|
35
|
+
// Validate the edited value
|
|
36
|
+
const validation = validateEditedResource(currentEditValue);
|
|
37
|
+
if (!validation.isValid) {
|
|
38
|
+
setValidationErrors(validation.errors);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
// Save the edit
|
|
42
|
+
onSave(resourceId, currentEditValue, value);
|
|
43
|
+
setIsEditing(false);
|
|
44
|
+
setCurrentEditValue(null);
|
|
45
|
+
setValidationErrors([]);
|
|
46
|
+
}, [resourceId, currentEditValue, value, onSave]);
|
|
47
|
+
// Handle changes in the JSON editor
|
|
48
|
+
const handleJsonChange = useCallback((newValue) => {
|
|
49
|
+
setCurrentEditValue(newValue);
|
|
50
|
+
// Clear validation errors when user starts typing
|
|
51
|
+
if (validationErrors.length > 0) {
|
|
52
|
+
setValidationErrors([]);
|
|
53
|
+
}
|
|
54
|
+
}, [validationErrors]);
|
|
55
|
+
// JSON editor configuration
|
|
56
|
+
const jsonEditConfig = useMemo(() => ({
|
|
57
|
+
minHeight: '200px',
|
|
58
|
+
maxHeight: '400px',
|
|
59
|
+
style: {
|
|
60
|
+
container: {
|
|
61
|
+
backgroundColor: '#f9fafb',
|
|
62
|
+
border: '1px solid #d1d5db',
|
|
63
|
+
borderRadius: '0.375rem',
|
|
64
|
+
fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Monaco, Consolas, "Liberation Mono", "Courier New", monospace'
|
|
65
|
+
},
|
|
66
|
+
key: {
|
|
67
|
+
color: '#1f2937',
|
|
68
|
+
fontWeight: '500'
|
|
69
|
+
},
|
|
70
|
+
string: {
|
|
71
|
+
color: '#059669'
|
|
72
|
+
},
|
|
73
|
+
number: {
|
|
74
|
+
color: '#dc2626'
|
|
75
|
+
},
|
|
76
|
+
boolean: {
|
|
77
|
+
color: '#7c3aed'
|
|
78
|
+
},
|
|
79
|
+
null: {
|
|
80
|
+
color: '#6b7280'
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
enableHighlight: true,
|
|
84
|
+
enableClipboard: true
|
|
85
|
+
}), []);
|
|
86
|
+
return (React.createElement("div", { className: `bg-white rounded-lg border ${className}` },
|
|
87
|
+
React.createElement("div", { className: "flex items-center justify-between p-3 border-b bg-gray-50" },
|
|
88
|
+
React.createElement("div", { className: "flex items-center space-x-2" },
|
|
89
|
+
React.createElement("h4", { className: "text-sm font-semibold text-gray-900" }, "Resource Content"),
|
|
90
|
+
isEdited && (React.createElement("span", { className: "inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-800" }, "Edited"))),
|
|
91
|
+
!isEditing && (React.createElement("button", { onClick: handleStartEdit, disabled: disabled, className: "inline-flex items-center px-3 py-1.5 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed", title: "Edit resource content" },
|
|
92
|
+
React.createElement(PencilIcon, { className: "h-4 w-4 mr-1" }),
|
|
93
|
+
"Edit")),
|
|
94
|
+
isEditing && (React.createElement("div", { className: "flex items-center space-x-2" },
|
|
95
|
+
React.createElement("button", { onClick: handleSaveEdit, disabled: validationErrors.length > 0, className: "inline-flex items-center px-3 py-1.5 text-sm font-medium text-white bg-green-600 border border-transparent rounded-md hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 disabled:opacity-50 disabled:cursor-not-allowed", title: "Save changes" },
|
|
96
|
+
React.createElement(CheckIcon, { className: "h-4 w-4 mr-1" }),
|
|
97
|
+
"Save"),
|
|
98
|
+
React.createElement("button", { onClick: handleCancelEdit, className: "inline-flex items-center px-3 py-1.5 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500", title: "Cancel changes" },
|
|
99
|
+
React.createElement(XMarkIcon, { className: "h-4 w-4 mr-1" }),
|
|
100
|
+
"Cancel")))),
|
|
101
|
+
validationErrors.length > 0 && (React.createElement("div", { className: "p-3 border-b bg-red-50" },
|
|
102
|
+
React.createElement("div", { className: "text-sm text-red-800" },
|
|
103
|
+
React.createElement("p", { className: "font-medium mb-1" }, "Validation Errors:"),
|
|
104
|
+
React.createElement("ul", { className: "list-disc list-inside space-y-1" }, validationErrors.map((error, index) => (React.createElement("li", { key: index }, error))))))),
|
|
105
|
+
React.createElement("div", { className: "p-3" }, isEditing ? (React.createElement(JsonEditor, { data: currentEditValue, setData: handleJsonChange, ...jsonEditConfig })) : (React.createElement("pre", { className: "text-sm font-mono text-gray-800 bg-gray-50 p-3 rounded border overflow-x-auto whitespace-pre-wrap" }, JSON.stringify(displayValue, null, 2)))),
|
|
106
|
+
isEditing && (React.createElement("div", { className: "px-3 pb-3" },
|
|
107
|
+
React.createElement("p", { className: "text-xs text-gray-500" }, "Edit the JSON content above. Changes will be saved as a new candidate with the current resolution context.")))));
|
|
108
|
+
};
|
|
109
|
+
//# sourceMappingURL=EditableJsonView.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EditableJsonView.js","sourceRoot":"","sources":["../../../../src/components/views/ResolutionView/EditableJsonView.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useState, useCallback, useMemo } from 'react';\nimport { JsonEditor } from 'json-edit-react';\nimport { PencilIcon, CheckIcon, XMarkIcon } from '@heroicons/react/24/outline';\nimport { validateEditedResource } from '../../../utils/resolutionEditing';\n\nexport interface EditableJsonViewProps {\n /** The original JSON value */\n value: any;\n /** The resource ID for tracking edits */\n resourceId: string;\n /** Whether this resource has been edited */\n isEdited?: boolean;\n /** The current edited value if any */\n editedValue?: any;\n /** Callback when the user saves an edit */\n onSave?: (resourceId: string, editedValue: any, originalValue: any) => void;\n /** Callback when the user cancels an edit */\n onCancel?: (resourceId: string) => void;\n /** Whether editing is currently disabled */\n disabled?: boolean;\n /** Additional CSS classes */\n className?: string;\n}\n\nexport const EditableJsonView: React.FC<EditableJsonViewProps> = ({\n value,\n resourceId,\n isEdited = false,\n editedValue,\n onSave,\n onCancel,\n disabled = false,\n className = ''\n}) => {\n const [isEditing, setIsEditing] = useState(false);\n const [currentEditValue, setCurrentEditValue] = useState<any>(null);\n const [validationErrors, setValidationErrors] = useState<string[]>([]);\n\n // The display value is either the edited value or the original value\n const displayValue = useMemo(() => {\n if (isEdited && editedValue !== undefined) {\n return editedValue;\n }\n return value;\n }, [value, editedValue, isEdited]);\n\n // Handle starting an edit\n const handleStartEdit = useCallback(() => {\n if (disabled) return;\n setCurrentEditValue(displayValue);\n setIsEditing(true);\n setValidationErrors([]);\n }, [displayValue, disabled]);\n\n // Handle canceling an edit\n const handleCancelEdit = useCallback(() => {\n setIsEditing(false);\n setCurrentEditValue(null);\n setValidationErrors([]);\n onCancel?.(resourceId);\n }, [resourceId, onCancel]);\n\n // Handle saving an edit\n const handleSaveEdit = useCallback(() => {\n if (!onSave || currentEditValue === null) return;\n\n // Validate the edited value\n const validation = validateEditedResource(currentEditValue);\n if (!validation.isValid) {\n setValidationErrors(validation.errors);\n return;\n }\n\n // Save the edit\n onSave(resourceId, currentEditValue, value);\n setIsEditing(false);\n setCurrentEditValue(null);\n setValidationErrors([]);\n }, [resourceId, currentEditValue, value, onSave]);\n\n // Handle changes in the JSON editor\n const handleJsonChange = useCallback(\n (newValue: any) => {\n setCurrentEditValue(newValue);\n\n // Clear validation errors when user starts typing\n if (validationErrors.length > 0) {\n setValidationErrors([]);\n }\n },\n [validationErrors]\n );\n\n // JSON editor configuration\n const jsonEditConfig = useMemo(\n () => ({\n minHeight: '200px',\n maxHeight: '400px',\n style: {\n container: {\n backgroundColor: '#f9fafb',\n border: '1px solid #d1d5db',\n borderRadius: '0.375rem',\n fontFamily:\n 'ui-monospace, SFMono-Regular, \"SF Mono\", Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace'\n },\n key: {\n color: '#1f2937',\n fontWeight: '500'\n },\n string: {\n color: '#059669'\n },\n number: {\n color: '#dc2626'\n },\n boolean: {\n color: '#7c3aed'\n },\n null: {\n color: '#6b7280'\n }\n },\n enableHighlight: true,\n enableClipboard: true\n }),\n []\n );\n\n return (\n <div className={`bg-white rounded-lg border ${className}`}>\n {/* Header with edit controls */}\n <div className=\"flex items-center justify-between p-3 border-b bg-gray-50\">\n <div className=\"flex items-center space-x-2\">\n <h4 className=\"text-sm font-semibold text-gray-900\">Resource Content</h4>\n {isEdited && (\n <span className=\"inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-800\">\n Edited\n </span>\n )}\n </div>\n\n {!isEditing && (\n <button\n onClick={handleStartEdit}\n disabled={disabled}\n className=\"inline-flex items-center px-3 py-1.5 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed\"\n title=\"Edit resource content\"\n >\n <PencilIcon className=\"h-4 w-4 mr-1\" />\n Edit\n </button>\n )}\n\n {isEditing && (\n <div className=\"flex items-center space-x-2\">\n <button\n onClick={handleSaveEdit}\n disabled={validationErrors.length > 0}\n className=\"inline-flex items-center px-3 py-1.5 text-sm font-medium text-white bg-green-600 border border-transparent rounded-md hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 disabled:opacity-50 disabled:cursor-not-allowed\"\n title=\"Save changes\"\n >\n <CheckIcon className=\"h-4 w-4 mr-1\" />\n Save\n </button>\n <button\n onClick={handleCancelEdit}\n className=\"inline-flex items-center px-3 py-1.5 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500\"\n title=\"Cancel changes\"\n >\n <XMarkIcon className=\"h-4 w-4 mr-1\" />\n Cancel\n </button>\n </div>\n )}\n </div>\n\n {/* Validation errors */}\n {validationErrors.length > 0 && (\n <div className=\"p-3 border-b bg-red-50\">\n <div className=\"text-sm text-red-800\">\n <p className=\"font-medium mb-1\">Validation Errors:</p>\n <ul className=\"list-disc list-inside space-y-1\">\n {validationErrors.map((error, index) => (\n <li key={index}>{error}</li>\n ))}\n </ul>\n </div>\n </div>\n )}\n\n {/* JSON content */}\n <div className=\"p-3\">\n {isEditing ? (\n <JsonEditor data={currentEditValue} setData={handleJsonChange} {...jsonEditConfig} />\n ) : (\n <pre className=\"text-sm font-mono text-gray-800 bg-gray-50 p-3 rounded border overflow-x-auto whitespace-pre-wrap\">\n {JSON.stringify(displayValue, null, 2)}\n </pre>\n )}\n </div>\n\n {/* Help text */}\n {isEditing && (\n <div className=\"px-3 pb-3\">\n <p className=\"text-xs text-gray-500\">\n Edit the JSON content above. Changes will be saved as a new candidate with the current resolution\n context.\n </p>\n </div>\n )}\n </div>\n );\n};\n"]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface ResolutionEditControlsProps {
|
|
3
|
+
/** Number of unsaved edits */
|
|
4
|
+
editCount: number;
|
|
5
|
+
/** Whether edit application is currently in progress */
|
|
6
|
+
isApplying: boolean;
|
|
7
|
+
/** Whether any edits exist to operate on */
|
|
8
|
+
hasEdits: boolean;
|
|
9
|
+
/** Callback to apply all pending edits */
|
|
10
|
+
onApplyEdits?: () => Promise<void>;
|
|
11
|
+
/** Callback to discard all pending edits */
|
|
12
|
+
onDiscardEdits?: () => void;
|
|
13
|
+
/** Whether the controls should be disabled */
|
|
14
|
+
disabled?: boolean;
|
|
15
|
+
/** Additional CSS classes */
|
|
16
|
+
className?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare const ResolutionEditControls: React.FC<ResolutionEditControlsProps>;
|
|
19
|
+
//# sourceMappingURL=ResolutionEditControls.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResolutionEditControls.d.ts","sourceRoot":"","sources":["../../../../src/components/views/ResolutionView/ResolutionEditControls.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AASxC,MAAM,WAAW,2BAA2B;IAC1C,8BAA8B;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,UAAU,EAAE,OAAO,CAAC;IACpB,4CAA4C;IAC5C,QAAQ,EAAE,OAAO,CAAC;IAClB,0CAA0C;IAC1C,YAAY,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,4CAA4C;IAC5C,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,sBAAsB,EAAE,KAAK,CAAC,EAAE,CAAC,2BAA2B,CA+IxE,CAAC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { CheckIcon, XMarkIcon, ExclamationTriangleIcon, ArrowPathIcon, DocumentTextIcon } from '@heroicons/react/24/outline';
|
|
3
|
+
export const ResolutionEditControls = ({ editCount, isApplying, hasEdits, onApplyEdits, onDiscardEdits, disabled = false, className = '' }) => {
|
|
4
|
+
const [showDiscardConfirm, setShowDiscardConfirm] = useState(false);
|
|
5
|
+
const handleApplyEdits = async () => {
|
|
6
|
+
if (onApplyEdits && !isApplying && hasEdits) {
|
|
7
|
+
await onApplyEdits();
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
const handleDiscardEdits = () => {
|
|
11
|
+
if (onDiscardEdits && hasEdits && !isApplying) {
|
|
12
|
+
onDiscardEdits();
|
|
13
|
+
setShowDiscardConfirm(false);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
const handleDiscardClick = () => {
|
|
17
|
+
if (hasEdits) {
|
|
18
|
+
setShowDiscardConfirm(true);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
if (!hasEdits && !isApplying) {
|
|
22
|
+
return (React.createElement("div", { className: `bg-gray-50 rounded-lg border border-gray-200 p-4 ${className}` },
|
|
23
|
+
React.createElement("div", { className: "flex items-center justify-center text-gray-500" },
|
|
24
|
+
React.createElement(DocumentTextIcon, { className: "h-5 w-5 mr-2" }),
|
|
25
|
+
React.createElement("span", { className: "text-sm" }, "No pending edits"))));
|
|
26
|
+
}
|
|
27
|
+
return (React.createElement("div", { className: `bg-white rounded-lg border border-gray-200 shadow-sm ${className}` },
|
|
28
|
+
React.createElement("div", { className: "p-4" },
|
|
29
|
+
React.createElement("div", { className: "flex items-center justify-between mb-4" },
|
|
30
|
+
React.createElement("div", { className: "flex items-center" },
|
|
31
|
+
React.createElement("div", { className: "flex items-center space-x-2" },
|
|
32
|
+
React.createElement("h3", { className: "text-lg font-semibold text-gray-900" }, "Pending Edits"),
|
|
33
|
+
React.createElement("span", { className: "inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800" },
|
|
34
|
+
editCount,
|
|
35
|
+
" edit",
|
|
36
|
+
editCount !== 1 ? 's' : ''))),
|
|
37
|
+
isApplying && (React.createElement("div", { className: "flex items-center text-blue-600" },
|
|
38
|
+
React.createElement(ArrowPathIcon, { className: "h-4 w-4 mr-1 animate-spin" }),
|
|
39
|
+
React.createElement("span", { className: "text-sm font-medium" }, "Applying...")))),
|
|
40
|
+
React.createElement("p", { className: "text-sm text-gray-600 mb-4" },
|
|
41
|
+
"You have ",
|
|
42
|
+
editCount,
|
|
43
|
+
" unsaved edit",
|
|
44
|
+
editCount !== 1 ? 's' : '',
|
|
45
|
+
".",
|
|
46
|
+
' ',
|
|
47
|
+
editCount === 1 ? 'This edit' : 'These edits',
|
|
48
|
+
" will be applied as new candidate",
|
|
49
|
+
editCount !== 1 ? 's' : '',
|
|
50
|
+
" with the current resolution context."),
|
|
51
|
+
!showDiscardConfirm ? (React.createElement("div", { className: "flex items-center space-x-3" },
|
|
52
|
+
React.createElement("button", { onClick: handleApplyEdits, disabled: disabled || isApplying || !hasEdits, className: "inline-flex items-center px-4 py-2 text-sm font-medium text-white bg-green-600 border border-transparent rounded-md hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 disabled:opacity-50 disabled:cursor-not-allowed" }, isApplying ? (React.createElement(React.Fragment, null,
|
|
53
|
+
React.createElement(ArrowPathIcon, { className: "h-4 w-4 mr-2 animate-spin" }),
|
|
54
|
+
"Applying Edits...")) : (React.createElement(React.Fragment, null,
|
|
55
|
+
React.createElement(CheckIcon, { className: "h-4 w-4 mr-2" }),
|
|
56
|
+
"Apply Edits"))),
|
|
57
|
+
React.createElement("button", { onClick: handleDiscardClick, disabled: disabled || isApplying || !hasEdits, className: "inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed" },
|
|
58
|
+
React.createElement(XMarkIcon, { className: "h-4 w-4 mr-2" }),
|
|
59
|
+
"Discard Edits"))) : (
|
|
60
|
+
/* Discard confirmation */
|
|
61
|
+
React.createElement("div", { className: "bg-yellow-50 border border-yellow-200 rounded-lg p-4" },
|
|
62
|
+
React.createElement("div", { className: "flex items-start" },
|
|
63
|
+
React.createElement(ExclamationTriangleIcon, { className: "h-5 w-5 text-yellow-400 mt-0.5 mr-3" }),
|
|
64
|
+
React.createElement("div", { className: "flex-1" },
|
|
65
|
+
React.createElement("h4", { className: "text-sm font-medium text-yellow-800 mb-1" }, "Confirm Discard"),
|
|
66
|
+
React.createElement("p", { className: "text-sm text-yellow-700 mb-3" },
|
|
67
|
+
"Are you sure you want to discard ",
|
|
68
|
+
editCount,
|
|
69
|
+
" unsaved edit",
|
|
70
|
+
editCount !== 1 ? 's' : '',
|
|
71
|
+
"? This action cannot be undone."),
|
|
72
|
+
React.createElement("div", { className: "flex items-center space-x-3" },
|
|
73
|
+
React.createElement("button", { onClick: handleDiscardEdits, className: "inline-flex items-center px-3 py-1.5 text-sm font-medium text-white bg-red-600 border border-transparent rounded hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500" },
|
|
74
|
+
React.createElement(XMarkIcon, { className: "h-4 w-4 mr-1" }),
|
|
75
|
+
"Yes, Discard"),
|
|
76
|
+
React.createElement("button", { onClick: () => setShowDiscardConfirm(false), className: "inline-flex items-center px-3 py-1.5 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500" }, "Cancel"))))))),
|
|
77
|
+
hasEdits && !showDiscardConfirm && (React.createElement("div", { className: "border-t border-gray-200 px-4 py-3 bg-blue-50" },
|
|
78
|
+
React.createElement("p", { className: "text-xs text-blue-700" },
|
|
79
|
+
React.createElement("strong", null, "Note:"),
|
|
80
|
+
" Applying edits will rebuild the entire resource system with your changes. This may take a moment and will update all resolution results.")))));
|
|
81
|
+
};
|
|
82
|
+
//# sourceMappingURL=ResolutionEditControls.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResolutionEditControls.js","sourceRoot":"","sources":["../../../../src/components/views/ResolutionView/ResolutionEditControls.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useState } from 'react';\nimport {\n CheckIcon,\n XMarkIcon,\n ExclamationTriangleIcon,\n ArrowPathIcon,\n DocumentTextIcon\n} from '@heroicons/react/24/outline';\n\nexport interface ResolutionEditControlsProps {\n /** Number of unsaved edits */\n editCount: number;\n /** Whether edit application is currently in progress */\n isApplying: boolean;\n /** Whether any edits exist to operate on */\n hasEdits: boolean;\n /** Callback to apply all pending edits */\n onApplyEdits?: () => Promise<void>;\n /** Callback to discard all pending edits */\n onDiscardEdits?: () => void;\n /** Whether the controls should be disabled */\n disabled?: boolean;\n /** Additional CSS classes */\n className?: string;\n}\n\nexport const ResolutionEditControls: React.FC<ResolutionEditControlsProps> = ({\n editCount,\n isApplying,\n hasEdits,\n onApplyEdits,\n onDiscardEdits,\n disabled = false,\n className = ''\n}) => {\n const [showDiscardConfirm, setShowDiscardConfirm] = useState(false);\n\n const handleApplyEdits = async () => {\n if (onApplyEdits && !isApplying && hasEdits) {\n await onApplyEdits();\n }\n };\n\n const handleDiscardEdits = () => {\n if (onDiscardEdits && hasEdits && !isApplying) {\n onDiscardEdits();\n setShowDiscardConfirm(false);\n }\n };\n\n const handleDiscardClick = () => {\n if (hasEdits) {\n setShowDiscardConfirm(true);\n }\n };\n\n if (!hasEdits && !isApplying) {\n return (\n <div className={`bg-gray-50 rounded-lg border border-gray-200 p-4 ${className}`}>\n <div className=\"flex items-center justify-center text-gray-500\">\n <DocumentTextIcon className=\"h-5 w-5 mr-2\" />\n <span className=\"text-sm\">No pending edits</span>\n </div>\n </div>\n );\n }\n\n return (\n <div className={`bg-white rounded-lg border border-gray-200 shadow-sm ${className}`}>\n <div className=\"p-4\">\n {/* Header */}\n <div className=\"flex items-center justify-between mb-4\">\n <div className=\"flex items-center\">\n <div className=\"flex items-center space-x-2\">\n <h3 className=\"text-lg font-semibold text-gray-900\">Pending Edits</h3>\n <span className=\"inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800\">\n {editCount} edit{editCount !== 1 ? 's' : ''}\n </span>\n </div>\n </div>\n\n {isApplying && (\n <div className=\"flex items-center text-blue-600\">\n <ArrowPathIcon className=\"h-4 w-4 mr-1 animate-spin\" />\n <span className=\"text-sm font-medium\">Applying...</span>\n </div>\n )}\n </div>\n\n {/* Info text */}\n <p className=\"text-sm text-gray-600 mb-4\">\n You have {editCount} unsaved edit{editCount !== 1 ? 's' : ''}.{' '}\n {editCount === 1 ? 'This edit' : 'These edits'} will be applied as new candidate\n {editCount !== 1 ? 's' : ''} with the current resolution context.\n </p>\n\n {/* Action buttons */}\n {!showDiscardConfirm ? (\n <div className=\"flex items-center space-x-3\">\n <button\n onClick={handleApplyEdits}\n disabled={disabled || isApplying || !hasEdits}\n className=\"inline-flex items-center px-4 py-2 text-sm font-medium text-white bg-green-600 border border-transparent rounded-md hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n {isApplying ? (\n <>\n <ArrowPathIcon className=\"h-4 w-4 mr-2 animate-spin\" />\n Applying Edits...\n </>\n ) : (\n <>\n <CheckIcon className=\"h-4 w-4 mr-2\" />\n Apply Edits\n </>\n )}\n </button>\n\n <button\n onClick={handleDiscardClick}\n disabled={disabled || isApplying || !hasEdits}\n className=\"inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n <XMarkIcon className=\"h-4 w-4 mr-2\" />\n Discard Edits\n </button>\n </div>\n ) : (\n /* Discard confirmation */\n <div className=\"bg-yellow-50 border border-yellow-200 rounded-lg p-4\">\n <div className=\"flex items-start\">\n <ExclamationTriangleIcon className=\"h-5 w-5 text-yellow-400 mt-0.5 mr-3\" />\n <div className=\"flex-1\">\n <h4 className=\"text-sm font-medium text-yellow-800 mb-1\">Confirm Discard</h4>\n <p className=\"text-sm text-yellow-700 mb-3\">\n Are you sure you want to discard {editCount} unsaved edit{editCount !== 1 ? 's' : ''}? This\n action cannot be undone.\n </p>\n <div className=\"flex items-center space-x-3\">\n <button\n onClick={handleDiscardEdits}\n className=\"inline-flex items-center px-3 py-1.5 text-sm font-medium text-white bg-red-600 border border-transparent rounded hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500\"\n >\n <XMarkIcon className=\"h-4 w-4 mr-1\" />\n Yes, Discard\n </button>\n <button\n onClick={() => setShowDiscardConfirm(false)}\n className=\"inline-flex items-center px-3 py-1.5 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500\"\n >\n Cancel\n </button>\n </div>\n </div>\n </div>\n </div>\n )}\n </div>\n\n {/* Warning about system rebuild */}\n {hasEdits && !showDiscardConfirm && (\n <div className=\"border-t border-gray-200 px-4 py-3 bg-blue-50\">\n <p className=\"text-xs text-blue-700\">\n <strong>Note:</strong> Applying edits will rebuild the entire resource system with your changes.\n This may take a moment and will update all resolution results.\n </p>\n </div>\n )}\n </div>\n );\n};\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/views/ResolutionView/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAyC,MAAM,OAAO,CAAC;AAY9D,OAAO,EAAE,mBAAmB,EAAqD,MAAM,gBAAgB,CAAC;AAOxG,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CA6TxD,CAAC;AA8PF,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import React, { useState, useMemo, useCallback } from 'react';
|
|
2
|
+
import { MagnifyingGlassIcon, DocumentTextIcon, CubeIcon, PencilIcon, ListBulletIcon, FolderIcon } from '@heroicons/react/24/outline';
|
|
3
|
+
import { QualifierContextControl } from '../../common/QualifierContextControl';
|
|
4
|
+
import { EditableJsonView } from './EditableJsonView';
|
|
5
|
+
import { ResolutionEditControls } from './ResolutionEditControls';
|
|
6
|
+
import { ResourceTreeView } from '../../common/ResourceTreeView';
|
|
7
|
+
export const ResolutionView = ({ resources, filterState, filterResult, resolutionState, resolutionActions, availableQualifiers = [], onMessage, className = '' }) => {
|
|
8
|
+
// Local UI state
|
|
9
|
+
const [viewMode, setViewMode] = useState('list');
|
|
10
|
+
// Use filtered resources when filtering is active and successful
|
|
11
|
+
const isFilteringActive = filterState?.enabled && filterResult?.success === true;
|
|
12
|
+
const activeProcessedResources = isFilteringActive ? filterResult?.processedResources : resources;
|
|
13
|
+
// Available resources for selection
|
|
14
|
+
const availableResources = useMemo(() => {
|
|
15
|
+
if (!activeProcessedResources?.summary?.resourceIds) {
|
|
16
|
+
return [];
|
|
17
|
+
}
|
|
18
|
+
return activeProcessedResources.summary.resourceIds.sort();
|
|
19
|
+
}, [activeProcessedResources?.summary?.resourceIds]);
|
|
20
|
+
// Handle context value changes using the shared component's callback pattern
|
|
21
|
+
const handleQualifierChange = useCallback((qualifierName, value) => {
|
|
22
|
+
resolutionActions?.updateContextValue(qualifierName, value);
|
|
23
|
+
}, [resolutionActions]);
|
|
24
|
+
// Handle resource selection
|
|
25
|
+
const handleResourceSelect = useCallback((resourceId) => {
|
|
26
|
+
resolutionActions?.selectResource(resourceId);
|
|
27
|
+
}, [resolutionActions]);
|
|
28
|
+
// Handle view mode change
|
|
29
|
+
const handleViewModeChange = useCallback((mode) => {
|
|
30
|
+
resolutionActions?.setViewMode(mode);
|
|
31
|
+
}, [resolutionActions]);
|
|
32
|
+
if (!resources) {
|
|
33
|
+
return (React.createElement("div", { className: `p-6 ${className}` },
|
|
34
|
+
React.createElement("div", { className: "flex items-center space-x-3 mb-6" },
|
|
35
|
+
React.createElement(MagnifyingGlassIcon, { className: "h-8 w-8 text-blue-600" }),
|
|
36
|
+
React.createElement("h2", { className: "text-2xl font-bold text-gray-900" }, "Resolution Viewer")),
|
|
37
|
+
React.createElement("div", { className: "bg-white rounded-lg shadow-sm border border-gray-200 p-8 text-center" },
|
|
38
|
+
React.createElement("div", { className: "max-w-2xl mx-auto" },
|
|
39
|
+
React.createElement("h3", { className: "text-xl font-semibold text-gray-900 mb-4" }, "No Resources Loaded"),
|
|
40
|
+
React.createElement("p", { className: "text-gray-600 mb-6" }, "Import resources first to test resource resolution with different contexts."),
|
|
41
|
+
React.createElement("div", { className: "bg-blue-50 rounded-lg p-4" },
|
|
42
|
+
React.createElement("p", { className: "text-sm text-blue-800" },
|
|
43
|
+
React.createElement("strong", null, "Resolution Viewer:"),
|
|
44
|
+
" Test how resources resolve with different qualifier contexts. Set context values and see which candidates match."))))));
|
|
45
|
+
}
|
|
46
|
+
return (React.createElement("div", { className: `p-6 ${className}` },
|
|
47
|
+
React.createElement("div", { className: "flex items-center space-x-3 mb-6" },
|
|
48
|
+
React.createElement(MagnifyingGlassIcon, { className: "h-8 w-8 text-blue-600" }),
|
|
49
|
+
React.createElement("h2", { className: "text-2xl font-bold text-gray-900" }, "Resolution Viewer"),
|
|
50
|
+
isFilteringActive && (React.createElement("span", { className: "inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-purple-100 text-purple-800" }, "Filtered"))),
|
|
51
|
+
React.createElement("div", { className: "bg-white rounded-lg shadow-sm border border-gray-200 p-6" },
|
|
52
|
+
React.createElement("div", { className: "mb-6" },
|
|
53
|
+
React.createElement("h3", { className: "text-lg font-semibold text-gray-900 mb-4" }, "Context Configuration"),
|
|
54
|
+
React.createElement("div", { className: "bg-gray-50 rounded-lg p-4" },
|
|
55
|
+
React.createElement("div", { className: "mb-4" },
|
|
56
|
+
React.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3" }, availableQualifiers.map((qualifierName) => (React.createElement(QualifierContextControl, { key: qualifierName, qualifierName: qualifierName, value: resolutionState?.pendingContextValues[qualifierName], onChange: handleQualifierChange, placeholder: `Enter ${qualifierName} value`, resources: activeProcessedResources }))))),
|
|
57
|
+
React.createElement("div", { className: "flex items-center justify-between" },
|
|
58
|
+
React.createElement("div", { className: "text-sm text-gray-600" },
|
|
59
|
+
"Current:",
|
|
60
|
+
' ',
|
|
61
|
+
Object.entries(resolutionState?.contextValues || {})
|
|
62
|
+
.map(([key, value]) => `${key}=${value === undefined ? '(undefined)' : value}`)
|
|
63
|
+
.join(', ')),
|
|
64
|
+
React.createElement("div", { className: "flex items-center space-x-2" },
|
|
65
|
+
React.createElement("button", { onClick: resolutionActions?.resetCache, className: "px-3 py-1 text-xs font-medium text-gray-600 bg-gray-100 rounded hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-gray-500", title: "Clear resolution cache" }, "Clear Cache"),
|
|
66
|
+
React.createElement("button", { onClick: resolutionActions?.applyContext, disabled: !resolutionState?.hasPendingChanges, className: `px-4 py-2 rounded-md text-sm font-medium ${resolutionState?.hasPendingChanges
|
|
67
|
+
? 'bg-blue-600 text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500'
|
|
68
|
+
: 'bg-gray-300 text-gray-500 cursor-not-allowed'}` }, resolutionState?.hasPendingChanges
|
|
69
|
+
? 'Apply Changes'
|
|
70
|
+
: resolutionState?.currentResolver
|
|
71
|
+
? 'Context Applied'
|
|
72
|
+
: 'Apply Context'))))),
|
|
73
|
+
resolutionState?.hasUnsavedEdits && (React.createElement("div", { className: "mt-6" },
|
|
74
|
+
React.createElement(ResolutionEditControls, { editCount: resolutionState.editedResources.size, isApplying: resolutionState.isApplyingEdits, hasEdits: resolutionState.hasUnsavedEdits, onApplyEdits: resolutionActions?.applyEdits, onDiscardEdits: resolutionActions?.discardEdits, disabled: !resolutionState.currentResolver }))),
|
|
75
|
+
React.createElement("div", { className: "flex flex-col lg:flex-row gap-6 h-[600px]" },
|
|
76
|
+
React.createElement("div", { className: "lg:w-1/2 flex flex-col" },
|
|
77
|
+
React.createElement("div", { className: "flex items-center justify-between mb-4" },
|
|
78
|
+
React.createElement("div", null,
|
|
79
|
+
React.createElement("h3", { className: "text-lg font-semibold text-gray-900" }, "Resources"),
|
|
80
|
+
React.createElement("div", { className: "text-sm text-gray-500" },
|
|
81
|
+
availableResources.length,
|
|
82
|
+
" available")),
|
|
83
|
+
React.createElement("div", { className: "flex items-center space-x-1 bg-gray-100 rounded-lg p-1" },
|
|
84
|
+
React.createElement("button", { onClick: () => setViewMode('list'), className: `flex items-center px-2 py-1 text-xs font-medium rounded ${viewMode === 'list'
|
|
85
|
+
? 'bg-white text-gray-900 shadow-sm'
|
|
86
|
+
: 'text-gray-600 hover:text-gray-900'}`, title: "List View" },
|
|
87
|
+
React.createElement(ListBulletIcon, { className: "h-4 w-4" }),
|
|
88
|
+
React.createElement("span", { className: "ml-1" }, "List")),
|
|
89
|
+
React.createElement("button", { onClick: () => setViewMode('tree'), className: `flex items-center px-2 py-1 text-xs font-medium rounded ${viewMode === 'tree'
|
|
90
|
+
? 'bg-white text-gray-900 shadow-sm'
|
|
91
|
+
: 'text-gray-600 hover:text-gray-900'}`, title: "Tree View" },
|
|
92
|
+
React.createElement(FolderIcon, { className: "h-4 w-4" }),
|
|
93
|
+
React.createElement("span", { className: "ml-1" }, "Tree")))),
|
|
94
|
+
React.createElement("div", { className: "flex-1 overflow-y-auto border border-gray-200 rounded-lg bg-gray-50" }, viewMode === 'tree' && activeProcessedResources?.system.resourceManager ? (React.createElement(ResourceTreeView, { resources: activeProcessedResources.system.resourceManager, selectedResourceId: resolutionState?.selectedResourceId || null, onResourceSelect: handleResourceSelect, searchTerm: "", className: "" })) : (availableResources.map((resourceId) => (React.createElement("div", { key: resourceId, className: `flex items-center px-3 py-2 cursor-pointer hover:bg-gray-100 ${resolutionState?.selectedResourceId === resourceId
|
|
95
|
+
? 'bg-blue-50 border-r-2 border-blue-500'
|
|
96
|
+
: ''}`, onClick: () => handleResourceSelect(resourceId) },
|
|
97
|
+
React.createElement(DocumentTextIcon, { className: "w-4 h-4 mr-2 text-green-500" }),
|
|
98
|
+
React.createElement("span", { className: `text-sm ${resolutionState?.selectedResourceId === resourceId
|
|
99
|
+
? 'font-medium text-blue-900'
|
|
100
|
+
: 'text-gray-700'}` }, resourceId),
|
|
101
|
+
resolutionActions?.hasEdit?.(resourceId) && (React.createElement("span", { className: "ml-auto" },
|
|
102
|
+
React.createElement(PencilIcon, { className: "h-3 w-3 text-blue-500" }))))))))),
|
|
103
|
+
React.createElement("div", { className: "lg:w-1/2 flex flex-col" },
|
|
104
|
+
React.createElement("div", { className: "flex items-center justify-between mb-4" },
|
|
105
|
+
React.createElement("h3", { className: "text-lg font-semibold text-gray-900" }, "Results"),
|
|
106
|
+
resolutionState?.selectedResourceId && (React.createElement("div", { className: "flex space-x-2" },
|
|
107
|
+
React.createElement("button", { onClick: () => handleViewModeChange('composed'), className: `px-3 py-1 text-xs rounded ${resolutionState?.viewMode === 'composed'
|
|
108
|
+
? 'bg-blue-600 text-white'
|
|
109
|
+
: 'bg-gray-200 text-gray-700'}` }, "Composed"),
|
|
110
|
+
React.createElement("button", { onClick: () => handleViewModeChange('best'), className: `px-3 py-1 text-xs rounded ${resolutionState?.viewMode === 'best'
|
|
111
|
+
? 'bg-blue-600 text-white'
|
|
112
|
+
: 'bg-gray-200 text-gray-700'}` }, "Best"),
|
|
113
|
+
React.createElement("button", { onClick: () => handleViewModeChange('all'), className: `px-3 py-1 text-xs rounded ${resolutionState?.viewMode === 'all'
|
|
114
|
+
? 'bg-blue-600 text-white'
|
|
115
|
+
: 'bg-gray-200 text-gray-700'}` }, "All"),
|
|
116
|
+
React.createElement("button", { onClick: () => handleViewModeChange('raw'), className: `px-3 py-1 text-xs rounded ${resolutionState?.viewMode === 'raw'
|
|
117
|
+
? 'bg-blue-600 text-white'
|
|
118
|
+
: 'bg-gray-200 text-gray-700'}` }, "Raw")))),
|
|
119
|
+
React.createElement("div", { className: "flex-1 overflow-y-auto border border-gray-200 rounded-lg p-4 bg-gray-50" }, !resolutionState?.selectedResourceId ? (React.createElement("div", { className: "flex items-center justify-center h-full" },
|
|
120
|
+
React.createElement("div", { className: "text-center" },
|
|
121
|
+
React.createElement(CubeIcon, { className: "h-12 w-12 text-gray-400 mx-auto mb-4" }),
|
|
122
|
+
React.createElement("p", { className: "text-gray-500" }, "Select a resource to view resolution results")))) : !resolutionState?.currentResolver ? (React.createElement("div", { className: "text-center text-gray-500" },
|
|
123
|
+
React.createElement("p", null, "Apply a context to resolve resources"))) : !resolutionState?.resolutionResult ? (React.createElement("div", { className: "text-center text-gray-500" },
|
|
124
|
+
React.createElement("p", null, "Resolving..."))) : (React.createElement(ResolutionResults, { result: resolutionState.resolutionResult, viewMode: resolutionState.viewMode, contextValues: resolutionState.contextValues, resolutionActions: resolutionActions, resolutionState: resolutionState }))))))));
|
|
125
|
+
};
|
|
126
|
+
const ResolutionResults = ({ result, viewMode, contextValues, resolutionActions, resolutionState }) => {
|
|
127
|
+
if (!result.success) {
|
|
128
|
+
return (React.createElement("div", { className: "bg-red-50 border border-red-200 rounded-lg p-4" },
|
|
129
|
+
React.createElement("h4", { className: "font-medium text-red-800 mb-2" }, "Resolution Failed"),
|
|
130
|
+
React.createElement("p", { className: "text-sm text-red-600" }, result.error)));
|
|
131
|
+
}
|
|
132
|
+
if (viewMode === 'raw') {
|
|
133
|
+
return (React.createElement("div", { className: "space-y-4" },
|
|
134
|
+
React.createElement("div", null,
|
|
135
|
+
React.createElement("h4", { className: "font-medium text-gray-800 mb-2" }, "Raw Resolution Data"),
|
|
136
|
+
React.createElement("pre", { className: "text-xs bg-white p-3 rounded border overflow-x-auto" }, JSON.stringify({
|
|
137
|
+
context: contextValues,
|
|
138
|
+
resource: result.resource
|
|
139
|
+
? {
|
|
140
|
+
id: result.resource.id,
|
|
141
|
+
candidateCount: result.resource.candidates.length
|
|
142
|
+
}
|
|
143
|
+
: null,
|
|
144
|
+
bestCandidate: result.bestCandidate?.json,
|
|
145
|
+
allCandidates: result.allCandidates?.map((c) => c.json),
|
|
146
|
+
composedValue: result.composedValue,
|
|
147
|
+
error: result.error
|
|
148
|
+
}, null, 2)))));
|
|
149
|
+
}
|
|
150
|
+
if (viewMode === 'composed') {
|
|
151
|
+
return (React.createElement("div", { className: "space-y-4" },
|
|
152
|
+
result.composedValue ? (React.createElement(EditableJsonView, { value: result.composedValue, resourceId: result.resourceId, isEdited: resolutionActions?.hasEdit?.(result.resourceId) || false, editedValue: resolutionActions?.getEditedValue?.(result.resourceId), onSave: resolutionActions?.saveEdit, onCancel: () => { }, disabled: resolutionState?.isApplyingEdits || false })) : (React.createElement("div", { className: "bg-yellow-50 border border-yellow-200 rounded p-3" },
|
|
153
|
+
React.createElement("p", { className: "text-sm text-yellow-800" }, "No composed value available for the current context."),
|
|
154
|
+
result.error && React.createElement("p", { className: "text-xs text-yellow-600 mt-1" }, result.error))),
|
|
155
|
+
result.resource && (React.createElement("div", null,
|
|
156
|
+
React.createElement("h4", { className: "font-medium text-gray-800 mb-2" }, "Resource Info"),
|
|
157
|
+
React.createElement("div", { className: "bg-white p-3 rounded border text-sm" },
|
|
158
|
+
React.createElement("div", null,
|
|
159
|
+
React.createElement("strong", null, "ID:"),
|
|
160
|
+
" ",
|
|
161
|
+
result.resource.id),
|
|
162
|
+
React.createElement("div", null,
|
|
163
|
+
React.createElement("strong", null, "Type:"),
|
|
164
|
+
" ",
|
|
165
|
+
result.resource.resourceType.key),
|
|
166
|
+
React.createElement("div", null,
|
|
167
|
+
React.createElement("strong", null, "Total Candidates:"),
|
|
168
|
+
" ",
|
|
169
|
+
result.resource.candidates.length))))));
|
|
170
|
+
}
|
|
171
|
+
if (viewMode === 'best') {
|
|
172
|
+
return (React.createElement("div", { className: "space-y-4" },
|
|
173
|
+
React.createElement("div", null,
|
|
174
|
+
React.createElement("h4", { className: "font-medium text-gray-800 mb-2" }, "Best Match"),
|
|
175
|
+
result.bestCandidate ? (React.createElement("div", { className: "bg-white p-3 rounded border border-green-200" },
|
|
176
|
+
React.createElement("div", { className: "text-sm font-medium text-gray-700 mb-2" }, "Selected candidate for current context"),
|
|
177
|
+
React.createElement("pre", { className: "text-xs bg-gray-50 p-2 rounded overflow-x-auto" }, JSON.stringify(result.bestCandidate.json, null, 2)))) : (React.createElement("div", { className: "bg-yellow-50 border border-yellow-200 rounded p-3" },
|
|
178
|
+
React.createElement("p", { className: "text-sm text-yellow-800" }, "No best candidate found for the current context."),
|
|
179
|
+
result.error && React.createElement("p", { className: "text-xs text-yellow-600 mt-1" }, result.error))))));
|
|
180
|
+
}
|
|
181
|
+
// 'all' view mode
|
|
182
|
+
const regularMatchingCandidates = result.candidateDetails?.filter((c) => c.matched && !c.isDefaultMatch) || [];
|
|
183
|
+
const defaultMatchingCandidates = result.candidateDetails?.filter((c) => c.matched && c.isDefaultMatch) || [];
|
|
184
|
+
const nonMatchingCandidates = result.candidateDetails?.filter((c) => !c.matched) || [];
|
|
185
|
+
const getMatchTypeColor = (type) => {
|
|
186
|
+
switch (type) {
|
|
187
|
+
case 'match':
|
|
188
|
+
return 'bg-green-100 text-green-800';
|
|
189
|
+
case 'matchAsDefault':
|
|
190
|
+
return 'bg-amber-100 text-amber-800';
|
|
191
|
+
case 'noMatch':
|
|
192
|
+
return 'bg-red-100 text-red-800';
|
|
193
|
+
default:
|
|
194
|
+
return 'bg-gray-100 text-gray-800';
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
const getMatchTypeIcon = (type) => {
|
|
198
|
+
switch (type) {
|
|
199
|
+
case 'match':
|
|
200
|
+
return '✓';
|
|
201
|
+
case 'matchAsDefault':
|
|
202
|
+
return '≈';
|
|
203
|
+
case 'noMatch':
|
|
204
|
+
return '✗';
|
|
205
|
+
default:
|
|
206
|
+
return '?';
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
return (React.createElement("div", { className: "space-y-4" },
|
|
210
|
+
regularMatchingCandidates.length > 0 && (React.createElement("div", null,
|
|
211
|
+
React.createElement("h4", { className: "font-medium text-gray-800 mb-2" }, "Regular Matches"),
|
|
212
|
+
React.createElement("div", { className: "space-y-2" }, regularMatchingCandidates.map((candidateInfo, index) => (React.createElement("div", { key: `regular-${candidateInfo.candidateIndex}`, className: "bg-white p-3 rounded border border-green-200" },
|
|
213
|
+
React.createElement("div", { className: "flex items-center justify-between mb-2" },
|
|
214
|
+
React.createElement("div", { className: "text-sm font-medium text-gray-700 flex items-center space-x-2" },
|
|
215
|
+
React.createElement("span", null,
|
|
216
|
+
"Candidate ",
|
|
217
|
+
candidateInfo.candidateIndex + 1,
|
|
218
|
+
" ",
|
|
219
|
+
index === 0 ? '(Best Match)' : ''),
|
|
220
|
+
React.createElement("span", { className: `px-2 py-1 rounded text-xs ${getMatchTypeColor(candidateInfo.matchType)}` },
|
|
221
|
+
getMatchTypeIcon(candidateInfo.matchType),
|
|
222
|
+
" ",
|
|
223
|
+
candidateInfo.matchType))),
|
|
224
|
+
React.createElement("pre", { className: "text-xs bg-gray-50 p-2 rounded overflow-x-auto" }, JSON.stringify(candidateInfo.candidate.json, null, 2)))))))),
|
|
225
|
+
defaultMatchingCandidates.length > 0 && (React.createElement("div", null,
|
|
226
|
+
React.createElement("h4", { className: "font-medium text-gray-800 mb-2" }, "Default Matches"),
|
|
227
|
+
React.createElement("div", { className: "space-y-2" }, defaultMatchingCandidates.map((candidateInfo) => (React.createElement("div", { key: `default-${candidateInfo.candidateIndex}`, className: "bg-white p-3 rounded border border-amber-200" },
|
|
228
|
+
React.createElement("div", { className: "flex items-center justify-between mb-2" },
|
|
229
|
+
React.createElement("div", { className: "text-sm font-medium text-gray-700 flex items-center space-x-2" },
|
|
230
|
+
React.createElement("span", null,
|
|
231
|
+
"Candidate ",
|
|
232
|
+
candidateInfo.candidateIndex + 1),
|
|
233
|
+
React.createElement("span", { className: `px-2 py-1 rounded text-xs ${getMatchTypeColor(candidateInfo.matchType)}` },
|
|
234
|
+
getMatchTypeIcon(candidateInfo.matchType),
|
|
235
|
+
" ",
|
|
236
|
+
candidateInfo.matchType))),
|
|
237
|
+
React.createElement("pre", { className: "text-xs bg-gray-50 p-2 rounded overflow-x-auto" }, JSON.stringify(candidateInfo.candidate.json, null, 2)))))))),
|
|
238
|
+
regularMatchingCandidates.length === 0 && defaultMatchingCandidates.length === 0 && (React.createElement("div", null,
|
|
239
|
+
React.createElement("h4", { className: "font-medium text-gray-800 mb-2" }, "Matching Candidates"),
|
|
240
|
+
React.createElement("p", { className: "text-sm text-gray-600" }, "No candidates matched the current context."))),
|
|
241
|
+
nonMatchingCandidates.length > 0 && (React.createElement("div", null,
|
|
242
|
+
React.createElement("h4", { className: "font-medium text-gray-500 mb-2" }, "Non-matching Candidates"),
|
|
243
|
+
React.createElement("div", { className: "space-y-2" },
|
|
244
|
+
nonMatchingCandidates.slice(0, 3).map((candidateInfo) => (React.createElement("div", { key: `non-matching-${candidateInfo.candidateIndex}`, className: "bg-gray-50 p-3 rounded border border-gray-200 opacity-75" },
|
|
245
|
+
React.createElement("div", { className: "text-sm font-medium text-gray-500 mb-2" },
|
|
246
|
+
"Candidate ",
|
|
247
|
+
candidateInfo.candidateIndex + 1),
|
|
248
|
+
React.createElement("pre", { className: "text-xs bg-gray-100 p-2 rounded overflow-x-auto text-gray-600" }, JSON.stringify(candidateInfo.candidate.json, null, 2))))),
|
|
249
|
+
nonMatchingCandidates.length > 3 && (React.createElement("div", { className: "text-center text-sm text-gray-500" },
|
|
250
|
+
"... and ",
|
|
251
|
+
nonMatchingCandidates.length - 3,
|
|
252
|
+
" more non-matching candidates")))))));
|
|
253
|
+
};
|
|
254
|
+
export default ResolutionView;
|
|
255
|
+
//# sourceMappingURL=index.js.map
|