@e-llm-studio/instant-learning 1.3.3 → 1.3.4

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.
Files changed (57) hide show
  1. package/dist/ILMarketplaceWrapper.js +3 -0
  2. package/dist/ILMarketplaceWrapper.js.map +1 -1
  3. package/dist/cjs/ILMarketplaceWrapper.js +3 -0
  4. package/dist/cjs/ILMarketplaceWrapper.js.map +1 -1
  5. package/dist/cjs/features/IL-OTJ/_components/ChatComponents/ChatComponent.js +2 -1
  6. package/dist/cjs/features/IL-OTJ/_components/ChatComponents/ChatComponent.js.map +1 -1
  7. package/dist/cjs/features/IL-OTJ/_components/ChatComponents/NormalChat.js +2 -1
  8. package/dist/cjs/features/IL-OTJ/_components/ChatComponents/NormalChat.js.map +1 -1
  9. package/dist/cjs/features/IL-marketplace/PromoteFlow/EnvironmentConfigurationModal.js +41 -4
  10. package/dist/cjs/features/IL-marketplace/PromoteFlow/EnvironmentConfigurationModal.js.map +1 -1
  11. package/dist/cjs/features/IL-marketplace/PromoteFlow/PromoteFlow.js +444 -169
  12. package/dist/cjs/features/IL-marketplace/PromoteFlow/PromoteFlow.js.map +1 -1
  13. package/dist/cjs/features/IL-marketplace/PromoteFlow/PromoteFlow.module.css.js +2 -2
  14. package/dist/cjs/features/IL-marketplace/PromoteFlow/promote-flow.api.js +19 -2
  15. package/dist/cjs/features/IL-marketplace/PromoteFlow/promote-flow.api.js.map +1 -1
  16. package/dist/cjs/features/IL-marketplace/PromoteFlow/promote-flow.store.js +7 -0
  17. package/dist/cjs/features/IL-marketplace/PromoteFlow/promote-flow.store.js.map +1 -1
  18. package/dist/cjs/features/InstantLearning/InstantLearning.js +1 -0
  19. package/dist/cjs/features/InstantLearning/InstantLearning.js.map +1 -1
  20. package/dist/cjs/features/InstantLearning/_components/ChatComponent.js +3 -1
  21. package/dist/cjs/features/InstantLearning/_components/ChatComponent.js.map +1 -1
  22. package/dist/cjs/features/InstantLearning/_components/ContextualChatComponent.js +3 -1
  23. package/dist/cjs/features/InstantLearning/_components/ContextualChatComponent.js.map +1 -1
  24. package/dist/features/IL-OTJ/_components/ChatComponents/ChatComponent.js +2 -1
  25. package/dist/features/IL-OTJ/_components/ChatComponents/ChatComponent.js.map +1 -1
  26. package/dist/features/IL-OTJ/_components/ChatComponents/NormalChat.js +2 -1
  27. package/dist/features/IL-OTJ/_components/ChatComponents/NormalChat.js.map +1 -1
  28. package/dist/features/IL-marketplace/PromoteFlow/EnvironmentConfigurationModal.js +41 -4
  29. package/dist/features/IL-marketplace/PromoteFlow/EnvironmentConfigurationModal.js.map +1 -1
  30. package/dist/features/IL-marketplace/PromoteFlow/PromoteFlow.js +446 -171
  31. package/dist/features/IL-marketplace/PromoteFlow/PromoteFlow.js.map +1 -1
  32. package/dist/features/IL-marketplace/PromoteFlow/PromoteFlow.module.css.js +2 -2
  33. package/dist/features/IL-marketplace/PromoteFlow/promote-flow.api.js +17 -3
  34. package/dist/features/IL-marketplace/PromoteFlow/promote-flow.api.js.map +1 -1
  35. package/dist/features/IL-marketplace/PromoteFlow/promote-flow.store.js +7 -0
  36. package/dist/features/IL-marketplace/PromoteFlow/promote-flow.store.js.map +1 -1
  37. package/dist/features/InstantLearning/InstantLearning.js +1 -0
  38. package/dist/features/InstantLearning/InstantLearning.js.map +1 -1
  39. package/dist/features/InstantLearning/_components/ChatComponent.js +3 -1
  40. package/dist/features/InstantLearning/_components/ChatComponent.js.map +1 -1
  41. package/dist/features/InstantLearning/_components/ContextualChatComponent.js +3 -1
  42. package/dist/features/InstantLearning/_components/ContextualChatComponent.js.map +1 -1
  43. package/dist/types/src/ILMarketplaceWrapper.d.ts.map +1 -1
  44. package/dist/types/src/features/IL-OTJ/_components/ChatComponents/ChatComponent.d.ts.map +1 -1
  45. package/dist/types/src/features/IL-OTJ/_components/ChatComponents/NormalChat.d.ts.map +1 -1
  46. package/dist/types/src/features/IL-marketplace/PromoteFlow/EnvironmentConfigurationModal.d.ts.map +1 -1
  47. package/dist/types/src/features/IL-marketplace/PromoteFlow/PromoteFlow.d.ts.map +1 -1
  48. package/dist/types/src/features/IL-marketplace/PromoteFlow/promote-flow.api.d.ts +5 -2
  49. package/dist/types/src/features/IL-marketplace/PromoteFlow/promote-flow.api.d.ts.map +1 -1
  50. package/dist/types/src/features/IL-marketplace/PromoteFlow/promote-flow.interfaces.d.ts +26 -1
  51. package/dist/types/src/features/IL-marketplace/PromoteFlow/promote-flow.interfaces.d.ts.map +1 -1
  52. package/dist/types/src/features/IL-marketplace/PromoteFlow/promote-flow.store.d.ts +3 -1
  53. package/dist/types/src/features/IL-marketplace/PromoteFlow/promote-flow.store.d.ts.map +1 -1
  54. package/dist/types/src/features/InstantLearning/InstantLearning.d.ts.map +1 -1
  55. package/dist/types/src/features/InstantLearning/_components/ChatComponent.d.ts.map +1 -1
  56. package/dist/types/src/features/InstantLearning/_components/ContextualChatComponent.d.ts.map +1 -1
  57. package/package.json +4 -4
@@ -48,26 +48,21 @@ const ACCORDIONS = [
48
48
  {
49
49
  id: "database",
50
50
  title: "Database Details",
51
- comingSoon: true
52
- },
53
- {
54
- id: "knowledgebase",
55
- title: "Knowledgebase Details",
56
- comingSoon: true
51
+ comingSoon: false
57
52
  }
53
+ // {
54
+ // id: 'knowledgebase',
55
+ // title: 'Knowledgebase Details',
56
+ // comingSoon: true,
57
+ // },
58
58
  ];
59
- const TABLE_NAMES = [
60
- "document_feature_details",
61
- "document_feature_terminology",
62
- "document_feature_validation",
63
- "techo_document_feature",
64
- "document_feature_configuration",
65
- "document_feature_techme",
66
- "document_feature_schema",
67
- "document_feature_cognitive_compare"
68
- ];
59
+ const isMissingPromotionStatus = (error) => {
60
+ var _a;
61
+ if (error instanceof Error && error.message.includes("404")) return true;
62
+ return typeof error === "object" && error !== null && "response" in error && ((_a = error.response) == null ? void 0 : _a.status) === 404;
63
+ };
69
64
  function PromoteFlow({ guideline, onBack, onPromote, className }) {
70
- var _a, _b, _c, _d, _e;
65
+ var _a, _b, _c, _d, _e, _f, _g;
71
66
  const [openSections, setOpenSections] = React.useState({
72
67
  overview: true
73
68
  });
@@ -77,13 +72,24 @@ function PromoteFlow({ guideline, onBack, onPromote, className }) {
77
72
  );
78
73
  const [promotedByName, setPromotedByName] = React.useState(null);
79
74
  const [promotionHistory, setPromotionHistory] = React.useState([]);
75
+ const [schemaPreview, setSchemaPreview] = React.useState({});
76
+ const [isLoadingSchemaPreview, setIsLoadingSchemaPreview] = React.useState(false);
80
77
  const [isLoadingHistory, setIsLoadingHistory] = React.useState(false);
81
78
  const [promotionConfigs, setPromotionConfigs] = React.useState([]);
82
79
  const [isLoadingConfigs, setIsLoadingConfigs] = React.useState(false);
83
80
  const [configSearchTier, setConfigSearchTier] = React.useState(null);
84
81
  const [submittingAction, setSubmittingAction] = React.useState(null);
82
+ const [historyActionTaskId, setHistoryActionTaskId] = React.useState(null);
83
+ const [isStatusPollingStopped, setIsStatusPollingStopped] = React.useState(false);
84
+ const [isInitialStatusLoading, setIsInitialStatusLoading] = React.useState(true);
85
+ const [isCheckingPreflight, setIsCheckingPreflight] = React.useState(false);
86
+ const [preflightResult, setPreflightResult] = React.useState(null);
85
87
  const sourceEnvironment = promoteFlow_store.usePromoteFlowStore((state) => state.sourceEnvironment);
86
88
  const destinationEnvironment = promoteFlow_store.usePromoteFlowStore((state) => state.destinationEnvironment);
89
+ const tenantSourceEnvironment = promoteFlow_store.usePromoteFlowStore((state) => state.tenantSourceEnvironment);
90
+ const tenantDestinationEnvironment = promoteFlow_store.usePromoteFlowStore(
91
+ (state) => state.tenantDestinationEnvironment
92
+ );
87
93
  const promotionTask = promoteFlow_store.usePromoteFlowStore((state) => state.promotionTask);
88
94
  const promotionResourceId = promoteFlow_store.usePromoteFlowStore((state) => state.promotionResourceId);
89
95
  const isSubmitting = promoteFlow_store.usePromoteFlowStore((state) => state.isSubmitting);
@@ -102,9 +108,14 @@ function PromoteFlow({ guideline, onBack, onPromote, className }) {
102
108
  const errorForGuideline = errorResourceId === guidelineResourceId ? error : null;
103
109
  const isSourceConfigured = Boolean(sourceEnvironment);
104
110
  const isDestinationConfigured = Boolean(destinationEnvironment);
105
- const canPromote = isSourceConfigured && isDestinationConfigured && !isSubmitting;
111
+ const canPromote = isSourceConfigured && isDestinationConfigured && !isSubmitting && !isInitialStatusLoading;
106
112
  const sourceEnvironmentLabel = promoteFlow_utils.getEnvironmentDisplayName(sourceEnvironment, "Dev");
107
113
  const destinationEnvironmentLabel = promoteFlow_utils.getEnvironmentDisplayName(destinationEnvironment, "QA");
114
+ const tenantSourceEnvironmentLabel = promoteFlow_utils.getEnvironmentDisplayName(tenantSourceEnvironment, "\u2014");
115
+ const tenantDestinationEnvironmentLabel = promoteFlow_utils.getEnvironmentDisplayName(
116
+ tenantDestinationEnvironment,
117
+ "\u2014"
118
+ );
108
119
  const isPromoting = Boolean(promotionTaskForGuideline);
109
120
  const canRetryPromotion = (promotionTaskForGuideline == null ? void 0 : promotionTaskForGuideline.status) === "FAILED";
110
121
  const sourceTier = (_b = sourceEnvironment == null ? void 0 : sourceEnvironment.env_tier) != null ? _b : "dev";
@@ -113,7 +124,7 @@ function PromoteFlow({ guideline, onBack, onPromote, className }) {
113
124
  [sourceTier]
114
125
  );
115
126
  const permittedSourceTiers = ["dev", "qa", "prod", "external"];
116
- const selectedEnvironment = configuredEnvironment === "source" ? sourceEnvironment : destinationEnvironment;
127
+ const selectedEnvironment = configuredEnvironment === "source" ? sourceEnvironment : configuredEnvironment === "destination" ? destinationEnvironment : configuredEnvironment === "tenantSource" ? tenantSourceEnvironment : tenantDestinationEnvironment;
117
128
  const latestPromotionForPair = React.useMemo(
118
129
  () => promoteFlow_utils.getLatestPromotionForEnvironmentPair(
119
130
  promotionHistory,
@@ -122,6 +133,17 @@ function PromoteFlow({ guideline, onBack, onPromote, className }) {
122
133
  ),
123
134
  [destinationEnvironment, promotionHistory, sourceEnvironment]
124
135
  );
136
+ const latestPromotionTaskId = React.useMemo(() => {
137
+ var _a2;
138
+ const latestPromotion = promotionHistory.reduce(
139
+ (latest, entry) => {
140
+ if (!latest) return entry;
141
+ return Date.parse(entry.updated_at) > Date.parse(latest.updated_at) ? entry : latest;
142
+ },
143
+ null
144
+ );
145
+ return (_a2 = latestPromotion == null ? void 0 : latestPromotion.promotion_task_id) != null ? _a2 : null;
146
+ }, [promotionHistory]);
125
147
  const promoteActionLabel = (latestPromotionForPair == null ? void 0 : latestPromotionForPair.status) === "SUCCESS" ? "Sync" : "Promote Now";
126
148
  const toggleSection = (id) => {
127
149
  setOpenSections((current) => ({ ...current, [id]: !current[id] }));
@@ -129,33 +151,77 @@ function PromoteFlow({ guideline, onBack, onPromote, className }) {
129
151
  React.useEffect(() => {
130
152
  let isCurrent = true;
131
153
  setIsLoadingHistory(true);
132
- promoteFlow_api.getPromotionHistory(guidelineResourceId).then((history) => {
133
- if (isCurrent) setPromotionHistory(history);
134
- }).catch((historyError) => {
154
+ setIsInitialStatusLoading(true);
155
+ setError(null);
156
+ setPromotionTask(null);
157
+ const refreshInitialPromotionState = async () => {
158
+ try {
159
+ await promoteFlow_api.getPromotionStatus(guidelineResourceId);
160
+ } catch (statusError) {
161
+ if (isCurrent && !isMissingPromotionStatus(statusError)) {
162
+ setError(
163
+ statusError instanceof Error ? statusError.message : "Unable to refresh promotion status.",
164
+ guidelineResourceId
165
+ );
166
+ }
167
+ } finally {
168
+ if (isCurrent) setIsInitialStatusLoading(false);
169
+ }
170
+ try {
171
+ const history = await promoteFlow_api.getPromotionHistory(guidelineResourceId);
172
+ if (isCurrent) setPromotionHistory(history);
173
+ } catch (historyError) {
174
+ if (isCurrent) {
175
+ setError(
176
+ historyError instanceof Error ? historyError.message : "Unable to load promotion history.",
177
+ guidelineResourceId
178
+ );
179
+ }
180
+ } finally {
181
+ if (isCurrent) setIsLoadingHistory(false);
182
+ }
183
+ };
184
+ void refreshInitialPromotionState();
185
+ return () => {
186
+ isCurrent = false;
187
+ };
188
+ }, [guidelineResourceId, setError, setPromotionTask]);
189
+ React.useEffect(() => {
190
+ let isCurrent = true;
191
+ setIsLoadingSchemaPreview(true);
192
+ promoteFlow_api.getSchemaPreview(guidelineResourceId).then((preview) => {
193
+ if (!isCurrent) return;
194
+ setSchemaPreview(
195
+ Object.entries(preview != null ? preview : {}).reduce((groups, [key, value]) => {
196
+ if (value && Array.isArray(value.tables)) groups[key] = value;
197
+ return groups;
198
+ }, {})
199
+ );
200
+ }).catch((schemaError) => {
135
201
  if (isCurrent) {
136
- setError(
137
- historyError instanceof Error ? historyError.message : "Unable to load promotion history.",
138
- guidelineResourceId
139
- );
202
+ console.error("Failed to load schema preview", { resourceId: guidelineResourceId, schemaError });
203
+ setSchemaPreview({});
140
204
  }
141
205
  }).finally(() => {
142
- if (isCurrent) setIsLoadingHistory(false);
206
+ if (isCurrent) setIsLoadingSchemaPreview(false);
143
207
  });
144
208
  return () => {
145
209
  isCurrent = false;
146
210
  };
147
- }, [guidelineResourceId, setError]);
211
+ }, [guidelineResourceId]);
148
212
  React.useEffect(() => {
149
- var _a2, _b2;
213
+ var _a2, _b2, _c2, _d2;
150
214
  if (!configuredEnvironment) return;
151
- const defaultTier = configuredEnvironment === "source" ? (_a2 = sourceEnvironment == null ? void 0 : sourceEnvironment.env_tier) != null ? _a2 : "dev" : (_b2 = destinationEnvironment == null ? void 0 : destinationEnvironment.env_tier) != null ? _b2 : permittedDestinationTiers[0];
215
+ const selectedEnvironment2 = configuredEnvironment === "source" ? (_a2 = sourceEnvironment == null ? void 0 : sourceEnvironment.env_tier) != null ? _a2 : "dev" : configuredEnvironment === "destination" ? (_b2 = destinationEnvironment == null ? void 0 : destinationEnvironment.env_tier) != null ? _b2 : permittedDestinationTiers[0] : configuredEnvironment === "tenantSource" ? (_c2 = tenantSourceEnvironment == null ? void 0 : tenantSourceEnvironment.env_tier) != null ? _c2 : "dev" : (_d2 = tenantDestinationEnvironment == null ? void 0 : tenantDestinationEnvironment.env_tier) != null ? _d2 : permittedDestinationTiers[0];
216
+ const defaultTier = selectedEnvironment2;
152
217
  const envTier = configSearchTier != null ? configSearchTier : defaultTier;
153
218
  let isCurrent = true;
154
219
  setIsLoadingConfigs(true);
155
220
  setPromotionConfigs([]);
156
221
  promoteFlow_api.searchEnvironmentConfigs({
157
222
  env_tier: envTier,
158
- db_type: envTier === "external" ? "EXTERNAL" : "INTERNAL"
223
+ db_type: envTier === "external" ? "EXTERNAL" : "INTERNAL",
224
+ is_tenant: configuredEnvironment === "tenantSource" || configuredEnvironment === "tenantDestination"
159
225
  }).then((configs) => {
160
226
  if (isCurrent) setPromotionConfigs(configs);
161
227
  }).catch(() => {
@@ -172,7 +238,9 @@ function PromoteFlow({ guideline, onBack, onPromote, className }) {
172
238
  destinationEnvironment == null ? void 0 : destinationEnvironment.env_tier,
173
239
  guidelineResourceId,
174
240
  permittedDestinationTiers,
175
- sourceEnvironment == null ? void 0 : sourceEnvironment.env_tier
241
+ sourceEnvironment == null ? void 0 : sourceEnvironment.env_tier,
242
+ tenantDestinationEnvironment == null ? void 0 : tenantDestinationEnvironment.env_tier,
243
+ tenantSourceEnvironment == null ? void 0 : tenantSourceEnvironment.env_tier
176
244
  ]);
177
245
  React.useEffect(() => {
178
246
  const promotedByEmail = promotionTaskForGuideline == null ? void 0 : promotionTaskForGuideline.created_by;
@@ -195,11 +263,14 @@ function PromoteFlow({ guideline, onBack, onPromote, className }) {
195
263
  };
196
264
  }, [promotionTaskForGuideline == null ? void 0 : promotionTaskForGuideline.created_by, promotionTaskForGuideline == null ? void 0 : promotionTaskForGuideline.promotion_task_id]);
197
265
  React.useEffect(() => {
198
- if (!promotionTaskForGuideline || promotionTaskForGuideline.status !== "MIGRATING") return;
266
+ if (!promotionTaskForGuideline || isStatusPollingStopped || !["MIGRATING", "ROLLBACK_IN_PROGRESS"].includes(promotionTaskForGuideline.status)) {
267
+ return;
268
+ }
199
269
  const pollStatus = async () => {
200
270
  try {
201
- setPromotionTask(await promoteFlow_api.getPromotionStatus(promotionTaskForGuideline.promotion_task_id));
271
+ setPromotionTask(await promoteFlow_api.getPromotionStatus(guidelineResourceId), guidelineResourceId);
202
272
  } catch (pollError) {
273
+ setIsStatusPollingStopped(true);
203
274
  setError(
204
275
  pollError instanceof Error ? pollError.message : "Unable to refresh promotion status.",
205
276
  guidelineResourceId
@@ -208,7 +279,7 @@ function PromoteFlow({ guideline, onBack, onPromote, className }) {
208
279
  };
209
280
  const intervalId = window.setInterval(pollStatus, 3e4);
210
281
  return () => window.clearInterval(intervalId);
211
- }, [guidelineResourceId, promotionTaskForGuideline, setError, setPromotionTask]);
282
+ }, [guidelineResourceId, isStatusPollingStopped, promotionTaskForGuideline, setError, setPromotionTask]);
212
283
  const handlePromoteNow = async () => {
213
284
  if (!canPromote || !sourceEnvironment || !destinationEnvironment) return;
214
285
  setSubmitting(true);
@@ -220,9 +291,18 @@ function PromoteFlow({ guideline, onBack, onPromote, className }) {
220
291
  resource_type: "PACKAGE",
221
292
  target_version: "latest",
222
293
  global_source_env_id: sourceEnvironment.env_id,
223
- global_target_env_id: destinationEnvironment.env_id
294
+ global_target_env_id: destinationEnvironment.env_id,
295
+ ...tenantSourceEnvironment && tenantDestinationEnvironment ? {
296
+ tenant_source_env_id: tenantSourceEnvironment.env_id,
297
+ tenant_target_env_id: tenantDestinationEnvironment.env_id
298
+ } : {}
224
299
  });
300
+ setIsStatusPollingStopped(false);
225
301
  setPromotionTask(task, guidelineResourceId);
302
+ try {
303
+ setPromotionTask(await promoteFlow_api.getPromotionStatus(guidelineResourceId), guidelineResourceId);
304
+ } catch (e) {
305
+ }
226
306
  onPromote == null ? void 0 : onPromote(guideline);
227
307
  } catch (promotionError) {
228
308
  setError(
@@ -234,15 +314,53 @@ function PromoteFlow({ guideline, onBack, onPromote, className }) {
234
314
  setSubmittingAction(null);
235
315
  }
236
316
  };
317
+ const handlePreflightCheck = async () => {
318
+ if (!sourceEnvironment || !destinationEnvironment || isCheckingPreflight) return;
319
+ setIsCheckingPreflight(true);
320
+ setPreflightResult(null);
321
+ setError(null);
322
+ try {
323
+ const result = await promoteFlow_api.checkPromotionPreflight({
324
+ resource_id: guidelineResourceId,
325
+ resource_type: "PACKAGE",
326
+ target_version: "latest",
327
+ global_source_env_id: sourceEnvironment.env_id,
328
+ global_target_env_id: destinationEnvironment.env_id,
329
+ ...tenantSourceEnvironment && tenantDestinationEnvironment ? {
330
+ tenant_source_env_id: tenantSourceEnvironment.env_id,
331
+ tenant_target_env_id: tenantDestinationEnvironment.env_id
332
+ } : {}
333
+ });
334
+ setPreflightResult({
335
+ ready: result.ready,
336
+ itemsChecked: result.items_checked,
337
+ itemsReady: result.items_ready
338
+ });
339
+ } catch (preflightError) {
340
+ setError(
341
+ preflightError instanceof Error ? preflightError.message : "Unable to complete pre-flight check.",
342
+ guidelineResourceId
343
+ );
344
+ } finally {
345
+ setIsCheckingPreflight(false);
346
+ }
347
+ };
237
348
  const handleSaveEnvironment = async (environment, configuration) => {
238
- const response = await promoteFlow_api.createEnvironmentConfig(promoteFlow_utils.toCreateEnvironmentConfigRequest(configuration));
239
- setEnvironment(environment, promoteFlow_utils.toRegistryRecord(response.env_id, configuration));
349
+ const isTenantEnvironment = environment === "tenantSource" || environment === "tenantDestination";
350
+ const configurationToSave = {
351
+ ...configuration,
352
+ is_tenant_db: isTenantEnvironment
353
+ };
354
+ const response = await promoteFlow_api.createEnvironmentConfig(
355
+ promoteFlow_utils.toCreateEnvironmentConfigRequest(configurationToSave)
356
+ );
357
+ setEnvironment(environment, promoteFlow_utils.toRegistryRecord(response.env_id, configurationToSave));
240
358
  };
241
359
  const openEnvironmentConfiguration = (environment) => {
242
360
  var _a2;
243
- const selected = environment === "source" ? sourceEnvironment : destinationEnvironment;
361
+ const selected = environment === "source" ? sourceEnvironment : environment === "destination" ? destinationEnvironment : environment === "tenantSource" ? tenantSourceEnvironment : tenantDestinationEnvironment;
244
362
  setConfigSearchTier(
245
- (_a2 = selected == null ? void 0 : selected.env_tier) != null ? _a2 : environment === "source" ? "dev" : permittedDestinationTiers[0]
363
+ (_a2 = selected == null ? void 0 : selected.env_tier) != null ? _a2 : environment === "source" || environment === "tenantSource" ? "dev" : permittedDestinationTiers[0]
246
364
  );
247
365
  setConfiguredEnvironment(environment);
248
366
  };
@@ -258,7 +376,11 @@ function PromoteFlow({ guideline, onBack, onPromote, className }) {
258
376
  resource_type: "PACKAGE",
259
377
  target_version: "latest",
260
378
  global_source_env_id: sourceEnvironment.env_id,
261
- global_target_env_id: destinationEnvironment.env_id
379
+ global_target_env_id: destinationEnvironment.env_id,
380
+ ...tenantSourceEnvironment && tenantDestinationEnvironment ? {
381
+ tenant_source_env_id: tenantSourceEnvironment.env_id,
382
+ tenant_target_env_id: tenantDestinationEnvironment.env_id
383
+ } : {}
262
384
  });
263
385
  const now = (/* @__PURE__ */ new Date()).toISOString();
264
386
  setPromotionTask(
@@ -293,7 +415,12 @@ function PromoteFlow({ guideline, onBack, onPromote, className }) {
293
415
  setError(null);
294
416
  try {
295
417
  const task = await promoteFlow_api.triggerScheduledPromotion(triggerUrl);
418
+ setIsStatusPollingStopped(false);
296
419
  setPromotionTask(task, guidelineResourceId);
420
+ try {
421
+ setPromotionTask(await promoteFlow_api.getPromotionStatus(guidelineResourceId), guidelineResourceId);
422
+ } catch (e) {
423
+ }
297
424
  onPromote == null ? void 0 : onPromote(guideline);
298
425
  } catch (promotionError) {
299
426
  setError(
@@ -305,7 +432,45 @@ function PromoteFlow({ guideline, onBack, onPromote, className }) {
305
432
  setSubmittingAction(null);
306
433
  }
307
434
  };
435
+ const handleViewPromotionDetails = async (promotionTaskId) => {
436
+ setHistoryActionTaskId(promotionTaskId);
437
+ setError(null);
438
+ try {
439
+ setIsStatusPollingStopped(false);
440
+ setPromotionTask(await promoteFlow_api.getPromotionStatus(guidelineResourceId), guidelineResourceId);
441
+ } catch (statusError) {
442
+ setError(
443
+ statusError instanceof Error ? statusError.message : "Unable to load promotion details.",
444
+ guidelineResourceId
445
+ );
446
+ } finally {
447
+ setHistoryActionTaskId(null);
448
+ }
449
+ };
450
+ const handleRollbackPromotion = async (promotionTaskId) => {
451
+ setHistoryActionTaskId(promotionTaskId);
452
+ setError(null);
453
+ try {
454
+ const task = await promoteFlow_api.rollbackPromotion(promotionTaskId);
455
+ setIsStatusPollingStopped(false);
456
+ setPromotionTask(task, guidelineResourceId);
457
+ } catch (rollbackError) {
458
+ setError(
459
+ rollbackError instanceof Error ? rollbackError.message : "Unable to start rollback.",
460
+ guidelineResourceId
461
+ );
462
+ } finally {
463
+ setHistoryActionTaskId(null);
464
+ }
465
+ };
308
466
  const handleBack = () => {
467
+ if (promotionTaskForGuideline) {
468
+ setPromotionTask(null);
469
+ return;
470
+ }
471
+ handleGoToMarketplace();
472
+ };
473
+ const handleGoToMarketplace = () => {
309
474
  if ((promotionTaskForGuideline == null ? void 0 : promotionTaskForGuideline.status) === "FAILED") {
310
475
  resetPromotionSession();
311
476
  }
@@ -326,63 +491,90 @@ function PromoteFlow({ guideline, onBack, onPromote, className }) {
326
491
  };
327
492
  const renderAccordionBody = (id) => {
328
493
  if (id === "overview") {
329
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PromoteFlow_module["default"].overviewPanel, children: [
330
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PromoteFlow_module["default"].overviewGrid, children: [
331
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
332
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PromoteFlow_module["default"].environmentHeading, children: [
333
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: PromoteFlow_module["default"].metaLabel, children: "Source Environment" }),
334
- /* @__PURE__ */ jsxRuntime.jsx(
335
- "button",
336
- {
337
- type: "button",
338
- className: utils.cx(
339
- PromoteFlow_module["default"].configureEnvironmentButton,
340
- !isSourceConfigured && PromoteFlow_module["default"].configureEnvironmentButtonRequired
341
- ),
342
- "aria-label": "Configure source environment",
343
- "data-tooltip": "Configure source environment",
344
- onClick: () => openEnvironmentConfiguration("source"),
345
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Settings2, { "aria-hidden": "true", strokeWidth: 2 })
346
- }
347
- )
348
- ] }),
349
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: PromoteFlow_module["default"].metaValue, children: sourceEnvironmentLabel })
494
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: PromoteFlow_module["default"].overviewPanel, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PromoteFlow_module["default"].overviewGrid, children: [
495
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
496
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PromoteFlow_module["default"].environmentHeading, children: [
497
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: PromoteFlow_module["default"].metaLabel, children: "Source Environment" }),
498
+ /* @__PURE__ */ jsxRuntime.jsx(
499
+ "button",
500
+ {
501
+ type: "button",
502
+ className: utils.cx(
503
+ PromoteFlow_module["default"].configureEnvironmentButton,
504
+ !isSourceConfigured && PromoteFlow_module["default"].configureEnvironmentButtonRequired
505
+ ),
506
+ "aria-label": "Configure source environment",
507
+ "data-tooltip": "Configure source environment",
508
+ onClick: () => openEnvironmentConfiguration("source"),
509
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Settings2, { "aria-hidden": "true", strokeWidth: 2 })
510
+ }
511
+ )
350
512
  ] }),
351
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
352
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PromoteFlow_module["default"].environmentHeading, children: [
353
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: PromoteFlow_module["default"].metaLabel, children: "Destination Environment" }),
354
- /* @__PURE__ */ jsxRuntime.jsx(
355
- "button",
356
- {
357
- type: "button",
358
- className: utils.cx(
359
- PromoteFlow_module["default"].configureEnvironmentButton,
360
- !isDestinationConfigured && PromoteFlow_module["default"].configureEnvironmentButtonRequired
361
- ),
362
- "aria-label": "Configure destination environment",
363
- "data-tooltip": "Configure destination environment",
364
- onClick: () => openEnvironmentConfiguration("destination"),
365
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Settings2, { "aria-hidden": "true", strokeWidth: 2 })
366
- }
367
- )
368
- ] }),
369
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: PromoteFlow_module["default"].metaValue, children: destinationEnvironmentLabel })
513
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: PromoteFlow_module["default"].metaValue, children: sourceEnvironmentLabel })
514
+ ] }),
515
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
516
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PromoteFlow_module["default"].environmentHeading, children: [
517
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: PromoteFlow_module["default"].metaLabel, children: "Destination Environment" }),
518
+ /* @__PURE__ */ jsxRuntime.jsx(
519
+ "button",
520
+ {
521
+ type: "button",
522
+ className: utils.cx(
523
+ PromoteFlow_module["default"].configureEnvironmentButton,
524
+ !isDestinationConfigured && PromoteFlow_module["default"].configureEnvironmentButtonRequired
525
+ ),
526
+ "aria-label": "Configure destination environment",
527
+ "data-tooltip": "Configure destination environment",
528
+ onClick: () => openEnvironmentConfiguration("destination"),
529
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Settings2, { "aria-hidden": "true", strokeWidth: 2 })
530
+ }
531
+ )
370
532
  ] }),
371
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
372
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: PromoteFlow_module["default"].metaLabel, children: "ILKB status" }),
373
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: PromoteFlow_module["default"].metaValue, children: statusLabel })
533
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: PromoteFlow_module["default"].metaValue, children: destinationEnvironmentLabel })
534
+ ] }),
535
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
536
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: PromoteFlow_module["default"].metaLabel, children: "ILKB status" }),
537
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: PromoteFlow_module["default"].metaValue, children: statusLabel })
538
+ ] }),
539
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
540
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: PromoteFlow_module["default"].metaLabel, children: "Version" }),
541
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: PromoteFlow_module["default"].versionPill, children: versionLabel })
542
+ ] }),
543
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
544
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PromoteFlow_module["default"].environmentHeading, children: [
545
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: PromoteFlow_module["default"].metaLabel, children: "Tenant Source Environment (optional)" }),
546
+ /* @__PURE__ */ jsxRuntime.jsx(
547
+ "button",
548
+ {
549
+ type: "button",
550
+ className: PromoteFlow_module["default"].configureEnvironmentButton,
551
+ "aria-label": "Configure tenant source environment",
552
+ "data-tooltip": "Configure tenant source environment",
553
+ onClick: () => openEnvironmentConfiguration("tenantSource"),
554
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Settings2, { "aria-hidden": "true", strokeWidth: 2 })
555
+ }
556
+ )
374
557
  ] }),
375
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
376
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: PromoteFlow_module["default"].metaLabel, children: "Version" }),
377
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: PromoteFlow_module["default"].versionPill, children: versionLabel })
378
- ] })
558
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: PromoteFlow_module["default"].metaValue, children: tenantSourceEnvironmentLabel })
379
559
  ] }),
380
560
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
381
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: PromoteFlow_module["default"].metaLabel, children: "Current URL" }),
382
- "Coming soon.",
383
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { className: PromoteFlow_module["default"].urlIcon, strokeWidth: 2 })
561
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PromoteFlow_module["default"].environmentHeading, children: [
562
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: PromoteFlow_module["default"].metaLabel, children: "Tenant Database Environment (optional)" }),
563
+ /* @__PURE__ */ jsxRuntime.jsx(
564
+ "button",
565
+ {
566
+ type: "button",
567
+ className: PromoteFlow_module["default"].configureEnvironmentButton,
568
+ "aria-label": "Configure tenant database environment",
569
+ "data-tooltip": "Configure tenant database environment",
570
+ onClick: () => openEnvironmentConfiguration("tenantDestination"),
571
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Settings2, { "aria-hidden": "true", strokeWidth: 2 })
572
+ }
573
+ )
574
+ ] }),
575
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: PromoteFlow_module["default"].metaValue, children: tenantDestinationEnvironmentLabel })
384
576
  ] })
385
- ] });
577
+ ] }) });
386
578
  }
387
579
  if (id === "history") {
388
580
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: PromoteFlow_module["default"].historyPanel, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: PromoteFlow_module["default"].historyTableWrapper, children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: PromoteFlow_module["default"].historyTable, children: [
@@ -395,37 +587,55 @@ function PromoteFlow({ guideline, onBack, onPromote, className }) {
395
587
  ] }) }),
396
588
  /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: isLoadingHistory ? /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan: 5, children: "Loading promotion history\u2026" }) }) : promotionHistory.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan: 5, children: "No promotion history yet." }) }) : promotionHistory.map((row) => {
397
589
  var _a2, _b2;
590
+ const canRollback = row.status === "SUCCESS" && row.promotion_task_id === latestPromotionTaskId;
398
591
  return /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
399
592
  /* @__PURE__ */ jsxRuntime.jsx("td", { children: row.promotion_task_id }),
400
593
  /* @__PURE__ */ jsxRuntime.jsx("td", { children: (_a2 = row.created_by) != null ? _a2 : "\u2014" }),
401
594
  /* @__PURE__ */ jsxRuntime.jsx("td", { children: (_b2 = row.error_summary) != null ? _b2 : "No errors." }),
402
595
  /* @__PURE__ */ jsxRuntime.jsx("td", { children: promoteFlow_utils.formatPromotionDate(row.updated_at) }),
403
- /* @__PURE__ */ jsxRuntime.jsx("td", { children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: PromoteFlow_module["default"].statusPill, children: row.status }) })
596
+ /* @__PURE__ */ jsxRuntime.jsxs("td", { children: [
597
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: PromoteFlow_module["default"].statusPill, children: row.status }),
598
+ /* @__PURE__ */ jsxRuntime.jsx(
599
+ "button",
600
+ {
601
+ type: "button",
602
+ className: utils.cx(
603
+ PromoteFlow_module["default"].tableActionButton,
604
+ canRollback && PromoteFlow_module["default"].tableActionButtonDanger
605
+ ),
606
+ onClick: () => canRollback ? handleRollbackPromotion(row.promotion_task_id) : handleViewPromotionDetails(row.promotion_task_id),
607
+ disabled: isInitialStatusLoading || historyActionTaskId !== null,
608
+ children: historyActionTaskId === row.promotion_task_id ? canRollback ? "Rolling back\u2026" : "Loading\u2026" : canRollback ? "Rollback" : "View details"
609
+ }
610
+ )
611
+ ] })
404
612
  ] }, row.promotion_task_id);
405
613
  }) })
406
614
  ] }) }) });
407
615
  }
408
616
  if (id === "database") {
409
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PromoteFlow_module["default"].databaseGrid, children: [
410
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PromoteFlow_module["default"].databaseCard, children: [
411
- /* @__PURE__ */ jsxRuntime.jsx("h3", { children: "Source Database : il-otj-35" }),
412
- /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
413
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: PromoteFlow_module["default"].inlineChevron, strokeWidth: 2 }),
414
- "Tables (12)"
617
+ if (isLoadingSchemaPreview) return /* @__PURE__ */ jsxRuntime.jsx("div", { className: PromoteFlow_module["default"].emptyBody, children: "Loading database details\u2026" });
618
+ const groups = Object.entries(schemaPreview);
619
+ if (groups.length === 0) return /* @__PURE__ */ jsxRuntime.jsx("div", { className: PromoteFlow_module["default"].emptyBody, children: "No database details available." });
620
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: PromoteFlow_module["default"].databaseGrid, children: groups.flatMap(
621
+ ([groupName, group]) => ["Source", "Destination"].map((environment) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PromoteFlow_module["default"].databaseCard, children: [
622
+ /* @__PURE__ */ jsxRuntime.jsxs("h3", { children: [
623
+ environment,
624
+ " Database: ",
625
+ group.database_name
415
626
  ] }),
416
- /* @__PURE__ */ jsxRuntime.jsx("ol", { className: PromoteFlow_module["default"].tableList, children: TABLE_NAMES.map((name) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: name }, name)) }),
417
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: PromoteFlow_module["default"].moreTablesButton, children: "+4 more" })
418
- ] }),
419
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PromoteFlow_module["default"].databaseCard, children: [
420
- /* @__PURE__ */ jsxRuntime.jsx("h3", { children: "Destination Database : il-otj-35" }),
421
627
  /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
422
628
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: PromoteFlow_module["default"].inlineChevron, strokeWidth: 2 }),
423
- "Tables (12)"
629
+ groupName,
630
+ " \xB7 ",
631
+ group.schema,
632
+ " \xB7 Tables (",
633
+ group.tables.length,
634
+ ")"
424
635
  ] }),
425
- /* @__PURE__ */ jsxRuntime.jsx("ol", { className: PromoteFlow_module["default"].tableList, children: TABLE_NAMES.map((name) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: name }, name)) }),
426
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: PromoteFlow_module["default"].moreTablesButton, children: "+4 more" })
427
- ] })
428
- ] });
636
+ /* @__PURE__ */ jsxRuntime.jsx("ol", { className: PromoteFlow_module["default"].tableList, children: group.tables.map((name) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: name }, `${groupName}-${environment}-${name}`)) })
637
+ ] }, `${groupName}-${environment}`))
638
+ ) });
429
639
  }
430
640
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: PromoteFlow_module["default"].emptyBody, children: "No details available yet." });
431
641
  };
@@ -439,61 +649,108 @@ function PromoteFlow({ guideline, onBack, onPromote, className }) {
439
649
  ] }),
440
650
  /* @__PURE__ */ jsxRuntime.jsx("h1", { className: PromoteFlow_module["default"].title, children: title })
441
651
  ] }),
442
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: PromoteFlow_module["default"].ctaRow, children: isPromoting ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
443
- canRetryPromotion && /* @__PURE__ */ jsxRuntime.jsxs(
444
- "button",
445
- {
446
- type: "button",
447
- className: PromoteFlow_module["default"].primaryButton,
448
- onClick: handlePromoteNow,
449
- disabled: !canPromote,
450
- children: [
451
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { className: PromoteFlow_module["default"].buttonIcon, strokeWidth: 2.2 }),
452
- isSubmitting ? "Starting promotion\u2026" : promoteActionLabel
453
- ]
454
- }
455
- ),
456
- /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: PromoteFlow_module["default"].primaryButton, onClick: handleBack, children: [
457
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownUp, { className: PromoteFlow_module["default"].buttonIcon, strokeWidth: 2.2 }),
458
- "Go to Marketplace"
652
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PromoteFlow_module["default"].ctaRow, children: [
653
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PromoteFlow_module["default"].preflightAction, children: [
654
+ /* @__PURE__ */ jsxRuntime.jsx(
655
+ StyledPromoteTooltip,
656
+ {
657
+ title: canPromote ? "Optionally check that this migration is ready before promoting." : "Configure both source and destination environments first.",
658
+ placement: "top",
659
+ arrow: true,
660
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
661
+ "button",
662
+ {
663
+ type: "button",
664
+ className: PromoteFlow_module["default"].secondaryButton,
665
+ onClick: handlePreflightCheck,
666
+ disabled: !canPromote || isCheckingPreflight,
667
+ children: [
668
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleCheck, { className: PromoteFlow_module["default"].buttonIcon, strokeWidth: 2.2 }),
669
+ isCheckingPreflight ? "Checking readiness\u2026" : "Check promotion readiness"
670
+ ]
671
+ }
672
+ )
673
+ }
674
+ ),
675
+ /* @__PURE__ */ jsxRuntime.jsx(
676
+ StyledPromoteTooltip,
677
+ {
678
+ title: "Runs a safe validation of the selected source and destination environments. It does not start a migration.",
679
+ placement: "top",
680
+ arrow: true,
681
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: PromoteFlow_module["default"].preflightInfo, "aria-label": "About the pre-flight check", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Info, { className: PromoteFlow_module["default"].helpIcon, strokeWidth: 2.2, "aria-hidden": "true" }) })
682
+ }
683
+ )
684
+ ] }),
685
+ isPromoting ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
686
+ canRetryPromotion && /* @__PURE__ */ jsxRuntime.jsxs(
687
+ "button",
688
+ {
689
+ type: "button",
690
+ className: PromoteFlow_module["default"].primaryButton,
691
+ onClick: handlePromoteNow,
692
+ disabled: !canPromote,
693
+ children: [
694
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { className: PromoteFlow_module["default"].buttonIcon, strokeWidth: 2.2 }),
695
+ isSubmitting ? "Starting promotion\u2026" : promoteActionLabel
696
+ ]
697
+ }
698
+ ),
699
+ /* @__PURE__ */ jsxRuntime.jsxs(
700
+ "button",
701
+ {
702
+ type: "button",
703
+ className: PromoteFlow_module["default"].primaryButton,
704
+ onClick: handleGoToMarketplace,
705
+ children: [
706
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownUp, { className: PromoteFlow_module["default"].buttonIcon, strokeWidth: 2.2 }),
707
+ "Go to Marketplace"
708
+ ]
709
+ }
710
+ )
711
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
712
+ submittingAction !== "now" && /* @__PURE__ */ jsxRuntime.jsxs(
713
+ "button",
714
+ {
715
+ type: "button",
716
+ className: PromoteFlow_module["default"].secondaryButton,
717
+ onClick: handlePromoteLater,
718
+ disabled: !canPromote,
719
+ children: [
720
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Calendar, { className: PromoteFlow_module["default"].buttonIcon, strokeWidth: 2.2 }),
721
+ submittingAction === "later" ? "Scheduling\u2026" : "Promote later"
722
+ ]
723
+ }
724
+ ),
725
+ submittingAction !== "later" && /* @__PURE__ */ jsxRuntime.jsx(
726
+ StyledPromoteTooltip,
727
+ {
728
+ title: canPromote ? "" : "Configure both source and destination environments first.",
729
+ disableHoverListener: canPromote,
730
+ placement: "top",
731
+ arrow: true,
732
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
733
+ "button",
734
+ {
735
+ type: "button",
736
+ className: PromoteFlow_module["default"].primaryButton,
737
+ onClick: handlePromoteNow,
738
+ disabled: !canPromote,
739
+ children: [
740
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { className: PromoteFlow_module["default"].buttonIcon, strokeWidth: 2.2 }),
741
+ submittingAction === "now" ? "Starting promotion\u2026" : promoteActionLabel
742
+ ]
743
+ }
744
+ )
745
+ }
746
+ )
459
747
  ] })
460
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
461
- submittingAction !== "now" && /* @__PURE__ */ jsxRuntime.jsxs(
462
- "button",
463
- {
464
- type: "button",
465
- className: PromoteFlow_module["default"].secondaryButton,
466
- onClick: handlePromoteLater,
467
- disabled: !canPromote,
468
- children: [
469
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Calendar, { className: PromoteFlow_module["default"].buttonIcon, strokeWidth: 2.2 }),
470
- submittingAction === "later" ? "Scheduling\u2026" : "Promote later"
471
- ]
472
- }
473
- ),
474
- submittingAction !== "later" && /* @__PURE__ */ jsxRuntime.jsx(
475
- StyledPromoteTooltip,
476
- {
477
- title: canPromote ? "" : "Configure both source and destination environments first.",
478
- disableHoverListener: canPromote,
479
- placement: "top",
480
- arrow: true,
481
- children: /* @__PURE__ */ jsxRuntime.jsxs(
482
- "button",
483
- {
484
- type: "button",
485
- className: PromoteFlow_module["default"].primaryButton,
486
- onClick: handlePromoteNow,
487
- disabled: !canPromote,
488
- children: [
489
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { className: PromoteFlow_module["default"].buttonIcon, strokeWidth: 2.2 }),
490
- submittingAction === "now" ? "Starting promotion\u2026" : promoteActionLabel
491
- ]
492
- }
493
- )
494
- }
495
- )
496
- ] }) })
748
+ ] })
749
+ ] }),
750
+ preflightResult && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PromoteFlow_module["default"].preflightSuccess, role: "status", children: [
751
+ "Pre-flight check completed successfully.",
752
+ " ",
753
+ preflightResult.ready ? `Migration is ready (${preflightResult.itemsReady}/${preflightResult.itemsChecked} checks passed).` : `Migration readiness requires attention (${preflightResult.itemsReady}/${preflightResult.itemsChecked} checks passed).`
497
754
  ] }),
498
755
  isPromoting ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PromoteFlow_module["default"].promotionStatusBox, children: [
499
756
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: PromoteFlow_module["default"].promotionStatusRow, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PromoteFlow_module["default"].promotionStatusRowHeader, children: [
@@ -548,6 +805,23 @@ function PromoteFlow({ guideline, onBack, onPromote, className }) {
548
805
  ] })
549
806
  ] })
550
807
  ] }),
808
+ (promotionTaskForGuideline == null ? void 0 : promotionTaskForGuideline.view_detail_url) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PromoteFlow_module["default"].promotionDetailsLink, children: [
809
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: PromoteFlow_module["default"].metaLabel, children: "Promotion details" }),
810
+ /* @__PURE__ */ jsxRuntime.jsxs(
811
+ "a",
812
+ {
813
+ className: PromoteFlow_module["default"].urlLink,
814
+ href: promotionTaskForGuideline.view_detail_url,
815
+ target: "_blank",
816
+ rel: "noreferrer",
817
+ title: promotionTaskForGuideline.view_detail_url,
818
+ children: [
819
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: promotionTaskForGuideline.view_detail_url }),
820
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { className: PromoteFlow_module["default"].urlIcon, strokeWidth: 2 })
821
+ ]
822
+ }
823
+ )
824
+ ] }),
551
825
  (promotionTaskForGuideline == null ? void 0 : promotionTaskForGuideline.status) === "SCHEDULED" && promotionTaskForGuideline.trigger_url && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PromoteFlow_module["default"].scheduledTrigger, children: [
552
826
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
553
827
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: PromoteFlow_module["default"].metaLabel, children: "Scheduled promotion URL" }),
@@ -557,7 +831,7 @@ function PromoteFlow({ guideline, onBack, onPromote, className }) {
557
831
  type: "button",
558
832
  className: PromoteFlow_module["default"].scheduledTriggerUrl,
559
833
  onClick: handleTriggerScheduledPromotion,
560
- disabled: submittingAction === "trigger",
834
+ disabled: isInitialStatusLoading || submittingAction === "trigger",
561
835
  title: promotionTaskForGuideline.trigger_url,
562
836
  children: [
563
837
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: promotionTaskForGuideline.trigger_url }),
@@ -572,7 +846,7 @@ function PromoteFlow({ guideline, onBack, onPromote, className }) {
572
846
  type: "button",
573
847
  className: PromoteFlow_module["default"].primaryButton,
574
848
  onClick: handleTriggerScheduledPromotion,
575
- disabled: submittingAction === "trigger",
849
+ disabled: isInitialStatusLoading || submittingAction === "trigger",
576
850
  children: [
577
851
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { className: PromoteFlow_module["default"].buttonIcon, strokeWidth: 2.2 }),
578
852
  submittingAction === "trigger" ? "Starting promotion\u2026" : "Start promotion"
@@ -632,14 +906,15 @@ function PromoteFlow({ guideline, onBack, onPromote, className }) {
632
906
  is_tenant_db: selectedEnvironment.is_tenant_db
633
907
  } : {
634
908
  ...promoteFlow_utils.EMPTY_ENVIRONMENT_CONFIGURATION,
635
- env_tier: configuredEnvironment === "source" ? "dev" : permittedDestinationTiers[0],
636
- db_type: configuredEnvironment === "destination" && permittedDestinationTiers[0] === "external" ? "EXTERNAL" : "INTERNAL"
909
+ env_tier: configuredEnvironment === "source" || configuredEnvironment === "tenantSource" ? "dev" : permittedDestinationTiers[0],
910
+ db_type: (configuredEnvironment === "destination" || configuredEnvironment === "tenantDestination") && permittedDestinationTiers[0] === "external" ? "EXTERNAL" : "INTERNAL",
911
+ is_tenant_db: configuredEnvironment === "tenantSource" || configuredEnvironment === "tenantDestination"
637
912
  },
638
- permittedTiers: configuredEnvironment === "source" ? permittedSourceTiers : permittedDestinationTiers,
913
+ permittedTiers: configuredEnvironment === "source" || configuredEnvironment === "tenantSource" ? permittedSourceTiers : permittedDestinationTiers,
639
914
  onSave: handleSaveEnvironment,
640
915
  onSelectPreset: setEnvironment,
641
916
  onPresetTierChange: setConfigSearchTier,
642
- presetTier: configSearchTier != null ? configSearchTier : configuredEnvironment === "source" ? (_d = sourceEnvironment == null ? void 0 : sourceEnvironment.env_tier) != null ? _d : "dev" : (_e = destinationEnvironment == null ? void 0 : destinationEnvironment.env_tier) != null ? _e : permittedDestinationTiers[0],
917
+ presetTier: configSearchTier != null ? configSearchTier : configuredEnvironment === "source" ? (_d = sourceEnvironment == null ? void 0 : sourceEnvironment.env_tier) != null ? _d : "dev" : configuredEnvironment === "destination" ? (_e = destinationEnvironment == null ? void 0 : destinationEnvironment.env_tier) != null ? _e : permittedDestinationTiers[0] : configuredEnvironment === "tenantSource" ? (_f = tenantSourceEnvironment == null ? void 0 : tenantSourceEnvironment.env_tier) != null ? _f : "dev" : (_g = tenantDestinationEnvironment == null ? void 0 : tenantDestinationEnvironment.env_tier) != null ? _g : permittedDestinationTiers[0],
643
918
  onClose: () => {
644
919
  setConfiguredEnvironment(null);
645
920
  setConfigSearchTier(null);