@fgv/ts-res-ui-components 5.0.0-21 → 5.0.0-23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +401 -155
- package/config/jest.setup.js +10 -0
- package/dist/ts-res-ui-components.d.ts +1657 -76
- package/lib/components/common/QualifierContextControl.js +4 -1
- package/lib/components/common/ResourceTreeView.js +4 -1
- package/lib/components/forms/GenericQualifierTypeEditForm.d.ts +26 -0
- package/lib/components/forms/GenericQualifierTypeEditForm.js +166 -0
- package/lib/components/forms/QualifierEditForm.d.ts +1 -1
- package/lib/components/forms/index.d.ts +2 -0
- package/lib/components/forms/index.js +1 -0
- package/lib/components/orchestrator/ResourceOrchestrator.d.ts +3 -0
- package/lib/components/orchestrator/ResourceOrchestrator.js +118 -51
- package/lib/components/pickers/ResourcePicker/ResourcePickerTree.js +32 -10
- package/lib/components/pickers/ResourcePicker/index.js +4 -2
- package/lib/components/views/CompiledView/index.js +75 -16
- package/lib/components/views/ConfigurationView/index.js +94 -35
- package/lib/components/views/FilterView/index.js +7 -4
- package/lib/components/views/GridView/EditableGridCell.d.ts +76 -0
- package/lib/components/views/GridView/EditableGridCell.js +224 -0
- package/lib/components/views/GridView/GridSelector.d.ts +43 -0
- package/lib/components/views/GridView/GridSelector.js +89 -0
- package/lib/components/views/GridView/MultiGridView.d.ts +85 -0
- package/lib/components/views/GridView/MultiGridView.js +196 -0
- package/lib/components/views/GridView/ResourceGrid.d.ts +38 -0
- package/lib/components/views/GridView/ResourceGrid.js +232 -0
- package/lib/components/views/GridView/SharedContextControls.d.ts +47 -0
- package/lib/components/views/GridView/SharedContextControls.js +95 -0
- package/lib/components/views/GridView/cells/BooleanCell.d.ts +44 -0
- package/lib/components/views/GridView/cells/BooleanCell.js +49 -0
- package/lib/components/views/GridView/cells/DropdownCell.d.ts +58 -0
- package/lib/components/views/GridView/cells/DropdownCell.js +182 -0
- package/lib/components/views/GridView/cells/StringCell.d.ts +57 -0
- package/lib/components/views/GridView/cells/StringCell.js +106 -0
- package/lib/components/views/GridView/cells/TriStateCell.d.ts +54 -0
- package/lib/components/views/GridView/cells/TriStateCell.js +112 -0
- package/lib/components/views/GridView/cells/index.d.ts +15 -0
- package/lib/components/views/GridView/cells/index.js +11 -0
- package/lib/components/views/GridView/index.d.ts +53 -0
- package/lib/components/views/GridView/index.js +212 -0
- package/lib/components/views/ImportView/index.js +22 -19
- package/lib/components/views/MessagesWindow/index.js +4 -1
- package/lib/components/views/ResolutionView/index.js +8 -5
- package/lib/contexts/ObservabilityContext.d.ts +85 -0
- package/lib/contexts/ObservabilityContext.js +98 -0
- package/lib/contexts/index.d.ts +2 -0
- package/lib/contexts/index.js +24 -0
- package/lib/hooks/useConfigurationState.d.ts +3 -3
- package/lib/hooks/useResolutionState.js +850 -246
- package/lib/hooks/useResourceData.d.ts +7 -4
- package/lib/hooks/useResourceData.js +185 -184
- package/lib/index.d.ts +5 -1
- package/lib/index.js +8 -1
- package/lib/namespaces/GridTools.d.ts +136 -0
- package/lib/namespaces/GridTools.js +138 -0
- package/lib/namespaces/ObservabilityTools.d.ts +3 -0
- package/lib/namespaces/ObservabilityTools.js +23 -0
- package/lib/namespaces/ResolutionTools.d.ts +2 -1
- package/lib/namespaces/ResolutionTools.js +2 -0
- package/lib/namespaces/index.d.ts +2 -0
- package/lib/namespaces/index.js +2 -0
- package/lib/test/integration/observability.integration.test.d.ts +2 -0
- package/lib/test/unit/hooks/useResourceData.test.d.ts +2 -0
- package/lib/test/unit/utils/downloadHelper.test.d.ts +2 -0
- package/lib/test/unit/workflows/resolutionWorkflows.test.d.ts +2 -0
- package/lib/test/unit/workflows/resourceCreation.test.d.ts +2 -0
- package/lib/test/unit/workflows/resultPatternExtensions.test.d.ts +2 -0
- package/lib/test/unit/workflows/validation.test.d.ts +2 -0
- package/lib/types/index.d.ts +387 -20
- package/lib/types/index.js +2 -1
- package/lib/utils/cellValidation.d.ts +113 -0
- package/lib/utils/cellValidation.js +248 -0
- package/lib/utils/downloadHelper.d.ts +66 -0
- package/lib/utils/downloadHelper.js +195 -0
- package/lib/utils/observability/factories.d.ts +29 -0
- package/lib/utils/observability/factories.js +58 -0
- package/lib/utils/observability/implementations.d.ts +61 -0
- package/lib/utils/observability/implementations.js +103 -0
- package/lib/utils/observability/index.d.ts +4 -0
- package/lib/utils/observability/index.js +26 -0
- package/lib/utils/observability/interfaces.d.ts +30 -0
- package/lib/utils/observability/interfaces.js +23 -0
- package/lib/utils/resolutionEditing.js +2 -1
- package/lib/utils/resourceSelector.d.ts +97 -0
- package/lib/utils/resourceSelector.js +195 -0
- package/lib/utils/resourceSelectors.d.ts +146 -0
- package/lib/utils/resourceSelectors.js +233 -0
- package/lib/utils/tsResIntegration.d.ts +6 -41
- package/lib/utils/tsResIntegration.js +20 -16
- package/lib/utils/zipLoader/zipProcessingHelpers.d.ts +3 -2
- package/lib/utils/zipLoader/zipProcessingHelpers.js +6 -5
- package/lib-commonjs/components/common/QualifierContextControl.js +4 -1
- package/lib-commonjs/components/common/ResourceTreeView.js +4 -1
- package/lib-commonjs/components/forms/GenericQualifierTypeEditForm.js +171 -0
- package/lib-commonjs/components/forms/index.js +3 -1
- package/lib-commonjs/components/orchestrator/ResourceOrchestrator.js +118 -51
- package/lib-commonjs/components/pickers/ResourcePicker/ResourcePickerTree.js +32 -10
- package/lib-commonjs/components/pickers/ResourcePicker/index.js +4 -2
- package/lib-commonjs/components/views/CompiledView/index.js +75 -16
- package/lib-commonjs/components/views/ConfigurationView/index.js +93 -34
- package/lib-commonjs/components/views/FilterView/index.js +7 -4
- package/lib-commonjs/components/views/GridView/EditableGridCell.js +232 -0
- package/lib-commonjs/components/views/GridView/GridSelector.js +94 -0
- package/lib-commonjs/components/views/GridView/MultiGridView.js +201 -0
- package/lib-commonjs/components/views/GridView/ResourceGrid.js +237 -0
- package/lib-commonjs/components/views/GridView/SharedContextControls.js +100 -0
- package/lib-commonjs/components/views/GridView/cells/BooleanCell.js +54 -0
- package/lib-commonjs/components/views/GridView/cells/DropdownCell.js +187 -0
- package/lib-commonjs/components/views/GridView/cells/StringCell.js +111 -0
- package/lib-commonjs/components/views/GridView/cells/TriStateCell.js +117 -0
- package/lib-commonjs/components/views/GridView/cells/index.js +18 -0
- package/lib-commonjs/components/views/GridView/index.js +217 -0
- package/lib-commonjs/components/views/ImportView/index.js +22 -19
- package/lib-commonjs/components/views/MessagesWindow/index.js +4 -1
- package/lib-commonjs/components/views/ResolutionView/index.js +8 -5
- package/lib-commonjs/contexts/ObservabilityContext.js +104 -0
- package/lib-commonjs/contexts/index.js +30 -0
- package/lib-commonjs/hooks/useResolutionState.js +849 -245
- package/lib-commonjs/hooks/useResourceData.js +184 -215
- package/lib-commonjs/index.js +15 -1
- package/lib-commonjs/namespaces/GridTools.js +161 -0
- package/lib-commonjs/namespaces/ObservabilityTools.js +33 -0
- package/lib-commonjs/namespaces/ResolutionTools.js +10 -1
- package/lib-commonjs/namespaces/index.js +3 -1
- package/lib-commonjs/types/index.js +10 -0
- package/lib-commonjs/utils/cellValidation.js +253 -0
- package/lib-commonjs/utils/downloadHelper.js +198 -0
- package/lib-commonjs/utils/observability/factories.js +63 -0
- package/lib-commonjs/utils/observability/implementations.js +109 -0
- package/lib-commonjs/utils/observability/index.js +36 -0
- package/lib-commonjs/utils/observability/interfaces.js +24 -0
- package/lib-commonjs/utils/resolutionEditing.js +2 -1
- package/lib-commonjs/utils/resourceSelector.js +200 -0
- package/lib-commonjs/utils/resourceSelectors.js +242 -0
- package/lib-commonjs/utils/tsResIntegration.js +21 -16
- package/lib-commonjs/utils/zipLoader/zipProcessingHelpers.js +7 -5
- package/package.json +7 -7
- package/src/components/common/QualifierContextControl.tsx +0 -338
- package/src/components/common/ResolutionContextOptionsControl.tsx +0 -450
- package/src/components/common/ResolutionResults/index.tsx +0 -481
- package/src/components/common/ResourceListView.tsx +0 -167
- package/src/components/common/ResourcePickerOptionsControl.tsx +0 -351
- package/src/components/common/ResourceTreeView.tsx +0 -417
- package/src/components/common/SourceResourceDetail/index.tsx +0 -493
- package/src/components/forms/HierarchyEditor.tsx +0 -285
- package/src/components/forms/QualifierEditForm.tsx +0 -487
- package/src/components/forms/QualifierTypeEditForm.tsx +0 -458
- package/src/components/forms/ResourceTypeEditForm.tsx +0 -437
- package/src/components/forms/index.ts +0 -11
- package/src/components/orchestrator/ResourceOrchestrator.tsx +0 -444
- package/src/components/pickers/ResourcePicker/README.md +0 -570
- package/src/components/pickers/ResourcePicker/ResourceItem.tsx +0 -127
- package/src/components/pickers/ResourcePicker/ResourcePickerList.tsx +0 -114
- package/src/components/pickers/ResourcePicker/ResourcePickerTree.tsx +0 -461
- package/src/components/pickers/ResourcePicker/index.tsx +0 -234
- package/src/components/pickers/ResourcePicker/types.ts +0 -301
- package/src/components/pickers/ResourcePicker/utils/treeNavigation.ts +0 -210
- package/src/components/views/CompiledView/index.tsx +0 -1342
- package/src/components/views/ConfigurationView/index.tsx +0 -848
- package/src/components/views/FilterView/index.tsx +0 -681
- package/src/components/views/ImportView/index.tsx +0 -789
- package/src/components/views/MessagesWindow/index.tsx +0 -325
- package/src/components/views/ResolutionView/EditableJsonView.tsx +0 -386
- package/src/components/views/ResolutionView/NewResourceModal.tsx +0 -158
- package/src/components/views/ResolutionView/UnifiedChangeControls.tsx +0 -163
- package/src/components/views/ResolutionView/index.tsx +0 -751
- package/src/components/views/SourceView/index.tsx +0 -291
- package/src/hooks/useConfigurationState.ts +0 -436
- package/src/hooks/useFilterState.ts +0 -150
- package/src/hooks/useResolutionState.ts +0 -893
- package/src/hooks/useResourceData.ts +0 -596
- package/src/hooks/useViewState.ts +0 -97
- package/src/index.ts +0 -68
- package/src/namespaces/ConfigurationTools.ts +0 -59
- package/src/namespaces/FilterTools.ts +0 -47
- package/src/namespaces/ImportTools.ts +0 -42
- package/src/namespaces/PickerTools.ts +0 -104
- package/src/namespaces/ResolutionTools.ts +0 -68
- package/src/namespaces/ResourceTools.ts +0 -106
- package/src/namespaces/TsResTools.ts +0 -49
- package/src/namespaces/ViewStateTools.ts +0 -91
- package/src/namespaces/ZipTools.ts +0 -49
- package/src/namespaces/index.ts +0 -49
- package/src/types/index.ts +0 -1273
- package/src/utils/configurationUtils.ts +0 -339
- package/src/utils/fileProcessing.ts +0 -164
- package/src/utils/filterResources.ts +0 -356
- package/src/utils/resolutionEditing.ts +0 -346
- package/src/utils/resolutionUtils.ts +0 -740
- package/src/utils/tsResIntegration.ts +0 -475
- package/src/utils/zipLoader/index.ts +0 -5
- package/src/utils/zipLoader/zipProcessingHelpers.ts +0 -46
- package/src/utils/zipLoader/zipUtils.ts +0 -7
|
@@ -1,751 +0,0 @@
|
|
|
1
|
-
import React, { useState, useMemo, useCallback, useEffect, useRef } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
MagnifyingGlassIcon,
|
|
4
|
-
DocumentTextIcon,
|
|
5
|
-
CubeIcon,
|
|
6
|
-
CheckIcon,
|
|
7
|
-
XMarkIcon,
|
|
8
|
-
PencilIcon,
|
|
9
|
-
TrashIcon,
|
|
10
|
-
ListBulletIcon,
|
|
11
|
-
FolderIcon,
|
|
12
|
-
PlusIcon
|
|
13
|
-
} from '@heroicons/react/24/outline';
|
|
14
|
-
import {
|
|
15
|
-
ResolutionViewProps,
|
|
16
|
-
CandidateInfo,
|
|
17
|
-
ResolutionActions,
|
|
18
|
-
ResolutionState,
|
|
19
|
-
ResourceEditorFactory,
|
|
20
|
-
ResourceEditorResult,
|
|
21
|
-
ResolutionContextOptions
|
|
22
|
-
} from '../../../types';
|
|
23
|
-
import { ResourceId } from '@fgv/ts-res';
|
|
24
|
-
import { QualifierContextControl } from '../../common/QualifierContextControl';
|
|
25
|
-
import { UnifiedChangeControls } from './UnifiedChangeControls';
|
|
26
|
-
import { ResourcePicker } from '../../pickers/ResourcePicker';
|
|
27
|
-
import {
|
|
28
|
-
ResourceSelection,
|
|
29
|
-
ResourceAnnotations,
|
|
30
|
-
ResourcePickerOptions,
|
|
31
|
-
PendingResource
|
|
32
|
-
} from '../../pickers/ResourcePicker/types';
|
|
33
|
-
import { ResourcePickerOptionsControl } from '../../common/ResourcePickerOptionsControl';
|
|
34
|
-
import { ResolutionContextOptionsControl } from '../../common/ResolutionContextOptionsControl';
|
|
35
|
-
import { ResolutionResults } from '../../common/ResolutionResults';
|
|
36
|
-
import { NewResourceModal } from './NewResourceModal';
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* ResolutionView component for resource resolution testing and editing.
|
|
40
|
-
*
|
|
41
|
-
* Provides a comprehensive interface for testing resource resolution with different
|
|
42
|
-
* qualifier contexts, viewing resolution results, and editing resource values with
|
|
43
|
-
* custom editors. Supports real-time resolution testing and conflict detection.
|
|
44
|
-
*
|
|
45
|
-
* **Key Features:**
|
|
46
|
-
* - **Context management**: Set and update resolution context (qualifier values)
|
|
47
|
-
* - **Real-time resolution**: See how resources resolve with current context
|
|
48
|
-
* - **Resource editing**: Edit resource values with custom type-specific editors
|
|
49
|
-
* - **Conflict detection**: Detect when edits would conflict with existing resources
|
|
50
|
-
* - **Preview mode**: See how edits affect resolution without committing changes
|
|
51
|
-
* - **Custom editors**: Support for type-specific resource editors via factory pattern
|
|
52
|
-
* - **Fallback editing**: JSON editor fallback when custom editors aren't available
|
|
53
|
-
*
|
|
54
|
-
* @example
|
|
55
|
-
* ```tsx
|
|
56
|
-
* import { ResolutionView } from '@fgv/ts-res-ui-components';
|
|
57
|
-
*
|
|
58
|
-
* // Custom editor factory for specific resource types
|
|
59
|
-
* const editorFactory = {
|
|
60
|
-
* createEditor: (resourceId, resourceType, value) => {
|
|
61
|
-
* if (resourceType === 'market-info') {
|
|
62
|
-
* return {
|
|
63
|
-
* success: true,
|
|
64
|
-
* editor: MarketInfoEditor
|
|
65
|
-
* };
|
|
66
|
-
* }
|
|
67
|
-
* return { success: false };
|
|
68
|
-
* }
|
|
69
|
-
* };
|
|
70
|
-
*
|
|
71
|
-
* function MyResolutionTool() {
|
|
72
|
-
* return (
|
|
73
|
-
* <ResolutionView
|
|
74
|
-
* resources={processedResources}
|
|
75
|
-
* resolutionState={resolutionState}
|
|
76
|
-
* resolutionActions={resolutionActions}
|
|
77
|
-
* availableQualifiers={['language', 'territory', 'platform']}
|
|
78
|
-
* resourceEditorFactory={editorFactory}
|
|
79
|
-
* onMessage={(type, message) => console.log(`${type}: ${message}`)}
|
|
80
|
-
* />
|
|
81
|
-
* );
|
|
82
|
-
* }
|
|
83
|
-
* ```
|
|
84
|
-
*
|
|
85
|
-
* @public
|
|
86
|
-
*/
|
|
87
|
-
export const ResolutionView: React.FC<ResolutionViewProps> = ({
|
|
88
|
-
resources,
|
|
89
|
-
filterState,
|
|
90
|
-
filterResult,
|
|
91
|
-
resolutionState,
|
|
92
|
-
resolutionActions,
|
|
93
|
-
availableQualifiers = [],
|
|
94
|
-
resourceEditorFactory,
|
|
95
|
-
onMessage,
|
|
96
|
-
pickerOptions,
|
|
97
|
-
pickerOptionsPresentation = 'hidden',
|
|
98
|
-
contextOptions,
|
|
99
|
-
lockedViewMode,
|
|
100
|
-
sectionTitles,
|
|
101
|
-
allowResourceCreation = false,
|
|
102
|
-
defaultResourceType,
|
|
103
|
-
resourceTypeFactory,
|
|
104
|
-
onPendingResourcesApplied,
|
|
105
|
-
showPendingResourcesInList = true,
|
|
106
|
-
className = ''
|
|
107
|
-
}) => {
|
|
108
|
-
// State for picker options control
|
|
109
|
-
const [currentPickerOptions, setCurrentPickerOptions] = useState<ResourcePickerOptions>(
|
|
110
|
-
pickerOptions || {}
|
|
111
|
-
);
|
|
112
|
-
|
|
113
|
-
// State for context options control
|
|
114
|
-
const [currentContextOptions, setCurrentContextOptions] = useState<ResolutionContextOptions>(
|
|
115
|
-
contextOptions || {}
|
|
116
|
-
);
|
|
117
|
-
|
|
118
|
-
// State for new resource modal
|
|
119
|
-
const [showNewResourceModal, setShowNewResourceModal] = useState(false);
|
|
120
|
-
|
|
121
|
-
// Local toggles for editing/creation features (controllable via options dialog)
|
|
122
|
-
const [allowResourceCreationInternal, setAllowResourceCreationInternal] = useState<boolean>(
|
|
123
|
-
!!allowResourceCreation
|
|
124
|
-
);
|
|
125
|
-
const [showPendingResourcesInListInternal, setShowPendingResourcesInListInternal] = useState<boolean>(
|
|
126
|
-
!!showPendingResourcesInList
|
|
127
|
-
);
|
|
128
|
-
|
|
129
|
-
// Sync internal toggles when props change
|
|
130
|
-
useEffect(() => {
|
|
131
|
-
setAllowResourceCreationInternal(!!allowResourceCreation);
|
|
132
|
-
}, [allowResourceCreation]);
|
|
133
|
-
useEffect(() => {
|
|
134
|
-
setShowPendingResourcesInListInternal(!!showPendingResourcesInList);
|
|
135
|
-
}, [showPendingResourcesInList]);
|
|
136
|
-
|
|
137
|
-
// Update currentContextOptions when contextOptions prop changes
|
|
138
|
-
// This is important for host-managed values
|
|
139
|
-
React.useEffect(() => {
|
|
140
|
-
if (contextOptions?.hostManagedValues) {
|
|
141
|
-
setCurrentContextOptions((prev) => ({
|
|
142
|
-
...prev,
|
|
143
|
-
hostManagedValues: contextOptions.hostManagedValues
|
|
144
|
-
}));
|
|
145
|
-
}
|
|
146
|
-
}, [contextOptions?.hostManagedValues]);
|
|
147
|
-
|
|
148
|
-
// Use filtered resources when filtering is active and successful
|
|
149
|
-
const isFilteringActive = filterState?.enabled && filterResult?.success === true;
|
|
150
|
-
const baseProcessedResources = isFilteringActive ? filterResult?.processedResources : resources;
|
|
151
|
-
|
|
152
|
-
// For now, just use the base processed resources directly
|
|
153
|
-
// TODO: Implement merging of pending resources for display
|
|
154
|
-
const activeProcessedResources = baseProcessedResources;
|
|
155
|
-
|
|
156
|
-
// Merge picker options with resolution-specific defaults
|
|
157
|
-
const effectivePickerOptions = useMemo(
|
|
158
|
-
() => ({
|
|
159
|
-
defaultView: 'list' as const,
|
|
160
|
-
showViewToggle: true,
|
|
161
|
-
enableSearch: true,
|
|
162
|
-
searchPlaceholder: 'Search resources for resolution testing...',
|
|
163
|
-
searchScope: 'all' as const,
|
|
164
|
-
height: '520px',
|
|
165
|
-
emptyMessage: 'No resources available for resolution testing',
|
|
166
|
-
// Override with user-provided options
|
|
167
|
-
...pickerOptions,
|
|
168
|
-
// Override with current picker options from control
|
|
169
|
-
...currentPickerOptions
|
|
170
|
-
}),
|
|
171
|
-
[pickerOptions, currentPickerOptions]
|
|
172
|
-
);
|
|
173
|
-
|
|
174
|
-
// Create resource annotations for resolution results and edit states
|
|
175
|
-
const resourceAnnotations = useMemo(() => {
|
|
176
|
-
const annotations: ResourceAnnotations = {};
|
|
177
|
-
|
|
178
|
-
// Get all resource IDs (existing + pending)
|
|
179
|
-
const allResourceIds = new Set<string>();
|
|
180
|
-
|
|
181
|
-
if (activeProcessedResources?.summary?.resourceIds) {
|
|
182
|
-
activeProcessedResources.summary.resourceIds.forEach((id) => allResourceIds.add(id));
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// Add pending resource IDs
|
|
186
|
-
if (resolutionState?.pendingResources) {
|
|
187
|
-
resolutionState.pendingResources.forEach((_, id) => allResourceIds.add(id));
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
allResourceIds.forEach((resourceId) => {
|
|
191
|
-
const hasEdit = resolutionActions?.hasEdit?.(resourceId);
|
|
192
|
-
const isPending = resolutionState?.pendingResources?.has(resourceId);
|
|
193
|
-
const isMarkedForDeletion = resolutionState?.pendingResourceDeletions?.has(resourceId);
|
|
194
|
-
const isSelected = resolutionState?.selectedResourceId === resourceId;
|
|
195
|
-
const hasResolutionResult = isSelected && resolutionState?.resolutionResult;
|
|
196
|
-
|
|
197
|
-
// Base annotation with appropriate indicator
|
|
198
|
-
let indicator = undefined;
|
|
199
|
-
if (isPending) {
|
|
200
|
-
indicator = {
|
|
201
|
-
type: 'icon' as const,
|
|
202
|
-
value: '➕',
|
|
203
|
-
tooltip: 'New resource (pending)'
|
|
204
|
-
};
|
|
205
|
-
} else if (isMarkedForDeletion) {
|
|
206
|
-
indicator = {
|
|
207
|
-
type: 'icon' as const,
|
|
208
|
-
value: '🗑️',
|
|
209
|
-
tooltip: 'Marked for deletion'
|
|
210
|
-
};
|
|
211
|
-
} else if (hasEdit) {
|
|
212
|
-
indicator = {
|
|
213
|
-
type: 'icon' as const,
|
|
214
|
-
value: '✏️',
|
|
215
|
-
tooltip: 'Resource has unsaved edits'
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
annotations[resourceId] = {
|
|
220
|
-
indicator
|
|
221
|
-
};
|
|
222
|
-
|
|
223
|
-
// Add resolution result annotations for selected resource
|
|
224
|
-
if (hasResolutionResult && resolutionState?.resolutionResult?.success) {
|
|
225
|
-
const result = resolutionState.resolutionResult;
|
|
226
|
-
|
|
227
|
-
// Show match status as badge
|
|
228
|
-
if (result.bestCandidate) {
|
|
229
|
-
annotations[resourceId].badge = {
|
|
230
|
-
text: 'Resolved',
|
|
231
|
-
variant: 'info'
|
|
232
|
-
};
|
|
233
|
-
} else if (result.candidateDetails) {
|
|
234
|
-
const matchingCount = result.candidateDetails.filter((c: CandidateInfo) => c.matched).length;
|
|
235
|
-
const totalCount = result.candidateDetails.length;
|
|
236
|
-
|
|
237
|
-
if (matchingCount === 0) {
|
|
238
|
-
annotations[resourceId].badge = {
|
|
239
|
-
text: 'No Match',
|
|
240
|
-
variant: 'error'
|
|
241
|
-
};
|
|
242
|
-
} else {
|
|
243
|
-
annotations[resourceId].badge = {
|
|
244
|
-
text: `${matchingCount}/${totalCount}`,
|
|
245
|
-
variant: 'warning'
|
|
246
|
-
};
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
// Add suffix with candidate count
|
|
251
|
-
if (result.resource) {
|
|
252
|
-
const totalCandidates = result.resource.candidates.length;
|
|
253
|
-
annotations[resourceId].suffix = `${totalCandidates} candidate${totalCandidates !== 1 ? 's' : ''}`;
|
|
254
|
-
}
|
|
255
|
-
} else if (
|
|
256
|
-
isSelected &&
|
|
257
|
-
resolutionState?.resolutionResult &&
|
|
258
|
-
!resolutionState.resolutionResult.success
|
|
259
|
-
) {
|
|
260
|
-
// Show error state
|
|
261
|
-
annotations[resourceId].badge = {
|
|
262
|
-
text: 'Error',
|
|
263
|
-
variant: 'error'
|
|
264
|
-
};
|
|
265
|
-
}
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
return annotations;
|
|
269
|
-
}, [
|
|
270
|
-
activeProcessedResources?.summary?.resourceIds,
|
|
271
|
-
resolutionActions,
|
|
272
|
-
resolutionState?.selectedResourceId,
|
|
273
|
-
resolutionState?.resolutionResult,
|
|
274
|
-
resolutionState?.pendingResources,
|
|
275
|
-
resolutionState?.pendingResourceDeletions
|
|
276
|
-
]);
|
|
277
|
-
|
|
278
|
-
// Merge context options with current options from control
|
|
279
|
-
const effectiveContextOptions = useMemo(() => {
|
|
280
|
-
// Deep merge to preserve hostManagedValues from contextOptions
|
|
281
|
-
const merged = {
|
|
282
|
-
...contextOptions,
|
|
283
|
-
...currentContextOptions,
|
|
284
|
-
// Preserve hostManagedValues from contextOptions if currentContextOptions doesn't explicitly set it
|
|
285
|
-
hostManagedValues:
|
|
286
|
-
currentContextOptions?.hostManagedValues !== undefined
|
|
287
|
-
? currentContextOptions.hostManagedValues
|
|
288
|
-
: contextOptions?.hostManagedValues
|
|
289
|
-
};
|
|
290
|
-
console.log('ResolutionView - effectiveContextOptions:', merged);
|
|
291
|
-
console.log('ResolutionView - contextOptions hostManagedValues:', contextOptions?.hostManagedValues);
|
|
292
|
-
console.log(
|
|
293
|
-
'ResolutionView - currentContextOptions hostManagedValues:',
|
|
294
|
-
currentContextOptions?.hostManagedValues
|
|
295
|
-
);
|
|
296
|
-
console.log('ResolutionView - final hostManagedValues:', merged.hostManagedValues);
|
|
297
|
-
return merged;
|
|
298
|
-
}, [contextOptions, currentContextOptions]);
|
|
299
|
-
|
|
300
|
-
// Handle context value changes using the shared component's callback pattern
|
|
301
|
-
const handleQualifierChange = useCallback(
|
|
302
|
-
(qualifierName: string, value: string | undefined) => {
|
|
303
|
-
// Don't update context if this qualifier is host-managed
|
|
304
|
-
const qualifierOptions = effectiveContextOptions?.qualifierOptions?.[qualifierName];
|
|
305
|
-
const isHostManaged = qualifierOptions?.hostValue !== undefined;
|
|
306
|
-
|
|
307
|
-
if (!isHostManaged) {
|
|
308
|
-
resolutionActions?.updateContextValue(qualifierName, value);
|
|
309
|
-
}
|
|
310
|
-
},
|
|
311
|
-
[resolutionActions, effectiveContextOptions?.qualifierOptions]
|
|
312
|
-
);
|
|
313
|
-
|
|
314
|
-
// Apply host-managed values when they change
|
|
315
|
-
const prevHostValuesRef = useRef<string | undefined>(undefined);
|
|
316
|
-
React.useEffect(() => {
|
|
317
|
-
if (!effectiveContextOptions?.hostManagedValues || !resolutionActions?.applyContext) return;
|
|
318
|
-
|
|
319
|
-
const hostValuesStr = JSON.stringify(effectiveContextOptions.hostManagedValues);
|
|
320
|
-
if (prevHostValuesRef.current !== hostValuesStr) {
|
|
321
|
-
console.log(
|
|
322
|
-
'ResolutionView: Host values changed, applying:',
|
|
323
|
-
effectiveContextOptions.hostManagedValues
|
|
324
|
-
);
|
|
325
|
-
prevHostValuesRef.current = hostValuesStr;
|
|
326
|
-
// Pass host values to the resolution state
|
|
327
|
-
resolutionActions.applyContext(effectiveContextOptions.hostManagedValues);
|
|
328
|
-
}
|
|
329
|
-
}, [effectiveContextOptions?.hostManagedValues, resolutionActions]);
|
|
330
|
-
|
|
331
|
-
// Determine which qualifiers to show and their options
|
|
332
|
-
const visibleQualifiers = useMemo(() => {
|
|
333
|
-
if (!effectiveContextOptions?.qualifierOptions) {
|
|
334
|
-
return availableQualifiers;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
return availableQualifiers.filter((qualifierName) => {
|
|
338
|
-
const options = effectiveContextOptions.qualifierOptions![qualifierName];
|
|
339
|
-
return options?.visible !== false;
|
|
340
|
-
});
|
|
341
|
-
}, [availableQualifiers, effectiveContextOptions?.qualifierOptions]);
|
|
342
|
-
|
|
343
|
-
// Get effective context values - contextValues already includes host values from the hook
|
|
344
|
-
const effectiveContextValues = useMemo(() => {
|
|
345
|
-
// contextValues from state already includes host values (it's effectiveContext from the hook)
|
|
346
|
-
// Don't double-apply host values here
|
|
347
|
-
return resolutionState?.contextValues || {};
|
|
348
|
-
}, [resolutionState?.contextValues]);
|
|
349
|
-
|
|
350
|
-
// Convert pending resources to PendingResource format for ResourcePicker
|
|
351
|
-
const pendingResourcesList = useMemo<PendingResource[]>(() => {
|
|
352
|
-
const pending: PendingResource[] = [];
|
|
353
|
-
|
|
354
|
-
// Add new pending resources
|
|
355
|
-
if (resolutionState?.pendingResources) {
|
|
356
|
-
resolutionState.pendingResources.forEach((resource, id) => {
|
|
357
|
-
pending.push({
|
|
358
|
-
id,
|
|
359
|
-
type: 'new',
|
|
360
|
-
resourceType: resource.resourceTypeName,
|
|
361
|
-
displayName: id // Use the resource ID as display name
|
|
362
|
-
});
|
|
363
|
-
});
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
// Add deleted resources
|
|
367
|
-
if (resolutionState?.pendingResourceDeletions) {
|
|
368
|
-
resolutionState.pendingResourceDeletions.forEach((id) => {
|
|
369
|
-
pending.push({
|
|
370
|
-
id,
|
|
371
|
-
type: 'deleted',
|
|
372
|
-
displayName: id
|
|
373
|
-
});
|
|
374
|
-
});
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
// Add edited resources
|
|
378
|
-
if (resolutionState?.editedResources) {
|
|
379
|
-
resolutionState.editedResources.forEach((_, id) => {
|
|
380
|
-
// Only add if not already in pending as new
|
|
381
|
-
if (!resolutionState.pendingResources?.has(id)) {
|
|
382
|
-
pending.push({
|
|
383
|
-
id,
|
|
384
|
-
type: 'modified',
|
|
385
|
-
displayName: id
|
|
386
|
-
});
|
|
387
|
-
}
|
|
388
|
-
});
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
return pending;
|
|
392
|
-
}, [
|
|
393
|
-
resolutionState?.pendingResources,
|
|
394
|
-
resolutionState?.pendingResourceDeletions,
|
|
395
|
-
resolutionState?.editedResources
|
|
396
|
-
]);
|
|
397
|
-
|
|
398
|
-
// Handle resource selection from ResourcePicker
|
|
399
|
-
const handleResourceSelect = useCallback(
|
|
400
|
-
(selection: ResourceSelection) => {
|
|
401
|
-
if (selection.resourceId) {
|
|
402
|
-
resolutionActions?.selectResource(selection.resourceId);
|
|
403
|
-
}
|
|
404
|
-
},
|
|
405
|
-
[resolutionActions]
|
|
406
|
-
);
|
|
407
|
-
|
|
408
|
-
// Handle new resource creation
|
|
409
|
-
const handleStartNewResource = useCallback(() => {
|
|
410
|
-
resolutionActions?.startNewResource(defaultResourceType);
|
|
411
|
-
setShowNewResourceModal(true);
|
|
412
|
-
}, [resolutionActions]);
|
|
413
|
-
|
|
414
|
-
const handleCloseNewResourceModal = useCallback(() => {
|
|
415
|
-
setShowNewResourceModal(false);
|
|
416
|
-
resolutionActions?.cancelNewResource();
|
|
417
|
-
}, [resolutionActions]);
|
|
418
|
-
|
|
419
|
-
const handleApplyPendingResources = useCallback(async () => {
|
|
420
|
-
await resolutionActions?.applyPendingResources();
|
|
421
|
-
if (onPendingResourcesApplied && resolutionState) {
|
|
422
|
-
const added = Array.from(resolutionState.pendingResources.values());
|
|
423
|
-
const deleted = Array.from(resolutionState.pendingResourceDeletions);
|
|
424
|
-
onPendingResourcesApplied(added, deleted);
|
|
425
|
-
}
|
|
426
|
-
}, [resolutionActions, resolutionState, onPendingResourcesApplied]);
|
|
427
|
-
|
|
428
|
-
// Automatically set locked view mode when provided
|
|
429
|
-
useEffect(() => {
|
|
430
|
-
if (lockedViewMode && resolutionActions?.setViewMode) {
|
|
431
|
-
resolutionActions.setViewMode(lockedViewMode);
|
|
432
|
-
}
|
|
433
|
-
}, [lockedViewMode, resolutionActions]);
|
|
434
|
-
|
|
435
|
-
// Handle view mode change
|
|
436
|
-
const handleViewModeChange = useCallback(
|
|
437
|
-
(mode: 'composed' | 'best' | 'all' | 'raw') => {
|
|
438
|
-
// Don't allow view mode changes when locked
|
|
439
|
-
if (!lockedViewMode) {
|
|
440
|
-
resolutionActions?.setViewMode(mode);
|
|
441
|
-
}
|
|
442
|
-
},
|
|
443
|
-
[resolutionActions, lockedViewMode]
|
|
444
|
-
);
|
|
445
|
-
|
|
446
|
-
if (!resources) {
|
|
447
|
-
return (
|
|
448
|
-
<div className={`p-6 ${className}`}>
|
|
449
|
-
<div className="flex items-center space-x-3 mb-6">
|
|
450
|
-
<MagnifyingGlassIcon className="h-8 w-8 text-blue-600" />
|
|
451
|
-
<h2 className="text-2xl font-bold text-gray-900">Resolution Viewer</h2>
|
|
452
|
-
</div>
|
|
453
|
-
|
|
454
|
-
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-8 text-center">
|
|
455
|
-
<div className="max-w-2xl mx-auto">
|
|
456
|
-
<h3 className="text-xl font-semibold text-gray-900 mb-4">No Resources Loaded</h3>
|
|
457
|
-
<p className="text-gray-600 mb-6">
|
|
458
|
-
Import resources first to test resource resolution with different contexts.
|
|
459
|
-
</p>
|
|
460
|
-
<div className="bg-blue-50 rounded-lg p-4">
|
|
461
|
-
<p className="text-sm text-blue-800">
|
|
462
|
-
<strong>Resolution Viewer:</strong> Test how resources resolve with different qualifier
|
|
463
|
-
contexts. Set context values and see which candidates match.
|
|
464
|
-
</p>
|
|
465
|
-
</div>
|
|
466
|
-
</div>
|
|
467
|
-
</div>
|
|
468
|
-
</div>
|
|
469
|
-
);
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
return (
|
|
473
|
-
<div className={`p-6 ${className}`}>
|
|
474
|
-
<div className="flex items-center space-x-3 mb-6">
|
|
475
|
-
<MagnifyingGlassIcon className="h-8 w-8 text-blue-600" />
|
|
476
|
-
<h2 className="text-2xl font-bold text-gray-900">Resolution Viewer</h2>
|
|
477
|
-
{isFilteringActive && (
|
|
478
|
-
<span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-purple-100 text-purple-800">
|
|
479
|
-
Filtered
|
|
480
|
-
</span>
|
|
481
|
-
)}
|
|
482
|
-
</div>
|
|
483
|
-
|
|
484
|
-
{/* ResourcePicker Options Control */}
|
|
485
|
-
<ResourcePickerOptionsControl
|
|
486
|
-
options={currentPickerOptions}
|
|
487
|
-
onOptionsChange={setCurrentPickerOptions}
|
|
488
|
-
presentation={pickerOptionsPresentation}
|
|
489
|
-
title="Resolution Viewer Picker Options"
|
|
490
|
-
className="mb-6"
|
|
491
|
-
/>
|
|
492
|
-
|
|
493
|
-
{/* ResolutionContext Options Control */}
|
|
494
|
-
<ResolutionContextOptionsControl
|
|
495
|
-
options={currentContextOptions}
|
|
496
|
-
onOptionsChange={setCurrentContextOptions}
|
|
497
|
-
availableQualifiers={availableQualifiers}
|
|
498
|
-
presentation={pickerOptionsPresentation}
|
|
499
|
-
title="Resolution Context Options"
|
|
500
|
-
className="mb-6"
|
|
501
|
-
allowResourceCreation={allowResourceCreationInternal}
|
|
502
|
-
onAllowResourceCreationChange={setAllowResourceCreationInternal}
|
|
503
|
-
showPendingResourcesInList={showPendingResourcesInListInternal}
|
|
504
|
-
onShowPendingResourcesInListChange={setShowPendingResourcesInListInternal}
|
|
505
|
-
/>
|
|
506
|
-
|
|
507
|
-
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
|
|
508
|
-
{/* Context Configuration Panel */}
|
|
509
|
-
{effectiveContextOptions?.showContextControls !== false && (
|
|
510
|
-
<div className="mb-6">
|
|
511
|
-
<h3 className="text-lg font-semibold text-gray-900 mb-4">
|
|
512
|
-
{effectiveContextOptions?.contextPanelTitle || 'Context Configuration'}
|
|
513
|
-
</h3>
|
|
514
|
-
<div
|
|
515
|
-
className={`bg-gray-50 rounded-lg p-4 ${effectiveContextOptions?.contextPanelClassName || ''}`}
|
|
516
|
-
>
|
|
517
|
-
<div className="mb-4">
|
|
518
|
-
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3">
|
|
519
|
-
{visibleQualifiers.map((qualifierName) => {
|
|
520
|
-
const qualifierOptions = effectiveContextOptions?.qualifierOptions?.[qualifierName];
|
|
521
|
-
const hostManagedValue = effectiveContextOptions?.hostManagedValues?.[qualifierName];
|
|
522
|
-
const globalPlaceholder =
|
|
523
|
-
typeof effectiveContextOptions?.globalPlaceholder === 'function'
|
|
524
|
-
? effectiveContextOptions.globalPlaceholder(qualifierName)
|
|
525
|
-
: effectiveContextOptions?.globalPlaceholder;
|
|
526
|
-
|
|
527
|
-
// Merge host-managed values with qualifier options
|
|
528
|
-
const mergedOptions = {
|
|
529
|
-
...qualifierOptions,
|
|
530
|
-
// Host-managed values override qualifier-specific host values
|
|
531
|
-
hostValue:
|
|
532
|
-
hostManagedValue !== undefined ? hostManagedValue : qualifierOptions?.hostValue
|
|
533
|
-
};
|
|
534
|
-
|
|
535
|
-
return (
|
|
536
|
-
<QualifierContextControl
|
|
537
|
-
key={qualifierName}
|
|
538
|
-
qualifierName={qualifierName}
|
|
539
|
-
value={resolutionState?.pendingContextValues[qualifierName]}
|
|
540
|
-
onChange={handleQualifierChange}
|
|
541
|
-
placeholder={globalPlaceholder || `Enter ${qualifierName} value`}
|
|
542
|
-
resources={activeProcessedResources}
|
|
543
|
-
options={mergedOptions}
|
|
544
|
-
/>
|
|
545
|
-
);
|
|
546
|
-
})}
|
|
547
|
-
</div>
|
|
548
|
-
</div>
|
|
549
|
-
|
|
550
|
-
{effectiveContextOptions?.showCurrentContext !== false && (
|
|
551
|
-
<div className="flex items-center justify-between">
|
|
552
|
-
<div className="text-sm text-gray-600">
|
|
553
|
-
Current:{' '}
|
|
554
|
-
{Object.entries(effectiveContextValues)
|
|
555
|
-
.map(([key, value]) => `${key}=${value === undefined ? '(undefined)' : value}`)
|
|
556
|
-
.join(', ')}
|
|
557
|
-
</div>
|
|
558
|
-
{effectiveContextOptions?.showContextActions !== false && (
|
|
559
|
-
<div className="flex items-center space-x-2">
|
|
560
|
-
<button
|
|
561
|
-
onClick={resolutionActions?.resetCache}
|
|
562
|
-
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"
|
|
563
|
-
title="Clear resolution cache"
|
|
564
|
-
>
|
|
565
|
-
Clear Cache
|
|
566
|
-
</button>
|
|
567
|
-
<button
|
|
568
|
-
onClick={() => resolutionActions?.applyContext()}
|
|
569
|
-
disabled={!resolutionState?.hasPendingChanges}
|
|
570
|
-
className={`px-4 py-2 rounded-md text-sm font-medium ${
|
|
571
|
-
resolutionState?.hasPendingChanges
|
|
572
|
-
? 'bg-blue-600 text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500'
|
|
573
|
-
: 'bg-gray-300 text-gray-500 cursor-not-allowed'
|
|
574
|
-
}`}
|
|
575
|
-
>
|
|
576
|
-
{resolutionState?.hasPendingChanges
|
|
577
|
-
? 'Apply Changes'
|
|
578
|
-
: resolutionState?.currentResolver
|
|
579
|
-
? 'Context Applied'
|
|
580
|
-
: 'Apply Context'}
|
|
581
|
-
</button>
|
|
582
|
-
</div>
|
|
583
|
-
)}
|
|
584
|
-
</div>
|
|
585
|
-
)}
|
|
586
|
-
</div>
|
|
587
|
-
</div>
|
|
588
|
-
)}
|
|
589
|
-
|
|
590
|
-
{/* Unified Change Controls - replaces separate edit/pending controls */}
|
|
591
|
-
{(resolutionState?.hasUnsavedEdits || resolutionState?.hasPendingResourceChanges) && (
|
|
592
|
-
<div className="mt-6">
|
|
593
|
-
<UnifiedChangeControls
|
|
594
|
-
editCount={resolutionState?.editedResources?.size || 0}
|
|
595
|
-
addCount={resolutionState?.pendingResources?.size || 0}
|
|
596
|
-
deleteCount={resolutionState?.pendingResourceDeletions?.size || 0}
|
|
597
|
-
isApplying={resolutionState?.isApplyingEdits}
|
|
598
|
-
disabled={!resolutionState?.currentResolver}
|
|
599
|
-
onApplyAll={async () => {
|
|
600
|
-
await handleApplyPendingResources();
|
|
601
|
-
}}
|
|
602
|
-
onDiscardAll={() => {
|
|
603
|
-
resolutionActions?.discardEdits?.();
|
|
604
|
-
resolutionActions?.discardPendingResources?.();
|
|
605
|
-
}}
|
|
606
|
-
/>
|
|
607
|
-
</div>
|
|
608
|
-
)}
|
|
609
|
-
|
|
610
|
-
{/* Main Browser/Details Layout */}
|
|
611
|
-
<div className="flex flex-col lg:flex-row gap-6 h-[600px]">
|
|
612
|
-
{/* Left side: Resource Selection */}
|
|
613
|
-
<div className="lg:w-1/2 flex flex-col">
|
|
614
|
-
<div className="flex items-center justify-between mb-4">
|
|
615
|
-
<h3 className="text-lg font-semibold text-gray-900">
|
|
616
|
-
{sectionTitles?.resources || 'Resources'}
|
|
617
|
-
</h3>
|
|
618
|
-
{allowResourceCreationInternal && (
|
|
619
|
-
<button
|
|
620
|
-
onClick={handleStartNewResource}
|
|
621
|
-
className="flex items-center space-x-1 px-3 py-1.5 text-sm font-medium text-blue-600 bg-blue-50 rounded-md hover:bg-blue-100 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
622
|
-
title="Create a new resource"
|
|
623
|
-
>
|
|
624
|
-
<PlusIcon className="h-4 w-4" />
|
|
625
|
-
<span>Add Resource</span>
|
|
626
|
-
</button>
|
|
627
|
-
)}
|
|
628
|
-
</div>
|
|
629
|
-
|
|
630
|
-
<div className="flex-1">
|
|
631
|
-
<ResourcePicker
|
|
632
|
-
resources={activeProcessedResources || null}
|
|
633
|
-
selectedResourceId={resolutionState?.selectedResourceId || null}
|
|
634
|
-
onResourceSelect={handleResourceSelect}
|
|
635
|
-
resourceAnnotations={resourceAnnotations}
|
|
636
|
-
pendingResources={showPendingResourcesInListInternal ? pendingResourcesList : undefined}
|
|
637
|
-
options={effectivePickerOptions}
|
|
638
|
-
onMessage={onMessage}
|
|
639
|
-
/>
|
|
640
|
-
</div>
|
|
641
|
-
</div>
|
|
642
|
-
|
|
643
|
-
{/* Right side: Resolution Results */}
|
|
644
|
-
<div className="lg:w-1/2 flex flex-col">
|
|
645
|
-
<div className="flex items-center justify-between mb-4">
|
|
646
|
-
<h3 className="text-lg font-semibold text-gray-900">
|
|
647
|
-
{sectionTitles?.results || 'Results'}
|
|
648
|
-
{lockedViewMode && (
|
|
649
|
-
<span className="ml-2 inline-flex items-center px-2 py-1 text-xs font-medium bg-blue-100 text-blue-800 rounded-full">
|
|
650
|
-
{lockedViewMode.charAt(0).toUpperCase() + lockedViewMode.slice(1)} View
|
|
651
|
-
</span>
|
|
652
|
-
)}
|
|
653
|
-
</h3>
|
|
654
|
-
{resolutionState?.selectedResourceId && !lockedViewMode && (
|
|
655
|
-
<div className="flex space-x-2">
|
|
656
|
-
<button
|
|
657
|
-
onClick={() => handleViewModeChange('composed')}
|
|
658
|
-
className={`px-3 py-1 text-xs rounded ${
|
|
659
|
-
resolutionState?.viewMode === 'composed'
|
|
660
|
-
? 'bg-blue-600 text-white'
|
|
661
|
-
: 'bg-gray-200 text-gray-700'
|
|
662
|
-
}`}
|
|
663
|
-
>
|
|
664
|
-
Composed
|
|
665
|
-
</button>
|
|
666
|
-
<button
|
|
667
|
-
onClick={() => handleViewModeChange('best')}
|
|
668
|
-
className={`px-3 py-1 text-xs rounded ${
|
|
669
|
-
resolutionState?.viewMode === 'best'
|
|
670
|
-
? 'bg-blue-600 text-white'
|
|
671
|
-
: 'bg-gray-200 text-gray-700'
|
|
672
|
-
}`}
|
|
673
|
-
>
|
|
674
|
-
Best
|
|
675
|
-
</button>
|
|
676
|
-
<button
|
|
677
|
-
onClick={() => handleViewModeChange('all')}
|
|
678
|
-
className={`px-3 py-1 text-xs rounded ${
|
|
679
|
-
resolutionState?.viewMode === 'all'
|
|
680
|
-
? 'bg-blue-600 text-white'
|
|
681
|
-
: 'bg-gray-200 text-gray-700'
|
|
682
|
-
}`}
|
|
683
|
-
>
|
|
684
|
-
All
|
|
685
|
-
</button>
|
|
686
|
-
<button
|
|
687
|
-
onClick={() => handleViewModeChange('raw')}
|
|
688
|
-
className={`px-3 py-1 text-xs rounded ${
|
|
689
|
-
resolutionState?.viewMode === 'raw'
|
|
690
|
-
? 'bg-blue-600 text-white'
|
|
691
|
-
: 'bg-gray-200 text-gray-700'
|
|
692
|
-
}`}
|
|
693
|
-
>
|
|
694
|
-
Raw
|
|
695
|
-
</button>
|
|
696
|
-
</div>
|
|
697
|
-
)}
|
|
698
|
-
</div>
|
|
699
|
-
|
|
700
|
-
<div className="flex-1 overflow-y-auto border border-gray-200 rounded-lg p-4 bg-gray-50">
|
|
701
|
-
{!resolutionState?.selectedResourceId ? (
|
|
702
|
-
<div className="flex items-center justify-center h-full">
|
|
703
|
-
<div className="text-center">
|
|
704
|
-
<CubeIcon className="h-12 w-12 text-gray-400 mx-auto mb-4" />
|
|
705
|
-
<p className="text-gray-500">Select a resource to view resolution results</p>
|
|
706
|
-
</div>
|
|
707
|
-
</div>
|
|
708
|
-
) : !resolutionState?.currentResolver ? (
|
|
709
|
-
<div className="text-center text-gray-500">
|
|
710
|
-
<p>Apply a context to resolve resources</p>
|
|
711
|
-
</div>
|
|
712
|
-
) : !resolutionState?.resolutionResult ? (
|
|
713
|
-
<div className="text-center text-gray-500">
|
|
714
|
-
<p>Resolving...</p>
|
|
715
|
-
</div>
|
|
716
|
-
) : (
|
|
717
|
-
<ResolutionResults
|
|
718
|
-
result={resolutionState.resolutionResult}
|
|
719
|
-
viewMode={resolutionState.viewMode}
|
|
720
|
-
contextValues={resolutionState.contextValues}
|
|
721
|
-
resolutionActions={resolutionActions}
|
|
722
|
-
resolutionState={resolutionState}
|
|
723
|
-
resourceEditorFactory={resourceEditorFactory}
|
|
724
|
-
onMessage={onMessage}
|
|
725
|
-
/>
|
|
726
|
-
)}
|
|
727
|
-
</div>
|
|
728
|
-
</div>
|
|
729
|
-
</div>
|
|
730
|
-
</div>
|
|
731
|
-
|
|
732
|
-
{/* New Resource Modal */}
|
|
733
|
-
{resolutionState?.newResourceDraft && (
|
|
734
|
-
<NewResourceModal
|
|
735
|
-
isOpen={showNewResourceModal}
|
|
736
|
-
onClose={handleCloseNewResourceModal}
|
|
737
|
-
resourceId={resolutionState.newResourceDraft.resourceId}
|
|
738
|
-
resourceType={resolutionState.newResourceDraft.resourceType}
|
|
739
|
-
availableResourceTypes={resolutionState.availableResourceTypes}
|
|
740
|
-
isValid={resolutionState.newResourceDraft.isValid}
|
|
741
|
-
defaultResourceType={defaultResourceType}
|
|
742
|
-
onUpdateResourceId={resolutionActions?.updateNewResourceId || (() => {})}
|
|
743
|
-
onSelectResourceType={resolutionActions?.selectResourceType || (() => {})}
|
|
744
|
-
onSave={resolutionActions?.saveNewResourceAsPending || (() => {})}
|
|
745
|
-
/>
|
|
746
|
-
)}
|
|
747
|
-
</div>
|
|
748
|
-
);
|
|
749
|
-
};
|
|
750
|
-
|
|
751
|
-
export default ResolutionView;
|