@trops/dash-core 0.1.245 → 0.1.247

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -3574,6 +3574,102 @@ var StarRating = function StarRating(_ref) {
3574
3574
  });
3575
3575
  };
3576
3576
 
3577
+ var InstallProgressModal = function InstallProgressModal(_ref) {
3578
+ var isOpen = _ref.isOpen,
3579
+ setIsOpen = _ref.setIsOpen,
3580
+ _ref$widgets = _ref.widgets,
3581
+ widgets = _ref$widgets === void 0 ? [] : _ref$widgets,
3582
+ _ref$isComplete = _ref.isComplete,
3583
+ isComplete = _ref$isComplete === void 0 ? false : _ref$isComplete,
3584
+ onDone = _ref.onDone;
3585
+ var _useContext = React.useContext(DashReact.ThemeContext),
3586
+ currentTheme = _useContext.currentTheme;
3587
+ var panelStyles = DashReact.getStylesForItem(DashReact.themeObjects.PANEL, currentTheme, {
3588
+ grow: false
3589
+ });
3590
+
3591
+ // Prevent dismissal while installation is in progress
3592
+ var guardedSetIsOpen = function guardedSetIsOpen(val) {
3593
+ if (isComplete) setIsOpen(val);
3594
+ };
3595
+ var doneCount = widgets.filter(function (w) {
3596
+ return w.status === "installed" || w.status === "already-installed" || w.status === "failed";
3597
+ }).length;
3598
+ function statusIcon(status) {
3599
+ switch (status) {
3600
+ case "downloading":
3601
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
3602
+ className: "animate-spin rounded-full h-4 w-4 border-b-2 border-blue-400 flex-shrink-0"
3603
+ });
3604
+ case "installed":
3605
+ case "already-installed":
3606
+ return /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
3607
+ icon: "circle-check",
3608
+ className: "h-4 w-4 text-green-400 flex-shrink-0"
3609
+ });
3610
+ case "failed":
3611
+ return /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
3612
+ icon: "circle-xmark",
3613
+ className: "h-4 w-4 text-red-400 flex-shrink-0"
3614
+ });
3615
+ default:
3616
+ // pending
3617
+ return /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
3618
+ icon: "clock",
3619
+ className: "h-4 w-4 opacity-30 flex-shrink-0"
3620
+ });
3621
+ }
3622
+ }
3623
+ return /*#__PURE__*/jsxRuntime.jsx(DashReact.Modal, {
3624
+ isOpen: isOpen,
3625
+ setIsOpen: guardedSetIsOpen,
3626
+ width: "w-[440px]",
3627
+ height: "auto",
3628
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
3629
+ className: "flex flex-col rounded-lg overflow-hidden ".concat(panelStyles.backgroundColor || "bg-gray-900", " ").concat(panelStyles.textColor || "text-gray-200"),
3630
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
3631
+ className: "px-5 pt-5 pb-3",
3632
+ children: /*#__PURE__*/jsxRuntime.jsx("h3", {
3633
+ className: "text-sm font-semibold",
3634
+ children: isComplete ? "Installation Complete" : "Installing widget ".concat(doneCount + 1, " of ").concat(widgets.length, "...")
3635
+ })
3636
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
3637
+ className: "px-5 pb-3 space-y-1.5 max-h-64 overflow-y-auto",
3638
+ children: widgets.map(function (w, idx) {
3639
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
3640
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
3641
+ className: "flex items-center gap-2.5 p-2 rounded ".concat(currentTheme["bg-primary-medium"] || "bg-white/5"),
3642
+ children: [statusIcon(w.status), /*#__PURE__*/jsxRuntime.jsx("span", {
3643
+ className: "text-sm flex-1 truncate",
3644
+ children: w.displayName
3645
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
3646
+ className: "text-[10px] opacity-40",
3647
+ children: w.status === "already-installed" ? "Already installed" : w.status === "downloading" ? "Downloading..." : w.status === "installed" ? "Installed" : w.status === "failed" ? "Failed" : "Pending"
3648
+ })]
3649
+ }), w.status === "failed" && w.error && /*#__PURE__*/jsxRuntime.jsx("p", {
3650
+ className: "text-[10px] text-red-400/80 mt-0.5 ml-7 truncate",
3651
+ children: w.error
3652
+ })]
3653
+ }, idx);
3654
+ })
3655
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
3656
+ className: "flex items-center justify-end px-5 py-3 border-t ".concat(currentTheme["border-primary-medium"] || "border-white/10"),
3657
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
3658
+ title: "Done",
3659
+ bgColor: isComplete ? "bg-blue-600" : "bg-gray-700",
3660
+ hoverBackgroundColor: isComplete ? "hover:bg-blue-700" : "",
3661
+ textSize: "text-sm",
3662
+ padding: "py-1.5 px-4",
3663
+ onClick: function onClick() {
3664
+ if (isComplete && onDone) onDone();
3665
+ },
3666
+ disabled: !isComplete
3667
+ })
3668
+ })]
3669
+ })
3670
+ });
3671
+ };
3672
+
3577
3673
  function _createForOfIteratorHelper$g(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray$g(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
3578
3674
  function _unsupportedIterableToArray$g(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray$g(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray$g(r, a) : void 0; } }
3579
3675
  function _arrayLikeToArray$g(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
@@ -3616,15 +3712,30 @@ var RegistryDashboardDetail = function RegistryDashboardDetail(_ref) {
3616
3712
  _useState12 = _slicedToArray(_useState11, 2),
3617
3713
  authError = _useState12[0],
3618
3714
  setAuthError = _useState12[1];
3715
+ var _useState13 = React.useState(false),
3716
+ _useState14 = _slicedToArray(_useState13, 2),
3717
+ showProgressModal = _useState14[0],
3718
+ setShowProgressModal = _useState14[1];
3719
+ var _useState15 = React.useState([]),
3720
+ _useState16 = _slicedToArray(_useState15, 2),
3721
+ progressWidgets = _useState16[0],
3722
+ setProgressWidgets = _useState16[1];
3723
+ var _useState17 = React.useState(false),
3724
+ _useState18 = _slicedToArray(_useState17, 2),
3725
+ progressComplete = _useState18[0],
3726
+ setProgressComplete = _useState18[1];
3727
+ var progressResultRef = React.useRef(null);
3619
3728
  var pollIntervalRef = React.useRef(null);
3729
+ var cleanupProgressRef = React.useRef(null);
3620
3730
  var pkg = dashboardPackage;
3621
3731
  if (!pkg) return null;
3622
3732
 
3623
- // Clean up polling on unmount
3733
+ // Clean up polling and progress listener on unmount
3624
3734
  // eslint-disable-next-line react-hooks/rules-of-hooks
3625
3735
  React.useEffect(function () {
3626
3736
  return function () {
3627
3737
  if (pollIntervalRef.current) clearInterval(pollIntervalRef.current);
3738
+ if (cleanupProgressRef.current) cleanupProgressRef.current();
3628
3739
  };
3629
3740
  }, []);
3630
3741
 
@@ -3653,10 +3764,10 @@ var RegistryDashboardDetail = function RegistryDashboardDetail(_ref) {
3653
3764
  }, [pkg.name]);
3654
3765
  function handleInstall() {
3655
3766
  return _handleInstall.apply(this, arguments);
3656
- }
3767
+ } // eslint-disable-next-line react-hooks/rules-of-hooks
3657
3768
  function _handleInstall() {
3658
3769
  _handleInstall = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
3659
- var _result$workspace, result, _t;
3770
+ var deps, _window$mainApi2, _window$mainApi2$onIn, result, _result$workspace2, _t;
3660
3771
  return _regeneratorRuntime.wrap(function (_context) {
3661
3772
  while (1) switch (_context.prev = _context.next) {
3662
3773
  case 0:
@@ -3670,6 +3781,35 @@ var RegistryDashboardDetail = function RegistryDashboardDetail(_ref) {
3670
3781
  setInstallResult(null);
3671
3782
  setAuthFlow(null);
3672
3783
  setAuthError(null);
3784
+
3785
+ // Initialize progress modal from widget deps
3786
+ deps = widgetDeps.length > 0 ? widgetDeps : [];
3787
+ if (deps.length > 0) {
3788
+ setProgressWidgets(deps.map(function (w) {
3789
+ return {
3790
+ packageName: w["package"] || w.name,
3791
+ displayName: w.displayName || w.name || w["package"],
3792
+ status: "pending"
3793
+ };
3794
+ }));
3795
+ setProgressComplete(false);
3796
+ setShowProgressModal(true);
3797
+
3798
+ // Register progress listener
3799
+ if (cleanupProgressRef.current) cleanupProgressRef.current();
3800
+ cleanupProgressRef.current = (_window$mainApi2 = window.mainApi) === null || _window$mainApi2 === void 0 || (_window$mainApi2 = _window$mainApi2.dashboardConfig) === null || _window$mainApi2 === void 0 || (_window$mainApi2$onIn = _window$mainApi2.onInstallProgress) === null || _window$mainApi2$onIn === void 0 ? void 0 : _window$mainApi2$onIn.call(_window$mainApi2, function (data) {
3801
+ setProgressWidgets(function (prev) {
3802
+ var next = _toConsumableArray(prev);
3803
+ if (data.index >= 0 && data.index < next.length) {
3804
+ next[data.index] = _objectSpread$D(_objectSpread$D({}, next[data.index]), {}, {
3805
+ status: data.status,
3806
+ error: data.error || null
3807
+ });
3808
+ }
3809
+ return next;
3810
+ });
3811
+ });
3812
+ }
3673
3813
  _context.prev = 2;
3674
3814
  _context.next = 3;
3675
3815
  return window.mainApi.dashboardConfig.installDashboardFromRegistry(appId, pkg.name);
@@ -3679,33 +3819,52 @@ var RegistryDashboardDetail = function RegistryDashboardDetail(_ref) {
3679
3819
  _context.next = 4;
3680
3820
  break;
3681
3821
  }
3682
- // Auth needed — show inline auth prompt (DASH-135)
3822
+ // Auth needed — close progress modal, show inline auth prompt
3823
+ setShowProgressModal(false);
3683
3824
  setIsInstalling(false);
3684
3825
  setInstallResult({
3685
3826
  status: "auth",
3686
3827
  message: result.error || "Sign in to install this dashboard."
3687
3828
  });
3829
+ if (cleanupProgressRef.current) {
3830
+ cleanupProgressRef.current();
3831
+ cleanupProgressRef.current = null;
3832
+ }
3688
3833
  return _context.abrupt("return");
3689
3834
  case 4:
3690
- setInstallResult({
3691
- status: result !== null && result !== void 0 && result.success ? "success" : "error",
3692
- message: result !== null && result !== void 0 && result.success ? "Dashboard \"".concat(((_result$workspace = result.workspace) === null || _result$workspace === void 0 ? void 0 : _result$workspace.name) || pkg.name, "\" installed successfully.") : (result === null || result === void 0 ? void 0 : result.error) || "Installation failed."
3693
- });
3694
- if (result !== null && result !== void 0 && result.success && onInstallComplete) {
3695
- onInstallComplete(result);
3835
+ // Store result for use when modal closes
3836
+ progressResultRef.current = result;
3837
+ setProgressComplete(true);
3838
+
3839
+ // If no progress modal was shown, apply result directly
3840
+ if (deps.length === 0) {
3841
+ setInstallResult({
3842
+ status: result !== null && result !== void 0 && result.success ? "success" : "error",
3843
+ message: result !== null && result !== void 0 && result.success ? "Dashboard \"".concat(((_result$workspace2 = result.workspace) === null || _result$workspace2 === void 0 ? void 0 : _result$workspace2.name) || pkg.name, "\" installed successfully.") : (result === null || result === void 0 ? void 0 : result.error) || "Installation failed."
3844
+ });
3845
+ if (result !== null && result !== void 0 && result.success && onInstallComplete) {
3846
+ onInstallComplete(result);
3847
+ }
3696
3848
  }
3697
3849
  _context.next = 6;
3698
3850
  break;
3699
3851
  case 5:
3700
3852
  _context.prev = 5;
3701
3853
  _t = _context["catch"](2);
3702
- setInstallResult({
3703
- status: "error",
3704
- message: _t.message || "Failed to install dashboard."
3705
- });
3854
+ setProgressComplete(true);
3855
+ if (deps.length === 0) {
3856
+ setInstallResult({
3857
+ status: "error",
3858
+ message: _t.message || "Failed to install dashboard."
3859
+ });
3860
+ }
3706
3861
  case 6:
3707
3862
  _context.prev = 6;
3708
3863
  setIsInstalling(false);
3864
+ if (cleanupProgressRef.current) {
3865
+ cleanupProgressRef.current();
3866
+ cleanupProgressRef.current = null;
3867
+ }
3709
3868
  return _context.finish(6);
3710
3869
  case 7:
3711
3870
  case "end":
@@ -3715,6 +3874,20 @@ var RegistryDashboardDetail = function RegistryDashboardDetail(_ref) {
3715
3874
  }));
3716
3875
  return _handleInstall.apply(this, arguments);
3717
3876
  }
3877
+ var handleProgressDone = React.useCallback(function () {
3878
+ setShowProgressModal(false);
3879
+ var result = progressResultRef.current;
3880
+ if (result) {
3881
+ var _result$workspace;
3882
+ setInstallResult({
3883
+ status: result.success ? "success" : "error",
3884
+ message: result.success ? "Dashboard \"".concat(((_result$workspace = result.workspace) === null || _result$workspace === void 0 ? void 0 : _result$workspace.name) || pkg.name, "\" installed successfully.") : result.error || "Installation failed."
3885
+ });
3886
+ if (result.success && onInstallComplete) {
3887
+ onInstallComplete(result);
3888
+ }
3889
+ }
3890
+ }, [pkg.name, onInstallComplete]);
3718
3891
  function handleSignIn() {
3719
3892
  return _handleSignIn.apply(this, arguments);
3720
3893
  }
@@ -4096,6 +4269,12 @@ var RegistryDashboardDetail = function RegistryDashboardDetail(_ref) {
4096
4269
  onClick: handleInstall,
4097
4270
  disabled: isInstalling
4098
4271
  })
4272
+ }), /*#__PURE__*/jsxRuntime.jsx(InstallProgressModal, {
4273
+ isOpen: showProgressModal,
4274
+ setIsOpen: setShowProgressModal,
4275
+ widgets: progressWidgets,
4276
+ isComplete: progressComplete,
4277
+ onDone: handleProgressDone
4099
4278
  })]
4100
4279
  });
4101
4280
  };
@@ -38308,7 +38487,10 @@ var DashboardsSection = function DashboardsSection(_ref) {
38308
38487
  setInstallMode(null);
38309
38488
  setViewMode("grouped");
38310
38489
  },
38311
- appId: appId
38490
+ appId: appId,
38491
+ onInstallComplete: function onInstallComplete() {
38492
+ onReloadWorkspaces && onReloadWorkspaces();
38493
+ }
38312
38494
  });
38313
38495
  } else if (selectedWorkspace) {
38314
38496
  detailContent = /*#__PURE__*/jsxRuntime.jsx(DashboardDetail, {