@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.esm.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import _defineProperty from '@babel/runtime/helpers/defineProperty';
2
2
  import * as DashReact from '@trops/dash-react';
3
- import { isObject, ThemeContext, deepCopy, MainSection, getUUID, getStylesForItem, themeObjects, Heading, SearchInput, ButtonIcon, SubHeading3, InputText, Button, FontAwesomeIcon, Tag, Sidebar, Paragraph, Modal, Panel, Stepper, Tag2, Tag3, Card2, Card3, Heading3, MenuItem3, FormLabel, SelectMenu, Switch, SelectInput, CodeEditorInline, SettingsModal, SubHeading2, tailwindHeightFractions, Menu3, Panel3, DropdownPanel, MenuItem2, ButtonIcon2, DragComponent, ConfirmationModal, DropComponent, getStyleName, capitalizeFirstLetter, colorTypes, getCSSStyleForClassname, Panel2, Heading2, SubHeading, Paragraph2, Paragraph3, Button2, Button3, MenuItem, ButtonIcon3, DashPanel, colorNames, shades, themeVariants, Tabs3, DataList, Checkbox, StatCard, Card, Tabs, Accordion, Alert, Toast, ProgressBar, Toggle, Breadcrumbs, Tabs2, Accordion2, Alert2, Toast2, ProgressBar2, Toggle2, Breadcrumbs2, Accordion3, Alert3, Toast3, ProgressBar3, Toggle3, Breadcrumbs3, ThemeFromUrlPane, TextArea, Icon2, AlgoliaSearchBox, CommandPalette, EmptyState, Navbar, withRouter, Menu as Menu$1 } from '@trops/dash-react';
3
+ import { isObject, ThemeContext, deepCopy, MainSection, getUUID, getStylesForItem, themeObjects, Heading, SearchInput, ButtonIcon, SubHeading3, InputText, Button, FontAwesomeIcon, Tag, Modal, Sidebar, Paragraph, Panel, Stepper, Tag2, Tag3, Card2, Card3, Heading3, MenuItem3, FormLabel, SelectMenu, Switch, SelectInput, CodeEditorInline, SettingsModal, SubHeading2, tailwindHeightFractions, Menu3, Panel3, DropdownPanel, MenuItem2, ButtonIcon2, DragComponent, ConfirmationModal, DropComponent, getStyleName, capitalizeFirstLetter, colorTypes, getCSSStyleForClassname, Panel2, Heading2, SubHeading, Paragraph2, Paragraph3, Button2, Button3, MenuItem, ButtonIcon3, DashPanel, colorNames, shades, themeVariants, Tabs3, DataList, Checkbox, StatCard, Card, Tabs, Accordion, Alert, Toast, ProgressBar, Toggle, Breadcrumbs, Tabs2, Accordion2, Alert2, Toast2, ProgressBar2, Toggle2, Breadcrumbs2, Accordion3, Alert3, Toast3, ProgressBar3, Toggle3, Breadcrumbs3, ThemeFromUrlPane, TextArea, Icon2, AlgoliaSearchBox, CommandPalette, EmptyState, Navbar, withRouter, Menu as Menu$1 } from '@trops/dash-react';
4
4
  export * from '@trops/dash-react';
5
5
  export { ThemeContext } from '@trops/dash-react';
6
6
  import _typeof from '@babel/runtime/helpers/typeof';
@@ -3556,6 +3556,102 @@ var StarRating = function StarRating(_ref) {
3556
3556
  });
3557
3557
  };
3558
3558
 
3559
+ var InstallProgressModal = function InstallProgressModal(_ref) {
3560
+ var isOpen = _ref.isOpen,
3561
+ setIsOpen = _ref.setIsOpen,
3562
+ _ref$widgets = _ref.widgets,
3563
+ widgets = _ref$widgets === void 0 ? [] : _ref$widgets,
3564
+ _ref$isComplete = _ref.isComplete,
3565
+ isComplete = _ref$isComplete === void 0 ? false : _ref$isComplete,
3566
+ onDone = _ref.onDone;
3567
+ var _useContext = useContext(ThemeContext),
3568
+ currentTheme = _useContext.currentTheme;
3569
+ var panelStyles = getStylesForItem(themeObjects.PANEL, currentTheme, {
3570
+ grow: false
3571
+ });
3572
+
3573
+ // Prevent dismissal while installation is in progress
3574
+ var guardedSetIsOpen = function guardedSetIsOpen(val) {
3575
+ if (isComplete) setIsOpen(val);
3576
+ };
3577
+ var doneCount = widgets.filter(function (w) {
3578
+ return w.status === "installed" || w.status === "already-installed" || w.status === "failed";
3579
+ }).length;
3580
+ function statusIcon(status) {
3581
+ switch (status) {
3582
+ case "downloading":
3583
+ return /*#__PURE__*/jsx("div", {
3584
+ className: "animate-spin rounded-full h-4 w-4 border-b-2 border-blue-400 flex-shrink-0"
3585
+ });
3586
+ case "installed":
3587
+ case "already-installed":
3588
+ return /*#__PURE__*/jsx(FontAwesomeIcon, {
3589
+ icon: "circle-check",
3590
+ className: "h-4 w-4 text-green-400 flex-shrink-0"
3591
+ });
3592
+ case "failed":
3593
+ return /*#__PURE__*/jsx(FontAwesomeIcon, {
3594
+ icon: "circle-xmark",
3595
+ className: "h-4 w-4 text-red-400 flex-shrink-0"
3596
+ });
3597
+ default:
3598
+ // pending
3599
+ return /*#__PURE__*/jsx(FontAwesomeIcon, {
3600
+ icon: "clock",
3601
+ className: "h-4 w-4 opacity-30 flex-shrink-0"
3602
+ });
3603
+ }
3604
+ }
3605
+ return /*#__PURE__*/jsx(Modal, {
3606
+ isOpen: isOpen,
3607
+ setIsOpen: guardedSetIsOpen,
3608
+ width: "w-[440px]",
3609
+ height: "auto",
3610
+ children: /*#__PURE__*/jsxs("div", {
3611
+ className: "flex flex-col rounded-lg overflow-hidden ".concat(panelStyles.backgroundColor || "bg-gray-900", " ").concat(panelStyles.textColor || "text-gray-200"),
3612
+ children: [/*#__PURE__*/jsx("div", {
3613
+ className: "px-5 pt-5 pb-3",
3614
+ children: /*#__PURE__*/jsx("h3", {
3615
+ className: "text-sm font-semibold",
3616
+ children: isComplete ? "Installation Complete" : "Installing widget ".concat(doneCount + 1, " of ").concat(widgets.length, "...")
3617
+ })
3618
+ }), /*#__PURE__*/jsx("div", {
3619
+ className: "px-5 pb-3 space-y-1.5 max-h-64 overflow-y-auto",
3620
+ children: widgets.map(function (w, idx) {
3621
+ return /*#__PURE__*/jsxs("div", {
3622
+ children: [/*#__PURE__*/jsxs("div", {
3623
+ className: "flex items-center gap-2.5 p-2 rounded ".concat(currentTheme["bg-primary-medium"] || "bg-white/5"),
3624
+ children: [statusIcon(w.status), /*#__PURE__*/jsx("span", {
3625
+ className: "text-sm flex-1 truncate",
3626
+ children: w.displayName
3627
+ }), /*#__PURE__*/jsx("span", {
3628
+ className: "text-[10px] opacity-40",
3629
+ children: w.status === "already-installed" ? "Already installed" : w.status === "downloading" ? "Downloading..." : w.status === "installed" ? "Installed" : w.status === "failed" ? "Failed" : "Pending"
3630
+ })]
3631
+ }), w.status === "failed" && w.error && /*#__PURE__*/jsx("p", {
3632
+ className: "text-[10px] text-red-400/80 mt-0.5 ml-7 truncate",
3633
+ children: w.error
3634
+ })]
3635
+ }, idx);
3636
+ })
3637
+ }), /*#__PURE__*/jsx("div", {
3638
+ className: "flex items-center justify-end px-5 py-3 border-t ".concat(currentTheme["border-primary-medium"] || "border-white/10"),
3639
+ children: /*#__PURE__*/jsx(Button, {
3640
+ title: "Done",
3641
+ bgColor: isComplete ? "bg-blue-600" : "bg-gray-700",
3642
+ hoverBackgroundColor: isComplete ? "hover:bg-blue-700" : "",
3643
+ textSize: "text-sm",
3644
+ padding: "py-1.5 px-4",
3645
+ onClick: function onClick() {
3646
+ if (isComplete && onDone) onDone();
3647
+ },
3648
+ disabled: !isComplete
3649
+ })
3650
+ })]
3651
+ })
3652
+ });
3653
+ };
3654
+
3559
3655
  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; } } }; }
3560
3656
  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; } }
3561
3657
  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; }
@@ -3598,15 +3694,30 @@ var RegistryDashboardDetail = function RegistryDashboardDetail(_ref) {
3598
3694
  _useState12 = _slicedToArray(_useState11, 2),
3599
3695
  authError = _useState12[0],
3600
3696
  setAuthError = _useState12[1];
3697
+ var _useState13 = useState(false),
3698
+ _useState14 = _slicedToArray(_useState13, 2),
3699
+ showProgressModal = _useState14[0],
3700
+ setShowProgressModal = _useState14[1];
3701
+ var _useState15 = useState([]),
3702
+ _useState16 = _slicedToArray(_useState15, 2),
3703
+ progressWidgets = _useState16[0],
3704
+ setProgressWidgets = _useState16[1];
3705
+ var _useState17 = useState(false),
3706
+ _useState18 = _slicedToArray(_useState17, 2),
3707
+ progressComplete = _useState18[0],
3708
+ setProgressComplete = _useState18[1];
3709
+ var progressResultRef = useRef(null);
3601
3710
  var pollIntervalRef = useRef(null);
3711
+ var cleanupProgressRef = useRef(null);
3602
3712
  var pkg = dashboardPackage;
3603
3713
  if (!pkg) return null;
3604
3714
 
3605
- // Clean up polling on unmount
3715
+ // Clean up polling and progress listener on unmount
3606
3716
  // eslint-disable-next-line react-hooks/rules-of-hooks
3607
3717
  useEffect(function () {
3608
3718
  return function () {
3609
3719
  if (pollIntervalRef.current) clearInterval(pollIntervalRef.current);
3720
+ if (cleanupProgressRef.current) cleanupProgressRef.current();
3610
3721
  };
3611
3722
  }, []);
3612
3723
 
@@ -3635,10 +3746,10 @@ var RegistryDashboardDetail = function RegistryDashboardDetail(_ref) {
3635
3746
  }, [pkg.name]);
3636
3747
  function handleInstall() {
3637
3748
  return _handleInstall.apply(this, arguments);
3638
- }
3749
+ } // eslint-disable-next-line react-hooks/rules-of-hooks
3639
3750
  function _handleInstall() {
3640
3751
  _handleInstall = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
3641
- var _result$workspace, result, _t;
3752
+ var deps, _window$mainApi2, _window$mainApi2$onIn, result, _result$workspace2, _t;
3642
3753
  return _regeneratorRuntime.wrap(function (_context) {
3643
3754
  while (1) switch (_context.prev = _context.next) {
3644
3755
  case 0:
@@ -3652,6 +3763,35 @@ var RegistryDashboardDetail = function RegistryDashboardDetail(_ref) {
3652
3763
  setInstallResult(null);
3653
3764
  setAuthFlow(null);
3654
3765
  setAuthError(null);
3766
+
3767
+ // Initialize progress modal from widget deps
3768
+ deps = widgetDeps.length > 0 ? widgetDeps : [];
3769
+ if (deps.length > 0) {
3770
+ setProgressWidgets(deps.map(function (w) {
3771
+ return {
3772
+ packageName: w["package"] || w.name,
3773
+ displayName: w.displayName || w.name || w["package"],
3774
+ status: "pending"
3775
+ };
3776
+ }));
3777
+ setProgressComplete(false);
3778
+ setShowProgressModal(true);
3779
+
3780
+ // Register progress listener
3781
+ if (cleanupProgressRef.current) cleanupProgressRef.current();
3782
+ 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) {
3783
+ setProgressWidgets(function (prev) {
3784
+ var next = _toConsumableArray(prev);
3785
+ if (data.index >= 0 && data.index < next.length) {
3786
+ next[data.index] = _objectSpread$D(_objectSpread$D({}, next[data.index]), {}, {
3787
+ status: data.status,
3788
+ error: data.error || null
3789
+ });
3790
+ }
3791
+ return next;
3792
+ });
3793
+ });
3794
+ }
3655
3795
  _context.prev = 2;
3656
3796
  _context.next = 3;
3657
3797
  return window.mainApi.dashboardConfig.installDashboardFromRegistry(appId, pkg.name);
@@ -3661,33 +3801,52 @@ var RegistryDashboardDetail = function RegistryDashboardDetail(_ref) {
3661
3801
  _context.next = 4;
3662
3802
  break;
3663
3803
  }
3664
- // Auth needed — show inline auth prompt (DASH-135)
3804
+ // Auth needed — close progress modal, show inline auth prompt
3805
+ setShowProgressModal(false);
3665
3806
  setIsInstalling(false);
3666
3807
  setInstallResult({
3667
3808
  status: "auth",
3668
3809
  message: result.error || "Sign in to install this dashboard."
3669
3810
  });
3811
+ if (cleanupProgressRef.current) {
3812
+ cleanupProgressRef.current();
3813
+ cleanupProgressRef.current = null;
3814
+ }
3670
3815
  return _context.abrupt("return");
3671
3816
  case 4:
3672
- setInstallResult({
3673
- status: result !== null && result !== void 0 && result.success ? "success" : "error",
3674
- 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."
3675
- });
3676
- if (result !== null && result !== void 0 && result.success && onInstallComplete) {
3677
- onInstallComplete(result);
3817
+ // Store result for use when modal closes
3818
+ progressResultRef.current = result;
3819
+ setProgressComplete(true);
3820
+
3821
+ // If no progress modal was shown, apply result directly
3822
+ if (deps.length === 0) {
3823
+ setInstallResult({
3824
+ status: result !== null && result !== void 0 && result.success ? "success" : "error",
3825
+ 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."
3826
+ });
3827
+ if (result !== null && result !== void 0 && result.success && onInstallComplete) {
3828
+ onInstallComplete(result);
3829
+ }
3678
3830
  }
3679
3831
  _context.next = 6;
3680
3832
  break;
3681
3833
  case 5:
3682
3834
  _context.prev = 5;
3683
3835
  _t = _context["catch"](2);
3684
- setInstallResult({
3685
- status: "error",
3686
- message: _t.message || "Failed to install dashboard."
3687
- });
3836
+ setProgressComplete(true);
3837
+ if (deps.length === 0) {
3838
+ setInstallResult({
3839
+ status: "error",
3840
+ message: _t.message || "Failed to install dashboard."
3841
+ });
3842
+ }
3688
3843
  case 6:
3689
3844
  _context.prev = 6;
3690
3845
  setIsInstalling(false);
3846
+ if (cleanupProgressRef.current) {
3847
+ cleanupProgressRef.current();
3848
+ cleanupProgressRef.current = null;
3849
+ }
3691
3850
  return _context.finish(6);
3692
3851
  case 7:
3693
3852
  case "end":
@@ -3697,6 +3856,20 @@ var RegistryDashboardDetail = function RegistryDashboardDetail(_ref) {
3697
3856
  }));
3698
3857
  return _handleInstall.apply(this, arguments);
3699
3858
  }
3859
+ var handleProgressDone = useCallback(function () {
3860
+ setShowProgressModal(false);
3861
+ var result = progressResultRef.current;
3862
+ if (result) {
3863
+ var _result$workspace;
3864
+ setInstallResult({
3865
+ status: result.success ? "success" : "error",
3866
+ 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."
3867
+ });
3868
+ if (result.success && onInstallComplete) {
3869
+ onInstallComplete(result);
3870
+ }
3871
+ }
3872
+ }, [pkg.name, onInstallComplete]);
3700
3873
  function handleSignIn() {
3701
3874
  return _handleSignIn.apply(this, arguments);
3702
3875
  }
@@ -4078,6 +4251,12 @@ var RegistryDashboardDetail = function RegistryDashboardDetail(_ref) {
4078
4251
  onClick: handleInstall,
4079
4252
  disabled: isInstalling
4080
4253
  })
4254
+ }), /*#__PURE__*/jsx(InstallProgressModal, {
4255
+ isOpen: showProgressModal,
4256
+ setIsOpen: setShowProgressModal,
4257
+ widgets: progressWidgets,
4258
+ isComplete: progressComplete,
4259
+ onDone: handleProgressDone
4081
4260
  })]
4082
4261
  });
4083
4262
  };
@@ -38290,7 +38469,10 @@ var DashboardsSection = function DashboardsSection(_ref) {
38290
38469
  setInstallMode(null);
38291
38470
  setViewMode("grouped");
38292
38471
  },
38293
- appId: appId
38472
+ appId: appId,
38473
+ onInstallComplete: function onInstallComplete() {
38474
+ onReloadWorkspaces && onReloadWorkspaces();
38475
+ }
38294
38476
  });
38295
38477
  } else if (selectedWorkspace) {
38296
38478
  detailContent = /*#__PURE__*/jsx(DashboardDetail, {