@optimizely/ocp-local-env 1.0.0-beta.9 → 1.0.1
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 +18 -133
- package/dist/package.json +15 -9
- package/dist/public/bundle.fa87c838198caf8c051a.js +3 -0
- package/dist/public/{bundle.82dc5d29fffb9f205051.js.LICENSE.txt → bundle.fa87c838198caf8c051a.js.LICENSE.txt} +3 -3
- package/dist/public/bundle.fa87c838198caf8c051a.js.map +1 -0
- package/dist/public/index.html +1 -1
- package/dist/src/cli.js +2 -2
- package/dist/src/cli.js.map +1 -1
- package/dist/src/executor/FunctionExecutor.js +8 -5
- package/dist/src/executor/FunctionExecutor.js.map +1 -1
- package/dist/src/executor/JobExecutor.js +0 -17
- package/dist/src/executor/JobExecutor.js.map +1 -1
- package/dist/src/executor/LifecycleExecutor.js +11 -2
- package/dist/src/executor/LifecycleExecutor.js.map +1 -1
- package/dist/src/executor/watcher.d.ts +6 -0
- package/dist/src/executor/watcher.js +45 -0
- package/dist/src/executor/watcher.js.map +1 -1
- package/dist/src/local_engine/LocalJobApi.d.ts +31 -2
- package/dist/src/local_engine/LocalJobApi.js +42 -17
- package/dist/src/local_engine/LocalJobApi.js.map +1 -1
- package/dist/src/local_engine/LocalNotifier.d.ts +3 -2
- package/dist/src/local_engine/LocalNotifier.js +7 -0
- package/dist/src/local_engine/LocalNotifier.js.map +1 -1
- package/dist/src/local_engine/LocalSourceApi.d.ts +40 -0
- package/dist/src/local_engine/LocalSourceApi.js +69 -0
- package/dist/src/local_engine/LocalSourceApi.js.map +1 -0
- package/dist/src/local_engine/local-engine-child-base.d.ts +0 -12
- package/dist/src/local_engine/local-engine-child-base.js +0 -127
- package/dist/src/local_engine/local-engine-child-base.js.map +1 -1
- package/dist/src/local_engine/local-engine-client.d.ts +19 -29
- package/dist/src/local_engine/local-engine-client.js +45 -94
- package/dist/src/local_engine/local-engine-client.js.map +1 -1
- package/dist/src/local_engine/local-engine-types.d.ts +13 -50
- package/dist/src/local_engine/local-engine-unified.d.ts +6 -13
- package/dist/src/local_engine/local-engine-unified.js +108 -222
- package/dist/src/local_engine/local-engine-unified.js.map +1 -1
- package/dist/src/local_engine/localSDKConfig.d.ts +6 -0
- package/dist/src/local_engine/localSDKConfig.js +66 -1
- package/dist/src/local_engine/localSDKConfig.js.map +1 -1
- package/dist/src/local_engine/storage/BaseKVStoreWrapper.d.ts +1 -2
- package/dist/src/local_engine/storage/BaseKVStoreWrapper.js.map +1 -1
- package/dist/src/local_engine/storage/LocalConfigStore.d.ts +7 -13
- package/dist/src/local_engine/storage/LocalConfigStore.js +9 -31
- package/dist/src/local_engine/storage/LocalConfigStore.js.map +1 -1
- package/dist/src/local_engine/storage/LocalKVStore.d.ts +4 -0
- package/dist/src/local_engine/storage/LocalKVStore.js +23 -0
- package/dist/src/local_engine/storage/LocalKVStore.js.map +1 -1
- package/dist/src/local_engine/storage/SourceDataStore.d.ts +16 -14
- package/dist/src/local_engine/storage/SourceDataStore.js +57 -57
- package/dist/src/local_engine/storage/SourceDataStore.js.map +1 -1
- package/dist/src/local_engine/utils.d.ts +2 -0
- package/dist/src/local_engine/utils.js +4 -2
- package/dist/src/local_engine/utils.js.map +1 -1
- package/dist/src/server/api/deploy.d.ts +20 -0
- package/dist/src/server/api/deploy.js +399 -0
- package/dist/src/server/api/deploy.js.map +1 -0
- package/dist/src/server/api/destinations.js +1 -1
- package/dist/src/server/api/destinations.js.map +1 -1
- package/dist/src/server/api/env.d.ts +2 -0
- package/dist/src/server/api/env.js +28 -0
- package/dist/src/server/api/env.js.map +1 -0
- package/dist/src/server/api/functions.js +13 -12
- package/dist/src/server/api/functions.js.map +1 -1
- package/dist/src/server/api/opalTools.d.ts +4 -0
- package/dist/src/server/api/opalTools.js +81 -0
- package/dist/src/server/api/opalTools.js.map +1 -0
- package/dist/src/server/api/schema.d.ts +6 -0
- package/dist/src/server/api/schema.js +95 -0
- package/dist/src/server/api/schema.js.map +1 -0
- package/dist/src/server/api/sources.d.ts +1 -2
- package/dist/src/server/api/sources.js +16 -275
- package/dist/src/server/api/sources.js.map +1 -1
- package/dist/src/server/api/v1.js +63 -55
- package/dist/src/server/api/v1.js.map +1 -1
- package/dist/src/server/api.d.ts +4 -0
- package/dist/src/server/api.js +131 -9
- package/dist/src/server/api.js.map +1 -1
- package/dist/src/server/app-discovery.js +37 -4
- package/dist/src/server/app-discovery.js.map +1 -1
- package/dist/src/server/app-env.d.ts +21 -0
- package/dist/src/server/app-env.js +122 -0
- package/dist/src/server/app-env.js.map +1 -0
- package/dist/src/server/browserFocus.d.ts +5 -0
- package/dist/src/server/browserFocus.js +39 -0
- package/dist/src/server/browserFocus.js.map +1 -0
- package/dist/src/server/config.d.ts +3 -0
- package/dist/src/server/config.js +7 -0
- package/dist/src/server/config.js.map +1 -1
- package/dist/src/server/mockDataGenerator.d.ts +1 -2
- package/dist/src/server/mockDataGenerator.js +77 -35
- package/dist/src/server/mockDataGenerator.js.map +1 -1
- package/dist/src/server/mockToolDataGenerator.d.ts +12 -0
- package/dist/src/server/mockToolDataGenerator.js +393 -0
- package/dist/src/server/mockToolDataGenerator.js.map +1 -0
- package/dist/src/server.js +152 -168
- package/dist/src/server.js.map +1 -1
- package/dist/src/types/app.d.ts +1 -3
- package/dist/src/types/app.js.map +1 -1
- package/dist/src/ui/components/App.js +303 -47
- package/dist/src/ui/components/App.js.map +1 -1
- package/dist/src/ui/components/DeployModal.d.ts +16 -0
- package/dist/src/ui/components/DeployModal.js +75 -0
- package/dist/src/ui/components/DeployModal.js.map +1 -0
- package/dist/src/ui/components/DestinationBatchEditor.d.ts +9 -1
- package/dist/src/ui/components/DestinationBatchEditor.js +12 -4
- package/dist/src/ui/components/DestinationBatchEditor.js.map +1 -1
- package/dist/src/ui/components/DestinationsView.js +5 -1
- package/dist/src/ui/components/DestinationsView.js.map +1 -1
- package/dist/src/ui/components/EntityNotAvailable.d.ts +15 -0
- package/dist/src/ui/components/EntityNotAvailable.js +27 -0
- package/dist/src/ui/components/EntityNotAvailable.js.map +1 -0
- package/dist/src/ui/components/EnvViewer.d.ts +8 -0
- package/dist/src/ui/components/EnvViewer.js +35 -0
- package/dist/src/ui/components/EnvViewer.js.map +1 -0
- package/dist/src/ui/components/FunctionsView.d.ts +2 -6
- package/dist/src/ui/components/FunctionsView.js +52 -75
- package/dist/src/ui/components/FunctionsView.js.map +1 -1
- package/dist/src/ui/components/JobsView.js +4 -4
- package/dist/src/ui/components/JobsView.js.map +1 -1
- package/dist/src/ui/components/KVStoreViewer.js +5 -5
- package/dist/src/ui/components/KVStoreViewer.js.map +1 -1
- package/dist/src/ui/components/KeyValueEditor.d.ts +15 -0
- package/dist/src/ui/components/KeyValueEditor.js +12 -0
- package/dist/src/ui/components/KeyValueEditor.js.map +1 -0
- package/dist/src/ui/components/NotificationViewer.d.ts +2 -11
- package/dist/src/ui/components/NotificationViewer.js +69 -15
- package/dist/src/ui/components/NotificationViewer.js.map +1 -1
- package/dist/src/ui/components/OdpSchemaView.d.ts +3 -0
- package/dist/src/ui/components/OdpSchemaView.js +58 -0
- package/dist/src/ui/components/OdpSchemaView.js.map +1 -0
- package/dist/src/ui/components/OpalToolsView.d.ts +9 -0
- package/dist/src/ui/components/OpalToolsView.js +399 -0
- package/dist/src/ui/components/OpalToolsView.js.map +1 -0
- package/dist/src/ui/components/ResponseViewer.d.ts +39 -0
- package/dist/src/ui/components/ResponseViewer.js +43 -0
- package/dist/src/ui/components/ResponseViewer.js.map +1 -0
- package/dist/src/ui/components/SecretsStoreViewer.js +3 -2
- package/dist/src/ui/components/SecretsStoreViewer.js.map +1 -1
- package/dist/src/ui/components/SettingsStoreViewer.js +3 -2
- package/dist/src/ui/components/SettingsStoreViewer.js.map +1 -1
- package/dist/src/ui/components/SourceEmittedDataPanel.d.ts +8 -0
- package/dist/src/ui/components/SourceEmittedDataPanel.js +103 -0
- package/dist/src/ui/components/SourceEmittedDataPanel.js.map +1 -0
- package/dist/src/ui/components/SourcesView.js +4 -8
- package/dist/src/ui/components/SourcesView.js.map +1 -1
- package/dist/src/ui/components/StoreViewer.js +2 -1
- package/dist/src/ui/components/StoreViewer.js.map +1 -1
- package/dist/src/ui/components/TabbedConsole.d.ts +11 -0
- package/dist/src/ui/components/TabbedConsole.js +134 -44
- package/dist/src/ui/components/TabbedConsole.js.map +1 -1
- package/dist/src/ui/components/ToolSettingsView.d.ts +7 -0
- package/dist/src/ui/components/ToolSettingsView.js +25 -0
- package/dist/src/ui/components/ToolSettingsView.js.map +1 -0
- package/dist/src/ui/components/common/EyeIcon.js +2 -1
- package/dist/src/ui/components/common/EyeIcon.js.map +1 -1
- package/dist/src/ui/hooks/useKeyValuePairs.d.ts +52 -0
- package/dist/src/ui/hooks/useKeyValuePairs.js +66 -0
- package/dist/src/ui/hooks/useKeyValuePairs.js.map +1 -0
- package/dist/src/ui/store/formStateSlice.d.ts +19 -2
- package/dist/src/ui/store/formStateSlice.js +69 -4
- package/dist/src/ui/store/formStateSlice.js.map +1 -1
- package/dist/src/ui/types/common.d.ts +33 -0
- package/dist/src/ui/types/common.js +6 -0
- package/dist/src/ui/types/common.js.map +1 -0
- package/package.json +15 -9
- package/dist/public/bundle.82dc5d29fffb9f205051.js +0 -3
- package/dist/public/bundle.82dc5d29fffb9f205051.js.map +0 -1
- package/dist/src/executor/SourceExecutor.d.ts +0 -32
- package/dist/src/executor/SourceExecutor.js +0 -163
- package/dist/src/executor/SourceExecutor.js.map +0 -1
- package/dist/src/local_engine/storage/SourceJobExecutionStore.d.ts +0 -25
- package/dist/src/local_engine/storage/SourceJobExecutionStore.js +0 -61
- package/dist/src/local_engine/storage/SourceJobExecutionStore.js.map +0 -1
- package/dist/src/ui/components/SourceDataViewer.d.ts +0 -8
- package/dist/src/ui/components/SourceDataViewer.js +0 -84
- package/dist/src/ui/components/SourceDataViewer.js.map +0 -1
- package/dist/src/ui/components/SourceJobsSection.d.ts +0 -8
- package/dist/src/ui/components/SourceJobsSection.js +0 -99
- package/dist/src/ui/components/SourceJobsSection.js.map +0 -1
- package/dist/src/ui/components/SourceLifecycleSection.d.ts +0 -7
- package/dist/src/ui/components/SourceLifecycleSection.js +0 -58
- package/dist/src/ui/components/SourceLifecycleSection.js.map +0 -1
- package/dist/src/ui/components/SourceWebhookEditor.d.ts +0 -8
- package/dist/src/ui/components/SourceWebhookEditor.js +0 -181
- package/dist/src/ui/components/SourceWebhookEditor.js.map +0 -1
|
@@ -11,8 +11,13 @@ const JobsView_1 = __importDefault(require("./JobsView"));
|
|
|
11
11
|
const TabbedConsole_1 = __importDefault(require("./TabbedConsole"));
|
|
12
12
|
const DestinationsView_1 = require("./DestinationsView");
|
|
13
13
|
const SourcesView_1 = require("./SourcesView");
|
|
14
|
+
const OpalToolsView_1 = __importDefault(require("./OpalToolsView"));
|
|
15
|
+
const ToolSettingsView_1 = __importDefault(require("./ToolSettingsView"));
|
|
16
|
+
const OdpSchemaView_1 = __importDefault(require("./OdpSchemaView"));
|
|
14
17
|
const useQueryParams_1 = require("../hooks/useQueryParams");
|
|
15
18
|
const store_1 = require("../store");
|
|
19
|
+
const axiom_icons_1 = require("@optimizely/axiom-icons");
|
|
20
|
+
const DeployModal_1 = require("./DeployModal");
|
|
16
21
|
const IFRAME_RESIZER_MESSAGES_PREFIX = "[iFrameSizer]app_directory_frame_directory";
|
|
17
22
|
const IFRAME_RESIZER_READY_MESSAGE = `${IFRAME_RESIZER_MESSAGES_PREFIX}:8:false:false:32:true:true:null:bodyOffset:null:null:0:false:parent:scroll:true`;
|
|
18
23
|
// Ex.: [iFrameSizer]app_directory_frame_directory:7096:1955:mutationObserver
|
|
@@ -42,11 +47,27 @@ const App = () => {
|
|
|
42
47
|
const [buildStatus, setBuildStatus] = (0, react_1.useState)(null);
|
|
43
48
|
const [storeTimestamps, setStoreTimestamps] = (0, react_1.useState)(null);
|
|
44
49
|
const [appInstalled, setAppInstalled] = (0, react_1.useState)(false);
|
|
50
|
+
// Install version counter - increments on each install to force UI refresh
|
|
51
|
+
const [installVersion, setInstallVersion] = (0, react_1.useState)(0);
|
|
45
52
|
const [notificationCount, setNotificationCount] = (0, react_1.useState)(0);
|
|
46
53
|
const [config, setConfig] = (0, react_1.useState)({
|
|
47
54
|
showZaiusAdminSections: false
|
|
48
55
|
});
|
|
49
|
-
const [
|
|
56
|
+
const [permanentlyDisconnected, setPermanentlyDisconnected] = (0, react_1.useState)(false);
|
|
57
|
+
const [appChanged, setAppChanged] = (0, react_1.useState)(null);
|
|
58
|
+
const [sourceDataVersion, setSourceDataVersion] = (0, react_1.useState)(0);
|
|
59
|
+
const [sourceDataTotalEmitted, setSourceDataTotalEmitted] = (0, react_1.useState)(0);
|
|
60
|
+
const [notificationVersion, setNotificationVersion] = (0, react_1.useState)(0);
|
|
61
|
+
const [envVersion, setEnvVersion] = (0, react_1.useState)(0);
|
|
62
|
+
const [deployStatus, setDeployStatus] = (0, react_1.useState)({ deployInProgress: false, lastDeploySuccess: null });
|
|
63
|
+
const [deployLogs, setDeployLogs] = (0, react_1.useState)([]);
|
|
64
|
+
const [deployVersion, setDeployVersion] = (0, react_1.useState)(0);
|
|
65
|
+
const [showDeployModal, setShowDeployModal] = (0, react_1.useState)(false);
|
|
66
|
+
const [deployModalData, setDeployModalData] = (0, react_1.useState)(null);
|
|
67
|
+
// Reference to store disconnect timer for 30-second timeout
|
|
68
|
+
const disconnectTimerRef = (0, react_1.useRef)(null);
|
|
69
|
+
// Reference to store initial app info for change detection
|
|
70
|
+
const initialAppInfoRef = (0, react_1.useRef)(null);
|
|
50
71
|
// Initialize Redux store with app name when appInfo is available
|
|
51
72
|
(0, react_1.useEffect)(() => {
|
|
52
73
|
if (appInfo?.name) {
|
|
@@ -55,9 +76,10 @@ const App = () => {
|
|
|
55
76
|
}, [appInfo?.name]);
|
|
56
77
|
// Reference to store polling interval IDs
|
|
57
78
|
const pollingIntervals = (0, react_1.useRef)({
|
|
58
|
-
logs: null,
|
|
59
79
|
status: null,
|
|
60
80
|
});
|
|
81
|
+
// Reference to store EventSource for cleanup on page unload
|
|
82
|
+
const eventSourceRef = (0, react_1.useRef)(null);
|
|
61
83
|
// Reference to the settings iframe
|
|
62
84
|
const settingsIframeRef = (0, react_1.useRef)(null);
|
|
63
85
|
const setIframeRef = (iframe) => {
|
|
@@ -83,7 +105,38 @@ const App = () => {
|
|
|
83
105
|
}
|
|
84
106
|
}
|
|
85
107
|
})}`;
|
|
86
|
-
settingsIframeRef.current.contentWindow.postMessage(userFeaturesMessage,
|
|
108
|
+
settingsIframeRef.current.contentWindow.postMessage(userFeaturesMessage, window.location.origin);
|
|
109
|
+
// Send prismContext with mock organization ID to prevent "Organization ID is missing" errors
|
|
110
|
+
const prismContextMessage = `[iFrameSizer]message:${JSON.stringify({
|
|
111
|
+
method: 'prismContext',
|
|
112
|
+
params: {
|
|
113
|
+
productName: 'local-dev',
|
|
114
|
+
subProductName: 'ocp-local-env',
|
|
115
|
+
trackerId: 'local-development-tracker-id',
|
|
116
|
+
scope: 1,
|
|
117
|
+
originalUser: {
|
|
118
|
+
id: 1,
|
|
119
|
+
email: 'local-dev@example.com',
|
|
120
|
+
name: 'Local Developer',
|
|
121
|
+
isOptiId: false,
|
|
122
|
+
isInternalUser: true,
|
|
123
|
+
optiIdAccessToken: 'local-dev-mock-token'
|
|
124
|
+
},
|
|
125
|
+
organization: {
|
|
126
|
+
id: 1,
|
|
127
|
+
name: 'Local Development Org',
|
|
128
|
+
masterCustomerId: 'local-master-customer',
|
|
129
|
+
turnstileOrganizationId: 'local-test-org'
|
|
130
|
+
},
|
|
131
|
+
account: {
|
|
132
|
+
id: 1,
|
|
133
|
+
name: 'Local Development Account',
|
|
134
|
+
instanceId: 'local-test-instance',
|
|
135
|
+
isOptiHub: false
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
})}`;
|
|
139
|
+
settingsIframeRef.current.contentWindow.postMessage(prismContextMessage, window.location.origin);
|
|
87
140
|
console.log("Sent ready event to iframe after 2 second delay");
|
|
88
141
|
}
|
|
89
142
|
}, 2000);
|
|
@@ -108,15 +161,19 @@ const App = () => {
|
|
|
108
161
|
};
|
|
109
162
|
// Set up polling on component mount
|
|
110
163
|
(0, react_1.useEffect)(() => {
|
|
111
|
-
//
|
|
164
|
+
// Don't set up new connections if permanently disconnected
|
|
165
|
+
if (permanentlyDisconnected) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
// Initial data load (logs come via SSE initialLogs event)
|
|
112
169
|
fetchConfig();
|
|
113
170
|
fetchAppInfo();
|
|
114
171
|
fetchStatus();
|
|
115
|
-
fetchConsoleLogs();
|
|
116
172
|
fetchInstallationStatus();
|
|
117
173
|
fetchNotificationCount();
|
|
118
174
|
// Set up SSE connection for real-time build status updates
|
|
119
175
|
const eventSource = new EventSource('/devserver/api/events');
|
|
176
|
+
eventSourceRef.current = eventSource;
|
|
120
177
|
eventSource.onmessage = (event) => {
|
|
121
178
|
const data = JSON.parse(event.data);
|
|
122
179
|
switch (data.type) {
|
|
@@ -130,6 +187,10 @@ const App = () => {
|
|
|
130
187
|
lastBuildTimestamp: null,
|
|
131
188
|
lastBuildError: null
|
|
132
189
|
});
|
|
190
|
+
// Reset deploy success status on code change (build start)
|
|
191
|
+
if (!deployStatus.deployInProgress) {
|
|
192
|
+
setDeployStatus(prev => ({ ...prev, lastDeploySuccess: null }));
|
|
193
|
+
}
|
|
133
194
|
break;
|
|
134
195
|
case 'buildSuccess':
|
|
135
196
|
setBuildStatus({
|
|
@@ -138,8 +199,7 @@ const App = () => {
|
|
|
138
199
|
lastBuildTimestamp: data.timestamp,
|
|
139
200
|
lastBuildError: null
|
|
140
201
|
});
|
|
141
|
-
// Refresh
|
|
142
|
-
fetchConsoleLogs();
|
|
202
|
+
// Refresh store timestamps after build (logs come via SSE)
|
|
143
203
|
fetchStatus();
|
|
144
204
|
break;
|
|
145
205
|
case 'buildError':
|
|
@@ -149,7 +209,6 @@ const App = () => {
|
|
|
149
209
|
lastBuildTimestamp: data.timestamp,
|
|
150
210
|
lastBuildError: data.error
|
|
151
211
|
});
|
|
152
|
-
fetchConsoleLogs();
|
|
153
212
|
break;
|
|
154
213
|
case 'status':
|
|
155
214
|
// Initial status on connection
|
|
@@ -160,10 +219,112 @@ const App = () => {
|
|
|
160
219
|
lastBuildError: data.lastBuildError
|
|
161
220
|
});
|
|
162
221
|
break;
|
|
222
|
+
case 'log':
|
|
223
|
+
// Append new log, keep last 500
|
|
224
|
+
setLogs(prev => [...prev.slice(-499), data.entry]);
|
|
225
|
+
break;
|
|
226
|
+
case 'initialLogs':
|
|
227
|
+
setLogs(data.logs || []);
|
|
228
|
+
// Handle app change detection (only compare app names, not paths)
|
|
229
|
+
if (data.app && data.app.name) {
|
|
230
|
+
if (!initialAppInfoRef.current) {
|
|
231
|
+
initialAppInfoRef.current = { name: data.app.name, path: data.app.path };
|
|
232
|
+
}
|
|
233
|
+
else if (initialAppInfoRef.current.name !== data.app.name) {
|
|
234
|
+
setAppChanged({ oldApp: initialAppInfoRef.current.name, newApp: data.app.name });
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
break;
|
|
238
|
+
case 'logsCleared':
|
|
239
|
+
setLogs([]);
|
|
240
|
+
break;
|
|
241
|
+
case 'serverShutdown':
|
|
242
|
+
// Server is shutting down - immediately show disconnect overlay
|
|
243
|
+
eventSource.close();
|
|
244
|
+
eventSourceRef.current = null;
|
|
245
|
+
setPermanentlyDisconnected(true);
|
|
246
|
+
// Update tab title to indicate disconnection
|
|
247
|
+
document.title = '[DISCONNECTED] ' + document.title;
|
|
248
|
+
break;
|
|
249
|
+
case 'connectionEvicted':
|
|
250
|
+
// Connection evicted due to limit - show disconnect overlay
|
|
251
|
+
eventSource.close();
|
|
252
|
+
eventSourceRef.current = null;
|
|
253
|
+
setPermanentlyDisconnected(true);
|
|
254
|
+
// Update tab title to indicate disconnection
|
|
255
|
+
document.title = '[DISCONNECTED] ' + document.title;
|
|
256
|
+
break;
|
|
257
|
+
case 'sourceDataChanged':
|
|
258
|
+
// Source data was emitted — increment version to trigger re-fetch in panel
|
|
259
|
+
setSourceDataVersion(v => v + 1);
|
|
260
|
+
setSourceDataTotalEmitted(data.totalEmitted ?? 0);
|
|
261
|
+
break;
|
|
262
|
+
case 'notificationChanged':
|
|
263
|
+
// Notification was created — increment version to trigger re-fetch in panel
|
|
264
|
+
setNotificationVersion(v => v + 1);
|
|
265
|
+
fetchNotificationCount();
|
|
266
|
+
break;
|
|
267
|
+
case 'envChanged':
|
|
268
|
+
setEnvVersion(v => v + 1);
|
|
269
|
+
break;
|
|
270
|
+
case 'installSuccess':
|
|
271
|
+
// App was installed via API - update state and increment version
|
|
272
|
+
console.log('SSE: App installed via API');
|
|
273
|
+
setAppInstalled(true);
|
|
274
|
+
setInstallVersion(v => v + 1); // Increment to force UI refresh
|
|
275
|
+
setConnected(true);
|
|
276
|
+
break;
|
|
277
|
+
case 'uninstallSuccess':
|
|
278
|
+
// App was uninstalled via API - update state
|
|
279
|
+
console.log('SSE: App uninstalled via API');
|
|
280
|
+
setAppInstalled(false);
|
|
281
|
+
setConnected(false);
|
|
282
|
+
break;
|
|
283
|
+
case 'deployStart':
|
|
284
|
+
setDeployStatus({ deployInProgress: true, lastDeploySuccess: null });
|
|
285
|
+
// Add a separator between deploy runs instead of clearing logs
|
|
286
|
+
setDeployLogs(prev => prev.length > 0
|
|
287
|
+
? [...prev, '───────────────────────────────────────']
|
|
288
|
+
: prev);
|
|
289
|
+
setDeployVersion(v => v + 1);
|
|
290
|
+
break;
|
|
291
|
+
case 'deployLog':
|
|
292
|
+
setDeployLogs(prev => [...prev, data.line]);
|
|
293
|
+
setDeployVersion(v => v + 1);
|
|
294
|
+
break;
|
|
295
|
+
case 'deploySuccess':
|
|
296
|
+
setDeployStatus({ deployInProgress: false, lastDeploySuccess: true });
|
|
297
|
+
setDeployVersion(v => v + 1);
|
|
298
|
+
// Refresh app info to update version display in nav
|
|
299
|
+
fetchAppInfo();
|
|
300
|
+
break;
|
|
301
|
+
case 'deployError':
|
|
302
|
+
setDeployStatus({ deployInProgress: false, lastDeploySuccess: false });
|
|
303
|
+
if (data.error) {
|
|
304
|
+
setDeployLogs(prev => [...prev, `Error: ${data.error}`]);
|
|
305
|
+
}
|
|
306
|
+
setDeployVersion(v => v + 1);
|
|
307
|
+
break;
|
|
308
|
+
case 'deployStatus':
|
|
309
|
+
// Initial deploy status on connection
|
|
310
|
+
setDeployStatus({
|
|
311
|
+
deployInProgress: data.deployInProgress || false,
|
|
312
|
+
lastDeploySuccess: data.lastDeploySuccess ?? null
|
|
313
|
+
});
|
|
314
|
+
break;
|
|
163
315
|
}
|
|
164
316
|
};
|
|
165
317
|
eventSource.onerror = () => {
|
|
166
318
|
setConnected(false);
|
|
319
|
+
// Start 30-second timer if not already started
|
|
320
|
+
if (!disconnectTimerRef.current && !permanentlyDisconnected) {
|
|
321
|
+
disconnectTimerRef.current = setTimeout(() => {
|
|
322
|
+
// Permanently disconnect - close EventSource and show message
|
|
323
|
+
eventSource.close();
|
|
324
|
+
eventSourceRef.current = null;
|
|
325
|
+
setPermanentlyDisconnected(true);
|
|
326
|
+
}, 30000);
|
|
327
|
+
}
|
|
167
328
|
// Fallback to polling if SSE fails
|
|
168
329
|
if (!pollingIntervals.current.status) {
|
|
169
330
|
pollingIntervals.current.status = setInterval(fetchStatus, 3000);
|
|
@@ -171,25 +332,43 @@ const App = () => {
|
|
|
171
332
|
};
|
|
172
333
|
eventSource.onopen = () => {
|
|
173
334
|
setConnected(true);
|
|
335
|
+
// Clear disconnect timer if we reconnected in time
|
|
336
|
+
if (disconnectTimerRef.current) {
|
|
337
|
+
clearTimeout(disconnectTimerRef.current);
|
|
338
|
+
disconnectTimerRef.current = null;
|
|
339
|
+
}
|
|
340
|
+
// Check if app has changed (server restarted with different app)
|
|
341
|
+
// Only check if we had a previous app loaded
|
|
342
|
+
if (initialAppInfoRef.current) {
|
|
343
|
+
fetchAppInfo(true);
|
|
344
|
+
}
|
|
174
345
|
// Stop fallback polling if it was started
|
|
175
346
|
if (pollingIntervals.current.status) {
|
|
176
347
|
clearInterval(pollingIntervals.current.status);
|
|
177
348
|
pollingIntervals.current.status = null;
|
|
178
349
|
}
|
|
179
350
|
};
|
|
180
|
-
//
|
|
181
|
-
|
|
351
|
+
// Close SSE on page unload/refresh to prevent connection accumulation
|
|
352
|
+
// This is critical for Firefox which has a strict 6-connection limit per domain
|
|
353
|
+
const handleBeforeUnload = () => {
|
|
354
|
+
if (eventSourceRef.current) {
|
|
355
|
+
eventSourceRef.current.close();
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
window.addEventListener('beforeunload', handleBeforeUnload);
|
|
182
359
|
// Cleanup
|
|
183
360
|
return () => {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
clearInterval(pollingIntervals.current.logs);
|
|
361
|
+
if (disconnectTimerRef.current) {
|
|
362
|
+
clearTimeout(disconnectTimerRef.current);
|
|
187
363
|
}
|
|
364
|
+
eventSource.close();
|
|
365
|
+
eventSourceRef.current = null;
|
|
366
|
+
window.removeEventListener('beforeunload', handleBeforeUnload);
|
|
188
367
|
if (pollingIntervals.current.status) {
|
|
189
368
|
clearInterval(pollingIntervals.current.status);
|
|
190
369
|
}
|
|
191
370
|
};
|
|
192
|
-
}, []);
|
|
371
|
+
}, [permanentlyDisconnected]);
|
|
193
372
|
// Listen for events from the iframe
|
|
194
373
|
(0, react_1.useEffect)(() => {
|
|
195
374
|
const deserializeResizerMessage = (data) => {
|
|
@@ -223,11 +402,11 @@ const App = () => {
|
|
|
223
402
|
const message = deserializeResizerMessage(event.data);
|
|
224
403
|
// Handle getTracker message
|
|
225
404
|
if (message.method === "getTracker") {
|
|
226
|
-
const
|
|
405
|
+
const response = serializeResizerMessage({
|
|
227
406
|
method: "setTracker",
|
|
228
407
|
params: "local-development-tracker-id",
|
|
229
408
|
});
|
|
230
|
-
settingsIframeRef.current?.contentWindow?.postMessage(
|
|
409
|
+
settingsIframeRef.current?.contentWindow?.postMessage(response, event.origin);
|
|
231
410
|
console.log("getTracker sent");
|
|
232
411
|
}
|
|
233
412
|
// Handle installation lifecycle events
|
|
@@ -238,6 +417,7 @@ const App = () => {
|
|
|
238
417
|
case "install_success":
|
|
239
418
|
console.log("Installation successful, updating app state");
|
|
240
419
|
setAppInstalled(true);
|
|
420
|
+
setInstallVersion(v => v + 1); // Increment to force UI refresh
|
|
241
421
|
setConnected(true);
|
|
242
422
|
break;
|
|
243
423
|
case "uninstall_success":
|
|
@@ -269,11 +449,25 @@ const App = () => {
|
|
|
269
449
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
270
450
|
}, []);
|
|
271
451
|
// Fetch app info from the API
|
|
272
|
-
const fetchAppInfo = async () => {
|
|
452
|
+
const fetchAppInfo = async (checkForChanges = false) => {
|
|
273
453
|
try {
|
|
274
454
|
const response = await fetch("/devserver/api/app");
|
|
275
455
|
if (response.ok) {
|
|
276
456
|
const data = await response.json();
|
|
457
|
+
// Store initial app info on first successful fetch
|
|
458
|
+
if (!initialAppInfoRef.current && data.name) {
|
|
459
|
+
initialAppInfoRef.current = { name: data.name, path: data.path };
|
|
460
|
+
}
|
|
461
|
+
// Check if app has changed (different app being served) - only compare names
|
|
462
|
+
if (checkForChanges && initialAppInfoRef.current && data.name) {
|
|
463
|
+
if (initialAppInfoRef.current.name !== data.name) {
|
|
464
|
+
setAppChanged({
|
|
465
|
+
oldApp: initialAppInfoRef.current.name,
|
|
466
|
+
newApp: data.name
|
|
467
|
+
});
|
|
468
|
+
return; // Don't update appInfo - show the change notification instead
|
|
469
|
+
}
|
|
470
|
+
}
|
|
277
471
|
setAppInfo(data);
|
|
278
472
|
setConnected(true);
|
|
279
473
|
}
|
|
@@ -307,34 +501,11 @@ const App = () => {
|
|
|
307
501
|
setConnected(false);
|
|
308
502
|
}
|
|
309
503
|
};
|
|
310
|
-
// Fetch console logs from the API
|
|
311
|
-
const fetchConsoleLogs = async () => {
|
|
312
|
-
try {
|
|
313
|
-
const response = await fetch("/devserver/api/console/logs?limit=50");
|
|
314
|
-
if (response.ok) {
|
|
315
|
-
const data = await response.json();
|
|
316
|
-
if (data.logs && data.logs.length > 0) {
|
|
317
|
-
setLogs(data.logs); // Pass raw LogEntry[] directly
|
|
318
|
-
}
|
|
319
|
-
else {
|
|
320
|
-
setLogs([]);
|
|
321
|
-
}
|
|
322
|
-
setConnected(true);
|
|
323
|
-
}
|
|
324
|
-
else {
|
|
325
|
-
setConnected(false);
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
catch (error) {
|
|
329
|
-
console.error("Error fetching console logs:", error);
|
|
330
|
-
setConnected(false);
|
|
331
|
-
}
|
|
332
|
-
};
|
|
333
504
|
// Clear console logs
|
|
334
505
|
const clearConsoleLogs = async () => {
|
|
335
506
|
try {
|
|
336
507
|
await fetch("/devserver/api/console/logs", { method: "DELETE" });
|
|
337
|
-
|
|
508
|
+
// SSE logsCleared event will update the UI
|
|
338
509
|
}
|
|
339
510
|
catch (error) {
|
|
340
511
|
console.error("Error clearing logs:", error);
|
|
@@ -392,9 +563,8 @@ const App = () => {
|
|
|
392
563
|
},
|
|
393
564
|
});
|
|
394
565
|
if (response.ok) {
|
|
395
|
-
// Immediately fetch new status
|
|
566
|
+
// Immediately fetch new status (logs come via SSE)
|
|
396
567
|
fetchStatus();
|
|
397
|
-
fetchConsoleLogs();
|
|
398
568
|
}
|
|
399
569
|
else {
|
|
400
570
|
console.error("Failed to trigger build");
|
|
@@ -404,14 +574,100 @@ const App = () => {
|
|
|
404
574
|
console.error("Error triggering build:", error);
|
|
405
575
|
}
|
|
406
576
|
};
|
|
407
|
-
|
|
577
|
+
// Compute deploy button CSS modifier class based on current deploy status
|
|
578
|
+
const getDeployStatusClass = () => {
|
|
579
|
+
if (deployStatus.deployInProgress)
|
|
580
|
+
return 'deploying';
|
|
581
|
+
if (deployStatus.lastDeploySuccess === true)
|
|
582
|
+
return 'deploy-success';
|
|
583
|
+
if (deployStatus.lastDeploySuccess === false)
|
|
584
|
+
return 'deploy-error';
|
|
585
|
+
return '';
|
|
586
|
+
};
|
|
587
|
+
// Append a deploy log message and increment the version counter
|
|
588
|
+
const appendDeployLog = (message) => {
|
|
589
|
+
setDeployLogs(prev => [...prev, message]);
|
|
590
|
+
setDeployVersion(v => v + 1);
|
|
591
|
+
};
|
|
592
|
+
// Trigger a deploy
|
|
593
|
+
const triggerDeploy = async () => {
|
|
594
|
+
try {
|
|
595
|
+
// First, resolve the version from Rivendell
|
|
596
|
+
const resolveResponse = await fetch("/devserver/api/deploy/resolve-version", {
|
|
597
|
+
method: "POST",
|
|
598
|
+
headers: { "Content-Type": "application/json" },
|
|
599
|
+
});
|
|
600
|
+
if (!resolveResponse.ok) {
|
|
601
|
+
const errorData = await resolveResponse.json().catch(() => ({}));
|
|
602
|
+
appendDeployLog(`Error resolving version: ${errorData.error || 'Unknown error'}`);
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
const versionData = await resolveResponse.json();
|
|
606
|
+
if (versionData.searchError) {
|
|
607
|
+
appendDeployLog(`Warning: Rivendell search failed (${versionData.searchError}), bumping version locally`);
|
|
608
|
+
}
|
|
609
|
+
if (versionData.isDevVersion && (0, DeployModal_1.shouldSkipDevConfirmation)()) {
|
|
610
|
+
// Dev version with "do not show again" enabled: deploy immediately
|
|
611
|
+
startDeploy(versionData.suggestedVersion);
|
|
612
|
+
}
|
|
613
|
+
else {
|
|
614
|
+
// Show confirmation modal
|
|
615
|
+
setDeployModalData({
|
|
616
|
+
currentVersion: versionData.currentVersion,
|
|
617
|
+
suggestedVersion: versionData.suggestedVersion,
|
|
618
|
+
isDevVersion: versionData.isDevVersion
|
|
619
|
+
});
|
|
620
|
+
setShowDeployModal(true);
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
catch (error) {
|
|
624
|
+
console.error("Error triggering deploy:", error);
|
|
625
|
+
appendDeployLog(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
626
|
+
}
|
|
627
|
+
};
|
|
628
|
+
// Start the deploy with a specific version
|
|
629
|
+
const startDeploy = async (version) => {
|
|
630
|
+
setShowDeployModal(false);
|
|
631
|
+
try {
|
|
632
|
+
const response = await fetch("/devserver/api/deploy/start", {
|
|
633
|
+
method: "POST",
|
|
634
|
+
headers: { "Content-Type": "application/json" },
|
|
635
|
+
body: JSON.stringify({ version }),
|
|
636
|
+
});
|
|
637
|
+
if (!response.ok) {
|
|
638
|
+
const errorData = await response.json().catch(() => ({}));
|
|
639
|
+
appendDeployLog(`Error starting deploy: ${errorData.error || 'Unknown error'}`);
|
|
640
|
+
}
|
|
641
|
+
// Success: SSE events will handle state updates
|
|
642
|
+
}
|
|
643
|
+
catch (error) {
|
|
644
|
+
console.error("Error starting deploy:", error);
|
|
645
|
+
appendDeployLog(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
646
|
+
}
|
|
647
|
+
};
|
|
648
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: "app postman-layout", children: [(0, jsx_runtime_1.jsxs)("header", { className: "top-nav", children: [(0, jsx_runtime_1.jsx)("div", { className: "nav-left", children: (0, jsx_runtime_1.jsx)("div", { className: "app-title", children: (0, jsx_runtime_1.jsx)("h1", { children: "OCP Local Environment" }) }) }), appInfo && ((0, jsx_runtime_1.jsx)("div", { className: "nav-center", children: (0, jsx_runtime_1.jsxs)("div", { className: "app-info-nav", children: [(0, jsx_runtime_1.jsx)("span", { className: "app-name", children: appInfo.displayName || appInfo.name }), (0, jsx_runtime_1.jsxs)("span", { className: "app-version", children: ["v", appInfo.version] })] }) })), (0, jsx_runtime_1.jsxs)("div", { className: "nav-right", children: [(0, jsx_runtime_1.jsxs)("button", { className: `deploy-btn ${getDeployStatusClass()}`, onClick: triggerDeploy, disabled: deployStatus.deployInProgress || !!buildStatus?.buildInProgress, title: "Deploy app version to OCP", children: [(0, jsx_runtime_1.jsx)("span", { className: "deploy-status-dot" }), deployStatus.deployInProgress ? "Deploying..." :
|
|
649
|
+
deployStatus.lastDeploySuccess === true ? "Deployed" : "Deploy"] }), (0, jsx_runtime_1.jsxs)("button", { className: `rebuild-btn ${buildStatus?.buildInProgress ? 'building' :
|
|
408
650
|
buildStatus?.lastBuildSuccess === true ? 'success' :
|
|
409
|
-
buildStatus?.lastBuildSuccess === false ? 'error' : ''}`, onClick: triggerBuild, disabled: buildStatus?.buildInProgress, children: [(0, jsx_runtime_1.jsx)("span", { className: "rebuild-status-dot" }), buildStatus?.buildInProgress ? "Building..." : "Rebuild"] }),
|
|
651
|
+
buildStatus?.lastBuildSuccess === false ? 'error' : ''}`, onClick: triggerBuild, disabled: buildStatus?.buildInProgress, children: [(0, jsx_runtime_1.jsx)("span", { className: "rebuild-status-dot" }), buildStatus?.buildInProgress ? "Building..." : "Rebuild"] }), config.hasSchemaFiles && ((0, jsx_runtime_1.jsxs)("div", { className: "odp-status-badge", children: [(0, jsx_runtime_1.jsx)("span", { className: `odp-status-dot ${config.odpKeyConfigured ? 'configured' : 'not-configured'}` }), "ODP/OCP", (0, jsx_runtime_1.jsx)("span", { className: "odp-tooltip", children: config.odpKeyConfigured
|
|
652
|
+
? 'ODP API Key is configured'
|
|
653
|
+
: 'ODP API Key is not configured — set it in Tool Settings' })] })), (0, jsx_runtime_1.jsx)("div", { className: "nav-separator-vertical" }), (0, jsx_runtime_1.jsxs)("a", { href: "https://github.com/optimizely/ocp-developer-feedback/issues/new/choose", target: "_blank", rel: "noopener noreferrer", className: "feedback-btn", title: "Provide Feedback", children: [(0, jsx_runtime_1.jsx)(axiom_icons_1.IconPenField, { size: "14" }), "Feedback"] }), (0, jsx_runtime_1.jsxs)("a", { href: "https://docs.developers.optimizely.com/optimizely-connect-platform/docs/local-testing", target: "_blank", rel: "noopener noreferrer", className: "docs-btn", title: "Documentation", children: [(0, jsx_runtime_1.jsx)(axiom_icons_1.IconBookOpen, { size: "14" }), " Docs"] })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "main-layout", children: [(0, jsx_runtime_1.jsx)("aside", { className: "sidebar", children: (0, jsx_runtime_1.jsxs)("nav", { className: "sidebar-nav", children: [(0, jsx_runtime_1.jsxs)("button", { className: `nav-item ${activeView === "settings" ? "active" : ""}`, onClick: () => navigatePreservingConsole('/settings'), children: [(0, jsx_runtime_1.jsx)(axiom_icons_1.IconGear, { size: "2xs" }), (0, jsx_runtime_1.jsx)("span", { className: "nav-label", children: "App Settings" })] }), appInfo && appInfo.functions && appInfo.functions.length > 0 && ((0, jsx_runtime_1.jsxs)("button", { className: `nav-item ${activeView === "functions" ? "active" : ""}`, onClick: () => navigatePreservingConsole('/functions'), children: [(0, jsx_runtime_1.jsx)(axiom_icons_1.IconBolt, { size: "2xs" }), (0, jsx_runtime_1.jsx)("span", { className: "nav-label", children: "Functions" })] })), appInfo && appInfo.jobs && appInfo.jobs.length > 0 && ((0, jsx_runtime_1.jsxs)("button", { className: `nav-item ${activeView === "jobs" ? "active" : ""}`, onClick: () => navigatePreservingConsole('/jobs'), children: [(0, jsx_runtime_1.jsx)(axiom_icons_1.IconCubes, { size: "2xs" }), (0, jsx_runtime_1.jsx)("span", { className: "nav-label", children: "Jobs" })] })), appInfo && appInfo.destinations && appInfo.destinations.length > 0 && ((0, jsx_runtime_1.jsxs)("button", { className: `nav-item ${activeView === "destinations" ? "active" : ""}`, onClick: () => navigatePreservingConsole('/destinations'), children: [(0, jsx_runtime_1.jsx)(axiom_icons_1.IconUpload, { size: "2xs" }), (0, jsx_runtime_1.jsx)("span", { className: "nav-label", children: "Destinations" })] })), appInfo && appInfo.sources && appInfo.sources.length > 0 && ((0, jsx_runtime_1.jsxs)("button", { className: `nav-item ${activeView === "sources" ? "active" : ""}`, onClick: () => navigatePreservingConsole('/sources'), children: [(0, jsx_runtime_1.jsx)(axiom_icons_1.IconDownload, { size: "2xs" }), (0, jsx_runtime_1.jsx)("span", { className: "nav-label", children: "Sources" })] })), appInfo && appInfo.opalTools && appInfo.opalTools.length > 0 && ((0, jsx_runtime_1.jsxs)("button", { className: `nav-item ${activeView === "opal-tools" ? "active" : ""}`, onClick: () => navigatePreservingConsole('/opal-tools'), children: [(0, jsx_runtime_1.jsx)(axiom_icons_1.IconScrewdriverWrench, { size: "2xs" }), (0, jsx_runtime_1.jsx)("span", { className: "nav-label", children: "Opal Tools" })] })), config.hasSchemaFiles && ((0, jsx_runtime_1.jsxs)("button", { className: `nav-item ${activeView === "odp-schema" ? "active" : ""}`, onClick: () => navigatePreservingConsole('/odp-schema'), children: [(0, jsx_runtime_1.jsx)(axiom_icons_1.IconMemoPad, { size: "2xs" }), (0, jsx_runtime_1.jsx)("span", { className: "nav-label", children: "ODP Schema" })] })), (0, jsx_runtime_1.jsx)("div", { className: "nav-separator", style: { height: '1px', background: '#3e3e42', margin: '4px 0' } }), (0, jsx_runtime_1.jsxs)("button", { className: `nav-item ${activeView === "tool-settings" ? "active" : ""}`, onClick: () => navigatePreservingConsole('/tool-settings'), children: [(0, jsx_runtime_1.jsx)(axiom_icons_1.IconGear, { size: "2xs" }), (0, jsx_runtime_1.jsx)("span", { className: "nav-label", children: "Tool Settings" })] })] }) }), (0, jsx_runtime_1.jsxs)("main", { className: "content-area", children: [activeView !== "jobs" && activeView !== "functions" && activeView !== "opal-tools" && activeView !== "destinations" && activeView !== "tool-settings" && activeView !== "odp-schema" && ((0, jsx_runtime_1.jsxs)("div", { className: "content-header", children: [(0, jsx_runtime_1.jsxs)("h2", { children: [activeView === "settings" && "App Settings", activeView === "sources" && "Sources"] }), appInfo && !appInfo.isValid && ((0, jsx_runtime_1.jsxs)("div", { className: "validation-errors-banner", children: [(0, jsx_runtime_1.jsx)("span", { className: "error-icon", children: "\u26A0\uFE0F" }), (0, jsx_runtime_1.jsx)("span", { children: "App has validation errors" })] }))] })), (0, jsx_runtime_1.jsx)("div", { className: "content-body", children: (0, jsx_runtime_1.jsxs)(react_router_dom_1.Routes, { children: [(0, jsx_runtime_1.jsx)(react_router_dom_1.Route, { path: "/", element: (0, jsx_runtime_1.jsx)(react_router_dom_1.Navigate, { to: "/settings", replace: true }) }), (0, jsx_runtime_1.jsx)(react_router_dom_1.Route, { path: "/settings", element: (0, jsx_runtime_1.jsxs)("div", { className: "settings-view", children: [appInfo && !appInfo.isValid && appInfo.errors && appInfo.errors.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "validation-errors", children: [(0, jsx_runtime_1.jsx)("h4", { children: "Validation Errors:" }), (0, jsx_runtime_1.jsx)("ul", { children: appInfo.errors.map((err, idx) => ((0, jsx_runtime_1.jsx)("li", { children: err }, idx))) })] })), buildStatus?.buildInProgress || (buildStatus?.lastBuildSuccess === null && buildStatus?.lastBuildTimestamp === null) ? ((0, jsx_runtime_1.jsx)("div", { className: "settings-loading-container", children: (0, jsx_runtime_1.jsxs)("div", { className: "placeholder-content", children: [(0, jsx_runtime_1.jsx)("h3", { children: "Building App..." }), (0, jsx_runtime_1.jsx)("p", { children: "Please wait while the app is being built." }), (0, jsx_runtime_1.jsx)("div", { className: "spinner" })] }) })) : buildStatus?.lastBuildSuccess === false ? ((0, jsx_runtime_1.jsx)("div", { className: "settings-loading-container", children: (0, jsx_runtime_1.jsxs)("div", { className: "placeholder-content", children: [(0, jsx_runtime_1.jsx)("h3", { children: "Build Failed" }), (0, jsx_runtime_1.jsx)("p", { children: "The app failed to build. Please check the console for errors." }), buildStatus.lastBuildError && ((0, jsx_runtime_1.jsx)("pre", { className: "error-details", children: buildStatus.lastBuildError }))] }) })) : ((0, jsx_runtime_1.jsx)("div", { className: "settings-iframe-container", children: (0, jsx_runtime_1.jsx)("iframe", { id: "app_directory_frame", style: {
|
|
410
654
|
width: "100%",
|
|
411
655
|
height: "100%",
|
|
412
656
|
border: "none",
|
|
413
657
|
overflow: "hidden",
|
|
414
|
-
}, ref: setIframeRef, src: `${window.location.origin}/app/${appInfo?.name || "unknown"}`, onLoad: handleIframeLoad }) }))] }) }), (0, jsx_runtime_1.jsx)(react_router_dom_1.Route, { path: "/functions/*", element: !appInfo ? ((0, jsx_runtime_1.jsx)("div", { className: "functions-view", children: (0, jsx_runtime_1.jsx)("div", { className: "placeholder-content", children: (0, jsx_runtime_1.jsx)("p", { children: "Loading..." }) }) })) : appInfo.functions && appInfo.functions.length > 0 ? ((0, jsx_runtime_1.jsx)(FunctionsView_1.default, { appInstalled: appInstalled, buildStatus: buildStatus })) : ((0, jsx_runtime_1.jsx)(react_router_dom_1.Navigate, { to: "/settings", replace: true })) }), (0, jsx_runtime_1.jsx)(react_router_dom_1.Route, { path: "/jobs/*", element: !appInfo ? ((0, jsx_runtime_1.jsx)("div", { className: "jobs-view", children: (0, jsx_runtime_1.jsx)("div", { className: "placeholder-content", children: (0, jsx_runtime_1.jsx)("p", { children: "Loading..." }) }) })) : appInfo.jobs && appInfo.jobs.length > 0 ? ((0, jsx_runtime_1.jsx)(JobsView_1.default, { appInstalled: appInstalled, buildStatus: buildStatus })) : ((0, jsx_runtime_1.jsx)(react_router_dom_1.Navigate, { to: "/settings", replace: true })) }), (0, jsx_runtime_1.jsx)(react_router_dom_1.Route, { path: "/destinations/*", element: !appInfo ? ((0, jsx_runtime_1.jsx)("div", { className: "destinations-view", children: (0, jsx_runtime_1.jsx)("div", { className: "placeholder-content", children: (0, jsx_runtime_1.jsx)("p", { children: "Loading..." }) }) })) : appInfo.destinations && appInfo.destinations.length > 0 ? ((0, jsx_runtime_1.jsx)(DestinationsView_1.DestinationsView, { apiBaseUrl: "/devserver/api", appInstalled: appInstalled, buildStatus: buildStatus })) : ((0, jsx_runtime_1.jsx)(react_router_dom_1.Navigate, { to: "/settings", replace: true })) }), (0, jsx_runtime_1.jsx)(react_router_dom_1.Route, { path: "/sources/*", element: !appInfo ? ((0, jsx_runtime_1.jsx)("div", { className: "sources-view", children: (0, jsx_runtime_1.jsx)("div", { className: "placeholder-content", children: (0, jsx_runtime_1.jsx)("p", { children: "Loading..." }) }) })) : appInfo.sources && appInfo.sources.length > 0 ? ((0, jsx_runtime_1.jsx)(SourcesView_1.SourcesView, { apiBaseUrl: "/devserver/api", appInstalled: appInstalled, buildStatus: buildStatus })) : ((0, jsx_runtime_1.jsx)(react_router_dom_1.Navigate, { to: "/settings", replace: true })) }), (0, jsx_runtime_1.jsx)(react_router_dom_1.Route, { path: "
|
|
658
|
+
}, ref: setIframeRef, src: `${window.location.origin}/app/${appInfo?.name || "unknown"}`, onLoad: handleIframeLoad }) }))] }) }), (0, jsx_runtime_1.jsx)(react_router_dom_1.Route, { path: "/functions/*", element: !appInfo ? ((0, jsx_runtime_1.jsx)("div", { className: "functions-view", children: (0, jsx_runtime_1.jsx)("div", { className: "placeholder-content", children: (0, jsx_runtime_1.jsx)("p", { children: "Loading..." }) }) })) : appInfo.functions && appInfo.functions.length > 0 ? ((0, jsx_runtime_1.jsx)(FunctionsView_1.default, { appInstalled: appInstalled, buildStatus: buildStatus, installVersion: installVersion })) : ((0, jsx_runtime_1.jsx)(react_router_dom_1.Navigate, { to: "/settings", replace: true })) }), (0, jsx_runtime_1.jsx)(react_router_dom_1.Route, { path: "/jobs/*", element: !appInfo ? ((0, jsx_runtime_1.jsx)("div", { className: "jobs-view", children: (0, jsx_runtime_1.jsx)("div", { className: "placeholder-content", children: (0, jsx_runtime_1.jsx)("p", { children: "Loading..." }) }) })) : appInfo.jobs && appInfo.jobs.length > 0 ? ((0, jsx_runtime_1.jsx)(JobsView_1.default, { appInstalled: appInstalled, buildStatus: buildStatus })) : ((0, jsx_runtime_1.jsx)(react_router_dom_1.Navigate, { to: "/settings", replace: true })) }), (0, jsx_runtime_1.jsx)(react_router_dom_1.Route, { path: "/destinations/*", element: !appInfo ? ((0, jsx_runtime_1.jsx)("div", { className: "destinations-view", children: (0, jsx_runtime_1.jsx)("div", { className: "placeholder-content", children: (0, jsx_runtime_1.jsx)("p", { children: "Loading..." }) }) })) : appInfo.destinations && appInfo.destinations.length > 0 ? ((0, jsx_runtime_1.jsx)(DestinationsView_1.DestinationsView, { apiBaseUrl: "/devserver/api", appInstalled: appInstalled, buildStatus: buildStatus })) : ((0, jsx_runtime_1.jsx)(react_router_dom_1.Navigate, { to: "/settings", replace: true })) }), (0, jsx_runtime_1.jsx)(react_router_dom_1.Route, { path: "/sources/*", element: !appInfo ? ((0, jsx_runtime_1.jsx)("div", { className: "sources-view", children: (0, jsx_runtime_1.jsx)("div", { className: "placeholder-content", children: (0, jsx_runtime_1.jsx)("p", { children: "Loading..." }) }) })) : appInfo.sources && appInfo.sources.length > 0 ? ((0, jsx_runtime_1.jsx)(SourcesView_1.SourcesView, { apiBaseUrl: "/devserver/api", appInstalled: appInstalled, buildStatus: buildStatus })) : ((0, jsx_runtime_1.jsx)(react_router_dom_1.Navigate, { to: "/settings", replace: true })) }), (0, jsx_runtime_1.jsx)(react_router_dom_1.Route, { path: "/opal-tools/*", element: !appInfo ? ((0, jsx_runtime_1.jsx)("div", { className: "functions-view", children: (0, jsx_runtime_1.jsx)("div", { className: "placeholder-content", children: (0, jsx_runtime_1.jsx)("p", { children: "Loading..." }) }) })) : appInfo.opalTools && appInfo.opalTools.length > 0 ? ((0, jsx_runtime_1.jsx)(OpalToolsView_1.default, { appInstalled: appInstalled, buildStatus: buildStatus, installVersion: installVersion })) : ((0, jsx_runtime_1.jsx)(react_router_dom_1.Navigate, { to: "/settings", replace: true })) }), (0, jsx_runtime_1.jsx)(react_router_dom_1.Route, { path: "/odp-schema", element: config.hasSchemaFiles ? ((0, jsx_runtime_1.jsx)(OdpSchemaView_1.default, {})) : ((0, jsx_runtime_1.jsx)(react_router_dom_1.Navigate, { to: "/settings", replace: true })) }), (0, jsx_runtime_1.jsx)(react_router_dom_1.Route, { path: "/tool-settings", element: (0, jsx_runtime_1.jsx)(ToolSettingsView_1.default, { odpApiKey: config.odpApiKey || '', onSave: async (odpApiKey) => {
|
|
659
|
+
try {
|
|
660
|
+
await fetch('/devserver/api/config/odp', {
|
|
661
|
+
method: 'POST',
|
|
662
|
+
headers: { 'Content-Type': 'application/json' },
|
|
663
|
+
body: JSON.stringify({ odpApiKey }),
|
|
664
|
+
});
|
|
665
|
+
fetchConfig();
|
|
666
|
+
}
|
|
667
|
+
catch (error) {
|
|
668
|
+
console.error('Error saving ODP config:', error);
|
|
669
|
+
}
|
|
670
|
+
} }) }), (0, jsx_runtime_1.jsx)(react_router_dom_1.Route, { path: "*", element: (0, jsx_runtime_1.jsxs)("div", { className: "not-found-view", style: {
|
|
415
671
|
display: 'flex',
|
|
416
672
|
flexDirection: 'column',
|
|
417
673
|
alignItems: 'center',
|
|
@@ -426,7 +682,7 @@ const App = () => {
|
|
|
426
682
|
color: 'white',
|
|
427
683
|
border: 'none',
|
|
428
684
|
borderRadius: '4px'
|
|
429
|
-
}, children: "Go to Settings" })] }) })] }) })] })] }), (0, jsx_runtime_1.jsx)(TabbedConsole_1.default, { logs: logs, onClearLogs: clearConsoleLogs, storeTimestamps: storeTimestamps, onRefreshStores: fetchStatus, notificationCount: notificationCount })] }));
|
|
685
|
+
}, children: "Go to Settings" })] }) })] }) })] })] }), (0, jsx_runtime_1.jsx)(TabbedConsole_1.default, { logs: logs, onClearLogs: clearConsoleLogs, storeTimestamps: storeTimestamps, onRefreshStores: fetchStatus, notificationCount: notificationCount, hasSources: !!(appInfo?.sources && appInfo.sources.length > 0), sourceDataVersion: sourceDataVersion, sourceDataTotalEmitted: sourceDataTotalEmitted, notificationVersion: notificationVersion, envVersion: envVersion, deployLogs: deployLogs, deployVersion: deployVersion, deployStatus: deployStatus }), (0, jsx_runtime_1.jsx)(DeployModal_1.DeployModal, { isOpen: showDeployModal, onClose: () => setShowDeployModal(false), currentVersion: deployModalData?.currentVersion || '', suggestedVersion: deployModalData?.suggestedVersion || '', isDevVersion: deployModalData?.isDevVersion || false, onDeploy: startDeploy }), permanentlyDisconnected && ((0, jsx_runtime_1.jsx)("div", { className: "disconnect-overlay", children: (0, jsx_runtime_1.jsxs)("div", { className: "disconnect-message", children: [(0, jsx_runtime_1.jsx)("h2", { children: "Server Disconnected" }), (0, jsx_runtime_1.jsx)("p", { children: "The development server has been stopped or is unreachable." }), (0, jsx_runtime_1.jsx)("button", { onClick: () => window.location.reload(), children: "Reconnect" })] }) })), appChanged && ((0, jsx_runtime_1.jsx)("div", { className: "disconnect-overlay", children: (0, jsx_runtime_1.jsxs)("div", { className: "disconnect-message app-changed", children: [(0, jsx_runtime_1.jsx)("h2", { children: "Different App Detected" }), (0, jsx_runtime_1.jsxs)("p", { children: ["The server is now running a different app.", (0, jsx_runtime_1.jsx)("br", {}), (0, jsx_runtime_1.jsxs)("span", { className: "app-change-details", children: [(0, jsx_runtime_1.jsx)("strong", { children: appChanged.oldApp }), " \u2192 ", (0, jsx_runtime_1.jsx)("strong", { children: appChanged.newApp })] })] }), (0, jsx_runtime_1.jsx)("button", { onClick: () => window.location.reload(), children: "Load New App" })] }) }))] }));
|
|
430
686
|
};
|
|
431
687
|
exports.default = App;
|
|
432
688
|
//# sourceMappingURL=App.js.map
|