@digital-ai/dot-components 3.22.0 → 3.23.0

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/index.esm.js CHANGED
@@ -9034,7 +9034,7 @@ class DashboardsService {
9034
9034
  * @param sort Sort ordering to apply to the query.
9035
9035
  * @param filter List of filters (each filter is a separate query param, and they are OR'ed).
9036
9036
  *
9037
- * * **Filterable field names**: author_fullname, author_id, bi_type, categories, created_dt, description, external_embedding_id, external_id, id, is_ootb_dashboard, lifecycle_state, name, target_apps, updated_by_fullname, updated_by_id, updated_dt
9037
+ * * **Filterable field names**: author_fullname, author_id, bi_type, categories, created_dt, description, external_embedding_id, external_id, id, is_ootb_dashboard, lifecycle_state, modified_parent_id, name, target_apps, updated_by_fullname, updated_by_id, updated_dt
9038
9038
  * * **Searchable field names**: author_fullname, categories, description, name, updated_by_fullname
9039
9039
  *
9040
9040
  * @param favorite Boolean flag to only return dashboards marked as favorites.
@@ -9111,19 +9111,24 @@ class DashboardsService {
9111
9111
  * Get one Dashboard definition.
9112
9112
  * Return a single Dashboard definition, selected by ID.
9113
9113
  * @param dashboardId
9114
+ * @param viewModified Return the dashboard with modified changes if they exist for this user.
9114
9115
  * @returns DashboardView OK
9115
9116
  * @returns Error Default error response
9116
9117
  * @throws ApiError
9117
9118
  */
9118
- static getDashboardsService1(dashboardId) {
9119
+ static getDashboardsService1(dashboardId, viewModified = false) {
9119
9120
  return __awaiter(this, void 0, void 0, function* () {
9120
9121
  const result = yield request({
9121
9122
  method: 'GET',
9122
9123
  path: `/metadata/bi/dashboards/${dashboardId}`,
9124
+ query: {
9125
+ view_modified: viewModified
9126
+ },
9123
9127
  errors: {
9124
9128
  400: `An unknown parameter was specified.`,
9125
9129
  401: `Could not resolve a valid Tenant from the provided API Token.`,
9126
- 404: `The dashboard could not be found.`
9130
+ 404: `The dashboard could not be found.`,
9131
+ 422: `Unprocessable Entity`
9127
9132
  }
9128
9133
  });
9129
9134
  return result.body;
@@ -9207,6 +9212,58 @@ class DashboardsService {
9207
9212
  return result.body;
9208
9213
  });
9209
9214
  }
9215
+ /**
9216
+ * Publish modifications to a dashboard
9217
+ * Publish modifications to a dashboard
9218
+ * @param dashboardId
9219
+ * @param requestBody
9220
+ * @param isSync Sync the dashboard with BI
9221
+ * @returns DashboardView Dashboard published.
9222
+ * @returns Error Default error response
9223
+ * @throws ApiError
9224
+ */
9225
+ static postDashboardsService1(dashboardId, requestBody, isSync = null) {
9226
+ return __awaiter(this, void 0, void 0, function* () {
9227
+ const result = yield request({
9228
+ method: 'POST',
9229
+ path: `/metadata/bi/dashboards/${dashboardId}/publish`,
9230
+ query: {
9231
+ is_sync: isSync
9232
+ },
9233
+ body: requestBody,
9234
+ mediaType: 'application/json',
9235
+ errors: {
9236
+ 400: `The provided data is not valid.`,
9237
+ 401: `Could not resolve a valid Tenant from the provided API Token.`,
9238
+ 404: `The dashboard could not be found.`,
9239
+ 422: `Unprocessable Entity`
9240
+ }
9241
+ });
9242
+ return result.body;
9243
+ });
9244
+ }
9245
+ /**
9246
+ * Revert modifications to a dashboard
9247
+ * Revert modifications to a dashboard
9248
+ * @param dashboardId
9249
+ * @returns DashboardView Dashboard changes reverted.
9250
+ * @returns Error Default error response
9251
+ * @throws ApiError
9252
+ */
9253
+ static postDashboardsService2(dashboardId) {
9254
+ return __awaiter(this, void 0, void 0, function* () {
9255
+ const result = yield request({
9256
+ method: 'POST',
9257
+ path: `/metadata/bi/dashboards/${dashboardId}/revert`,
9258
+ errors: {
9259
+ 400: `The provided data is not valid.`,
9260
+ 401: `Could not resolve a valid Tenant from the provided API Token.`,
9261
+ 404: `The dashboard could not be found.`
9262
+ }
9263
+ });
9264
+ return result.body;
9265
+ });
9266
+ }
9210
9267
  /**
9211
9268
  * Create a copy of existing dashboard
9212
9269
  * Create a copy of existing dashboard
@@ -9216,7 +9273,7 @@ class DashboardsService {
9216
9273
  * @returns Error Default error response
9217
9274
  * @throws ApiError
9218
9275
  */
9219
- static postDashboardsService1(dashboardId, requestBody) {
9276
+ static postDashboardsService3(dashboardId, requestBody) {
9220
9277
  return __awaiter(this, void 0, void 0, function* () {
9221
9278
  const result = yield request({
9222
9279
  method: 'POST',
@@ -9240,7 +9297,7 @@ class DashboardsService {
9240
9297
  * @returns Error Default error response
9241
9298
  * @throws ApiError
9242
9299
  */
9243
- static postDashboardsService2(dashboardId) {
9300
+ static postDashboardsService4(dashboardId) {
9244
9301
  return __awaiter(this, void 0, void 0, function* () {
9245
9302
  const result = yield request({
9246
9303
  method: 'POST',
@@ -9428,15 +9485,35 @@ class HelpContentService {
9428
9485
  }
9429
9486
 
9430
9487
  function DotDashboardStatusPill({
9431
- status
9488
+ dashboard,
9489
+ currentUser
9432
9490
  }) {
9433
- if (status === DashboardView.lifecycle_state.DRAFT) {
9491
+ if (dashboard.lifecycle_state === DashboardView.lifecycle_state.DRAFT) {
9434
9492
  return jsx(DotPill, {
9435
9493
  label: "Draft",
9436
9494
  size: "small",
9437
9495
  variant: "outlined",
9438
9496
  status: "in-progress"
9439
9497
  });
9498
+ } else if (dashboard.lifecycle_state === DashboardView.lifecycle_state.PUBLISHED && dashboard.is_being_modified && currentUser) {
9499
+ if (dashboard.modified_author_id === currentUser.id) {
9500
+ return jsx(DotPill, {
9501
+ label: "Edit in progress",
9502
+ size: "small",
9503
+ variant: "outlined",
9504
+ status: "success"
9505
+ });
9506
+ } else {
9507
+ return jsx(DotPill, {
9508
+ label: "Published",
9509
+ icon: jsx(DotIcon, {
9510
+ iconId: "lock"
9511
+ }),
9512
+ size: "small",
9513
+ variant: "outlined",
9514
+ status: "success"
9515
+ });
9516
+ }
9440
9517
  } else {
9441
9518
  return jsx(DotPill, {
9442
9519
  status: "success",
@@ -9466,7 +9543,7 @@ const dashboard1 = {
9466
9543
  lifecycle_state: DashboardView.lifecycle_state.DRAFT,
9467
9544
  application_instances: [],
9468
9545
  categories: [],
9469
- bi_type: DashboardView.bi_type.SUPERSET,
9546
+ bi_type: DashboardView.bi_type.MICROSTRATEGY,
9470
9547
  is_ootb_dashboard: false,
9471
9548
  thumbnail: '',
9472
9549
  external_object: {
@@ -9476,7 +9553,8 @@ const dashboard1 = {
9476
9553
  help_content_id: helpContent.id,
9477
9554
  filter_configuration: [],
9478
9555
  favorite: false,
9479
- updated_dt: '2023-11-22T06:42:07.952000+00:00'
9556
+ updated_dt: '2023-11-22T06:42:07.952000+00:00',
9557
+ is_being_modified: false
9480
9558
  };
9481
9559
  const dashboard2 = {
9482
9560
  author_fullname: 'Dashboard2 Author',
@@ -9578,6 +9656,36 @@ const dashboard4 = {
9578
9656
  favorite: false,
9579
9657
  updated_dt: '2023-11-21T04:42:07.951000+00:00'
9580
9658
  });
9659
+ // Dashboard with in-progress edits
9660
+ ({
9661
+ author_fullname: 'Dashboard6 Author',
9662
+ author_id: 'id6a',
9663
+ target_apps: ['AGILITY'],
9664
+ external_id: '6',
9665
+ name: 'Test dashboard 6',
9666
+ description: '',
9667
+ dashboard_url: 'https://test.com',
9668
+ server_url: 'https://test.com',
9669
+ external_embedding_id: null,
9670
+ created_dt: '2023-11-22T06:42:07.872000+00:00',
9671
+ id: 'id6',
9672
+ lifecycle_state: DashboardView.lifecycle_state.PUBLISHED,
9673
+ application_instances: [],
9674
+ categories: [],
9675
+ bi_type: DashboardView.bi_type.MICROSTRATEGY,
9676
+ is_ootb_dashboard: false,
9677
+ thumbnail: '',
9678
+ external_object: {
9679
+ page_count: 3
9680
+ },
9681
+ embed_config: {},
9682
+ help_content_id: helpContent.id,
9683
+ filter_configuration: [],
9684
+ favorite: false,
9685
+ updated_dt: '2023-11-22T06:42:07.952000+00:00',
9686
+ is_being_modified: true,
9687
+ modified_author_id: 'id123'
9688
+ });
9581
9689
  const getCategoriesMock = {
9582
9690
  categories: {
9583
9691
  AGILITY: ['Scrum Master', 'DevOps Manager', 'Release Train Engineer', 'Agility Analytics'],
@@ -9789,7 +9897,7 @@ const DotMetadataApiProvider = ({
9789
9897
  },
9790
9898
  duplicateDashboard: (dashboardId, dashboard) => {
9791
9899
  setAccountIdHeader(accountId);
9792
- return cancelablePromise(DashboardsService.postDashboardsService1(dashboardId, dashboard)).then(response => {
9900
+ return cancelablePromise(DashboardsService.postDashboardsService3(dashboardId, dashboard)).then(response => {
9793
9901
  setDashboardsError(null);
9794
9902
  setMetadata(null);
9795
9903
  if (dashboards) {
@@ -9804,10 +9912,33 @@ const DotMetadataApiProvider = ({
9804
9912
  return null;
9805
9913
  });
9806
9914
  },
9915
+ publishDashboardChanges: (dashboardId, dashboard, isSync) => __awaiter(void 0, void 0, void 0, function* () {
9916
+ setAccountIdHeader(accountId);
9917
+ return cancelablePromise(DashboardsService.postDashboardsService1(dashboardId, dashboard, isSync)).then(response => {
9918
+ setDashboardsError(null);
9919
+ setDashboards(orig => handleUpdateDashboard(orig, response));
9920
+ return response;
9921
+ }).catch(error => setDashboardsError(error));
9922
+ }),
9923
+ revertDashboardChanges: dashboardId => __awaiter(void 0, void 0, void 0, function* () {
9924
+ setAccountIdHeader(accountId);
9925
+ return cancelablePromise(DashboardsService.postDashboardsService2(dashboardId)).then(response => {
9926
+ setDashboardsError(null);
9927
+ setDashboards(orig => handleUpdateDashboard(orig, response));
9928
+ return response;
9929
+ }).catch(error => setDashboardsError(error));
9930
+ }),
9931
+ getDashboard: (dashboardId, viewModified) => {
9932
+ setAccountIdHeader(accountOverrideId);
9933
+ return cancelablePromise(viewModified === undefined ? DashboardsService.getDashboardsService1(dashboardId) : DashboardsService.getDashboardsService1(dashboardId, viewModified)).then(response => {
9934
+ setDashboardsError(null);
9935
+ return response;
9936
+ }).catch(error => setDashboardsError(error));
9937
+ },
9807
9938
  favoriteDashboard: (dashboardId, favoriteValue) => {
9808
9939
  setAccountIdHeader(accountId);
9809
9940
  if (favoriteValue) {
9810
- return cancelablePromise(DashboardsService.postDashboardsService2(dashboardId)).then(response => {
9941
+ return cancelablePromise(DashboardsService.postDashboardsService4(dashboardId)).then(response => {
9811
9942
  setDashboardsError(null);
9812
9943
  setDashboards(orig => handleUpdateDashboard(orig, response));
9813
9944
  return response;
@@ -10310,7 +10441,8 @@ const DotDashboardDetailsView = ({
10310
10441
  onFavorite,
10311
10442
  open,
10312
10443
  yOffset = 56,
10313
- zIndex = 990
10444
+ zIndex = 990,
10445
+ currentUser
10314
10446
  }) => {
10315
10447
  var _a, _b;
10316
10448
  const rootClasses = useStylesWithRootClass(rootClassName$E, className);
@@ -10395,7 +10527,8 @@ const DotDashboardDetailsView = ({
10395
10527
  className: "dashboard-details-status",
10396
10528
  label: "Status",
10397
10529
  children: jsx(DotDashboardStatusPill, {
10398
- status: dashboard.lifecycle_state
10530
+ dashboard: dashboard,
10531
+ currentUser: currentUser ? currentUser : null
10399
10532
  })
10400
10533
  }), jsx(DashboardDetailsField, {
10401
10534
  className: "dashboard-details-category",
@@ -10439,9 +10572,10 @@ const DotDashboardDetails = _a => {
10439
10572
  var {
10440
10573
  dashboard,
10441
10574
  onClose,
10442
- onFavorite
10575
+ onFavorite,
10576
+ currentUser
10443
10577
  } = _a,
10444
- commonProps = __rest(_a, ["dashboard", "onClose", "onFavorite"]);
10578
+ commonProps = __rest(_a, ["dashboard", "onClose", "onFavorite", "currentUser"]);
10445
10579
  const [_openedDashboard, _setOpenedDashboard] = useState(dashboard);
10446
10580
  const metadataApiContext = useDotMetadataApiContext();
10447
10581
  const {
@@ -10481,7 +10615,8 @@ const DotDashboardDetails = _a => {
10481
10615
  dashboard: openedDashboard,
10482
10616
  open: true,
10483
10617
  onFavorite: favoriteHandler,
10484
- onClose: closeHandler
10618
+ onClose: closeHandler,
10619
+ currentUser: currentUser ? currentUser : null
10485
10620
  }));
10486
10621
  }
10487
10622
  return null;
@@ -10575,7 +10710,14 @@ const DotInputSelect = ({
10575
10710
  return typeof option === 'string' ? option : option.option;
10576
10711
  };
10577
10712
  const getValue = option => {
10578
- return typeof option === 'string' ? option : (option === null || option === void 0 ? void 0 : option.value) || option.option;
10713
+ if (typeof option === 'string') {
10714
+ return option;
10715
+ }
10716
+ // Allow empty string as a value. This is useful when the user wants to select an empty option.
10717
+ if ((option === null || option === void 0 ? void 0 : option.value) === '') {
10718
+ return option.value;
10719
+ }
10720
+ return (option === null || option === void 0 ? void 0 : option.value) || option.option;
10579
10721
  };
10580
10722
  return jsxs("div", {
10581
10723
  className: className,
@@ -11136,7 +11278,8 @@ function ActivePublishMessage({
11136
11278
  published,
11137
11279
  publishing,
11138
11280
  onChange,
11139
- requiresApplication
11281
+ requiresApplication,
11282
+ editInProgress
11140
11283
  }) {
11141
11284
  const [selectedApp, setSelectedApp] = useState(applicationList.length > 0 ? applicationList[0] : null);
11142
11285
  const [selectedCategories, setSelectedCategories] = useState([]);
@@ -11220,11 +11363,11 @@ function ActivePublishMessage({
11220
11363
  children: ["To view your newly published dashboard in", ' ', jsxs("strong", {
11221
11364
  children: ["\"", selectedApp.name, "\""]
11222
11365
  }), ", go to the", ' ', jsx("strong", {
11223
- children: "'Digital.ai Analytics'"
11366
+ children: "'Analytics'"
11224
11367
  }), " section and explore."]
11225
11368
  }) : jsxs(DotTypography, {
11226
11369
  children: ["To view your newly published dashboard, go to the", ' ', jsx("strong", {
11227
- children: "'Digital.ai Analytics'"
11370
+ children: "'Analytics'"
11228
11371
  }), " section and explore."]
11229
11372
  })]
11230
11373
  });
@@ -11303,9 +11446,9 @@ function ActivePublishMessage({
11303
11446
  value: selectedCategories,
11304
11447
  filterSelectedOptions: true
11305
11448
  }), requiresApplication && jsxs(DotTypography, {
11306
- children: ["You are about to publish ", jsxs("strong", {
11449
+ children: ["You are about to", ' ', editInProgress ? 'apply changes to ' : 'publish ', ' ', jsxs("strong", {
11307
11450
  children: ["\"", dashboardName, "\""]
11308
- }), ". Click", ' ', "the publish button to promote it to the selected instance."]
11451
+ }), ".", editInProgress ? ' Do you want to proceed with publishing these updates?' : ' Click the publish button to promote it to the selected instance.']
11309
11452
  })]
11310
11453
  })
11311
11454
  });
@@ -11361,7 +11504,8 @@ function DotDashboardPublishConfirm({
11361
11504
  dashboardToPublish,
11362
11505
  dashboardToUnpublish,
11363
11506
  onClose,
11364
- onStatusChanged
11507
+ onStatusChanged,
11508
+ currentUser
11365
11509
  }) {
11366
11510
  const [publishing, setPublishing] = useState(null);
11367
11511
  const [unpublishing, setUnpublishing] = useState(null);
@@ -11376,7 +11520,8 @@ function DotDashboardPublishConfirm({
11376
11520
  });
11377
11521
  const {
11378
11522
  updateDashboard,
11379
- dashboardsError
11523
+ dashboardsError,
11524
+ publishDashboardChanges
11380
11525
  } = useDotMetadataApiContext();
11381
11526
  const {
11382
11527
  cancelablePromise
@@ -11401,20 +11546,26 @@ function DotDashboardPublishConfirm({
11401
11546
  setUnpublished(false);
11402
11547
  }
11403
11548
  }, [dashboardToUnpublish]);
11549
+ const editInProgressByCurrentUser = dashboard => {
11550
+ return currentUser && dashboard.is_being_modified && dashboard.modified_author_id === currentUser.id;
11551
+ };
11404
11552
  const handlePublish = useCallback(() => {
11405
11553
  const patchDashboard = {
11406
11554
  lifecycle_state: DashboardView.lifecycle_state.PUBLISHED,
11407
11555
  application_instances: publishAppInstance ? [publishAppInstance.id] : [],
11408
11556
  categories: publishCategories
11409
11557
  };
11410
- setPublishing(cancelablePromise(updateDashboard(dashboardToPublish.id, patchDashboard).then(updatedDashboard => {
11558
+ // If we're publishing a dashboard that is being modified by the current user, we need to use the
11559
+ // publishDashboardChanges method to commit the changes to the published dashboard.
11560
+ const publishMethod = editInProgressByCurrentUser(dashboardToPublish) ? publishDashboardChanges : updateDashboard;
11561
+ setPublishing(cancelablePromise(publishMethod(dashboardToPublish.id, patchDashboard).then(updatedDashboard => {
11411
11562
  setPublished(true);
11412
11563
  onStatusChanged(updatedDashboard);
11413
11564
  enqueueMessage('Dashboard has been published!', 'success');
11414
11565
  }).catch(() => {
11415
11566
  setPublishing(null);
11416
11567
  })));
11417
- }, [dashboardToPublish, publishAppInstance, publishCategories, updateDashboard]);
11568
+ }, [dashboardToPublish, publishAppInstance, publishCategories, updateDashboard, publishDashboardChanges]);
11418
11569
  const handleCancelPublish = useCallback(() => {
11419
11570
  if (publishing !== null) {
11420
11571
  publishing.cancel();
@@ -11448,17 +11599,26 @@ function DotDashboardPublishConfirm({
11448
11599
  }
11449
11600
  return !(requiresCategories && publishCategories.length === 0);
11450
11601
  }, [publishAppInstance, publishCategories, requiresApplication, requiresCategories]);
11602
+ const getPublishButtonLabel = dashboard => {
11603
+ if (published) {
11604
+ return 'Got it';
11605
+ } else if (editInProgressByCurrentUser(dashboard)) {
11606
+ return 'Yes, publish changes';
11607
+ } else {
11608
+ return 'Publish';
11609
+ }
11610
+ };
11451
11611
  return jsxs(Fragment, {
11452
11612
  children: [dashboardToPublish !== null && jsx(DotDialog, {
11453
11613
  cancelButtonVisible: !published,
11454
11614
  closeOnSubmit: false,
11455
11615
  hasPrimaryAction: publishing === null || published,
11456
11616
  open: dashboardToPublish !== null,
11457
- title: "Publish to application",
11617
+ title: editInProgressByCurrentUser(dashboardToPublish) ? 'Publish changes' : 'Publish to application',
11458
11618
  submitButtonProps: {
11459
11619
  'data-testid': 'publish-confirm-button',
11460
11620
  disabled: !canSubmit(),
11461
- label: published ? 'Got it' : 'Publish'
11621
+ label: getPublishButtonLabel(dashboardToPublish)
11462
11622
  },
11463
11623
  onCancel: handleCancelPublish,
11464
11624
  onSubmit: published ? handleCancelPublish : handlePublish,
@@ -11469,7 +11629,8 @@ function DotDashboardPublishConfirm({
11469
11629
  published: published,
11470
11630
  publishing: publishing !== null,
11471
11631
  onChange: handlePublishChange,
11472
- requiresApplication: requiresApplication
11632
+ requiresApplication: requiresApplication,
11633
+ editInProgress: editInProgressByCurrentUser(dashboardToPublish)
11473
11634
  })
11474
11635
  }), dashboardToUnpublish !== null && jsx(DotDialog, {
11475
11636
  cancelButtonVisible: !unpublished,
@@ -11524,11 +11685,14 @@ const StyledDotMenu = styled(DotMenu)`
11524
11685
 
11525
11686
  function DotDashboardOptionsMenu({
11526
11687
  dashboard,
11688
+ currentUser,
11527
11689
  isEdit = false,
11528
11690
  menuPlacement,
11529
11691
  onStartDelete,
11530
11692
  onStartDuplicate,
11531
11693
  onStartStatusChange,
11694
+ onStartRevert,
11695
+ onViewOriginal,
11532
11696
  onViewMode,
11533
11697
  onDetails
11534
11698
  }) {
@@ -11547,8 +11711,10 @@ function DotDashboardOptionsMenu({
11547
11711
  onViewMode(dashboard, 'edit');
11548
11712
  }, [dashboard, onViewMode]);
11549
11713
  const isDraft = dashboard.lifecycle_state === DashboardView.lifecycle_state.DRAFT;
11714
+ const isPublished = dashboard.lifecycle_state === DashboardView.lifecycle_state.PUBLISHED;
11715
+ const dashboardLocked = isPublished && currentUser && dashboard.is_being_modified && dashboard.modified_author_id !== currentUser.id;
11550
11716
  const menuItems = [];
11551
- if (!isEdit && onViewMode && !dashboard.is_ootb_dashboard) {
11717
+ if (!isEdit && onViewMode && !dashboard.is_ootb_dashboard && !dashboardLocked) {
11552
11718
  menuItems.push({
11553
11719
  children: jsxs(DotLink, {
11554
11720
  ariaLabel: "Edit dashboard",
@@ -11623,6 +11789,62 @@ function DotDashboardOptionsMenu({
11623
11789
  onclick: handleDeleteClick
11624
11790
  });
11625
11791
  }
11792
+ // If this is a published dashboard, with in-progress changes, and the user is the author of the changes,
11793
+ // show the republish, revert, and view original options.
11794
+ if (isEdit && isPublished && currentUser && dashboard.is_being_modified && dashboard.modified_author_id === currentUser.id) {
11795
+ const handlePublishChangesClick = () => {
11796
+ handleMenuClose();
11797
+ onStartStatusChange && onStartStatusChange(dashboard, DashboardView.lifecycle_state.PUBLISHED);
11798
+ };
11799
+ const handleRevertChangesClick = () => {
11800
+ handleMenuClose();
11801
+ onStartRevert && onStartRevert(dashboard);
11802
+ };
11803
+ const handleViewOriginalClick = () => {
11804
+ handleMenuClose();
11805
+ // Move to view mode and display the original dashboard without the changes
11806
+ onViewOriginal && onViewOriginal(dashboard);
11807
+ };
11808
+ menuItems.push({
11809
+ children: jsxs(DotLink, {
11810
+ ariaLabel: "Publish changes",
11811
+ color: "inherit",
11812
+ onClick: handlePublishChangesClick,
11813
+ underline: "none",
11814
+ children: [jsx(DotIcon, {
11815
+ iconId: "send-airplane"
11816
+ }), " Publish changes"]
11817
+ }),
11818
+ key: 'republish',
11819
+ onclick: handlePublishChangesClick
11820
+ });
11821
+ menuItems.push({
11822
+ children: jsxs(DotLink, {
11823
+ ariaLabel: "Revert to original",
11824
+ color: "inherit",
11825
+ onClick: handleRevertChangesClick,
11826
+ underline: "none",
11827
+ children: [jsx(DotIcon, {
11828
+ iconId: "undo"
11829
+ }), " Revert to original"]
11830
+ }),
11831
+ key: 'revert',
11832
+ onclick: handleRevertChangesClick
11833
+ });
11834
+ menuItems.push({
11835
+ children: jsxs(DotLink, {
11836
+ ariaLabel: "Open published dashboard",
11837
+ color: "inherit",
11838
+ onClick: handleViewOriginalClick,
11839
+ underline: "none",
11840
+ children: [jsx(DotIcon, {
11841
+ iconId: "visibility-on"
11842
+ }), " Open published dashboard"]
11843
+ }),
11844
+ key: 'original',
11845
+ onclick: handleViewOriginalClick
11846
+ });
11847
+ }
11626
11848
  if (onDetails) {
11627
11849
  if (menuItems.length > 0) {
11628
11850
  menuItems.push({
@@ -11788,13 +12010,17 @@ function DotDashboardActions({
11788
12010
  onDeleted,
11789
12011
  onDuplicated,
11790
12012
  onToggleFullscreen,
11791
- onViewMode
12013
+ onViewMode,
12014
+ onViewOriginal,
12015
+ onRevertChanges,
12016
+ currentUser
11792
12017
  }) {
11793
12018
  // NOTE: useState functions need to stay at the top of the file so that
11794
12019
  // they are evaluated before any context imports. If they are evaluated
11795
12020
  // after they can cause React state issues when rendering.
11796
12021
  const [dashboardToCopy, setDashboardToCopy] = useState(null);
11797
12022
  const [dashboardToDelete, setDashboardToDelete] = useState(null);
12023
+ const [dashboardToRevert, setDashboardToRevert] = useState(null);
11798
12024
  const [dashboardToPublish, setDashboardToPublish] = useState(null);
11799
12025
  const [dashboardToUnpublish, setDashboardToUnpublish] = useState(null);
11800
12026
  const [appCategories, setAppCategories] = useState(null);
@@ -11802,7 +12028,9 @@ function DotDashboardActions({
11802
12028
  deleteDashboard,
11803
12029
  duplicateDashboard,
11804
12030
  getCategories,
11805
- setOpenedDashboardDetails
12031
+ setOpenedDashboardDetails,
12032
+ revertDashboardChanges,
12033
+ getDashboard
11806
12034
  } = useDotMetadataApiContext();
11807
12035
  const {
11808
12036
  cancelablePromise
@@ -11819,6 +12047,8 @@ function DotDashboardActions({
11819
12047
  setDashboardToPublish(null);
11820
12048
  setDashboardToUnpublish(null);
11821
12049
  onStatusChanged && onStatusChanged(publishedDashboard);
12050
+ // Move to View Mode after publishing
12051
+ onViewMode && onViewMode(publishedDashboard, 'view');
11822
12052
  }, [onStatusChanged]);
11823
12053
  const handlePublishConfirmClose = useCallback(() => {
11824
12054
  setDashboardToPublish(null);
@@ -11854,9 +12084,32 @@ function DotDashboardActions({
11854
12084
  }
11855
12085
  });
11856
12086
  }, [dashboard, onDuplicated]);
12087
+ const handleRevertSubmit = useCallback(() => __awaiter(this, void 0, void 0, function* () {
12088
+ const dashboardId = dashboardToRevert.id;
12089
+ return cancelablePromise(revertDashboardChanges(dashboardId)).then(result => {
12090
+ setDashboardToRevert(null);
12091
+ onRevertChanges && onRevertChanges(result);
12092
+ onStatusChanged && onStatusChanged(result);
12093
+ onViewMode && onViewMode(result, 'view');
12094
+ });
12095
+ }), [dashboardToRevert, onRevertChanges, onStatusChanged]);
12096
+ const handleStartViewOriginal = useCallback(() => __awaiter(this, void 0, void 0, function* () {
12097
+ const dashboardId = dashboard.id;
12098
+ return cancelablePromise(getDashboard(dashboardId, false)).then(result => {
12099
+ onStatusChanged && onStatusChanged(result);
12100
+ onViewMode && onViewMode(result, 'view');
12101
+ onViewOriginal && onViewOriginal(result);
12102
+ });
12103
+ }), [dashboard, onViewOriginal, onStatusChanged]);
11857
12104
  const handleStartDelete = useCallback(dashboardToDel => {
11858
12105
  setDashboardToDelete(dashboardToDel);
11859
12106
  }, []);
12107
+ const handleStartRevert = useCallback(dashboard => {
12108
+ setDashboardToRevert(dashboard);
12109
+ }, []);
12110
+ const handleRevertClose = useCallback(() => {
12111
+ setDashboardToRevert(null);
12112
+ }, []);
11860
12113
  const handleStartDuplicate = useCallback(dashboardToDupe => {
11861
12114
  setDashboardToCopy(dashboardToDupe);
11862
12115
  }, []);
@@ -11864,6 +12117,8 @@ function DotDashboardActions({
11864
12117
  const handleStartStatusChangeIfConfig = onStatusChanged ? handleStartStatusChange : undefined;
11865
12118
  const handleStartDeleteIfConfig = onDeleted ? handleStartDelete : undefined;
11866
12119
  const handleViewModeIfConfig = onViewMode && canEdit ? onViewMode : undefined;
12120
+ const handleRevertChangesIfConfig = onRevertChanges ? handleStartRevert : undefined;
12121
+ const handleViewOriginalIfConfig = onViewOriginal ? handleStartViewOriginal : undefined;
11867
12122
  return jsxs(StyledDashboardActions, {
11868
12123
  "data-testid": "dot-dashboard-actions",
11869
12124
  children: [jsx(DotDashboardPublishConfirm, {
@@ -11871,7 +12126,8 @@ function DotDashboardActions({
11871
12126
  dashboardToPublish: dashboardToPublish,
11872
12127
  dashboardToUnpublish: dashboardToUnpublish,
11873
12128
  onClose: handlePublishConfirmClose,
11874
- onStatusChanged: handlePublishConfirm
12129
+ onStatusChanged: handlePublishConfirm,
12130
+ currentUser: currentUser ? currentUser : null
11875
12131
  }), appCategories && dashboardToCopy && jsx(DotDashboardDialog, {
11876
12132
  title: "Duplicate dashboard",
11877
12133
  availableCategories: appCategories,
@@ -11885,6 +12141,14 @@ function DotDashboardActions({
11885
12141
  record: dashboardToDelete.name,
11886
12142
  impact: dashboardToDelete.lifecycle_state === DashboardView.lifecycle_state.PUBLISHED ? 'high' : 'medium',
11887
12143
  open: true
12144
+ }), dashboardToRevert && jsx(DotImpactDialog, {
12145
+ onCancel: handleRevertClose,
12146
+ onSubmit: handleRevertSubmit,
12147
+ record: dashboardToRevert.name,
12148
+ impact: "medium",
12149
+ action: "revert",
12150
+ actionIcon: "undo",
12151
+ open: true
11888
12152
  }), jsx(HelpButton, {
11889
12153
  dashboard: dashboard
11890
12154
  }), onFavorite && jsx(FavoriteButton, {
@@ -11894,11 +12158,14 @@ function DotDashboardActions({
11894
12158
  dashboard: dashboard,
11895
12159
  isEdit: isEdit,
11896
12160
  menuPlacement: "bottom-start",
12161
+ onViewOriginal: handleViewOriginalIfConfig,
11897
12162
  onViewMode: handleViewModeIfConfig,
11898
12163
  onStartStatusChange: handleStartStatusChangeIfConfig,
11899
12164
  onStartDuplicate: handleStartDuplicateIfConfig,
11900
12165
  onStartDelete: handleStartDeleteIfConfig,
11901
- onDetails: () => setOpenedDashboardDetails(dashboard)
12166
+ onStartRevert: handleRevertChangesIfConfig,
12167
+ onDetails: () => setOpenedDashboardDetails(dashboard),
12168
+ currentUser: currentUser ? currentUser : null
11902
12169
  }), onToggleFullscreen && jsx(FullscreenButton, {
11903
12170
  dashboard: dashboard,
11904
12171
  isFullscreen: isFullscreen,
@@ -11920,6 +12187,22 @@ const StyledDashboardHeader = styled(DotActionToolbar)`
11920
12187
  padding: ${theme.spacing(0, 2)};
11921
12188
  `}
11922
12189
  `;
12190
+ const StyledDashboardBanner = styled.div`
12191
+ ${({
12192
+ theme
12193
+ }) => css`
12194
+ padding: ${theme.spacing(1, 2)};
12195
+ align-items: stretch;
12196
+ .MuiAlert-message {
12197
+ flex: 5;
12198
+ }
12199
+ .dot-typography {
12200
+ display: flex;
12201
+ justify-content: space-between;
12202
+ align-items: center;
12203
+ }
12204
+ `}
12205
+ `;
11923
12206
  const StyledDashboardHeaderTitleSection = styled.div`
11924
12207
  ${({
11925
12208
  theme
@@ -11940,9 +12223,75 @@ const StyledDashboardHeaderTitleSection = styled.div`
11940
12223
  `}
11941
12224
  `;
11942
12225
 
12226
+ function DotDashboardBanner({
12227
+ bannerSeverity,
12228
+ bannerText,
12229
+ buttonText,
12230
+ buttonAction
12231
+ }) {
12232
+ return jsx(StyledDashboardBanner, {
12233
+ children: jsxs(DotAlertBanner, {
12234
+ severity: bannerSeverity,
12235
+ "data-testid": "dashboard-banner",
12236
+ children: [bannerText, buttonText && jsx(DotButton, {
12237
+ type: "outlined",
12238
+ onClick: buttonAction,
12239
+ "data-testid": "dashboard-banner-button",
12240
+ children: buttonText
12241
+ })]
12242
+ })
12243
+ });
12244
+ }
12245
+ function getDashboardBanner(dashboard, isEdit, onExitEditMode, onPublishChanges, currentUser, modifiedAuthorUser) {
12246
+ if (isEdit) {
12247
+ if (dashboard.is_being_modified) {
12248
+ if (dashboard.modified_author_id === currentUser.id) {
12249
+ // We're in Edit mode for a published dashboard, and the dashboard is being modified by the current user.
12250
+ return jsx(DotDashboardBanner, {
12251
+ bannerSeverity: "warning",
12252
+ bannerText: jsx(DotTypography, {
12253
+ children: "The Dashboard is currently in edit mode and only you can make changes. Publish the changes for other users to see."
12254
+ }),
12255
+ buttonText: "Publish changes",
12256
+ buttonAction: () => {
12257
+ onPublishChanges(dashboard);
12258
+ }
12259
+ });
12260
+ }
12261
+ } else {
12262
+ // We're in Edit mode for a published dashboard, but there are no staged changes saved yet.
12263
+ return jsx(DotDashboardBanner, {
12264
+ bannerSeverity: "info",
12265
+ bannerText: jsx(DotTypography, {
12266
+ children: "You are currently in Edit Mode. Any changes you make will not be visible to others until you publish the updated dashboard."
12267
+ }),
12268
+ buttonText: "Exit edit mode",
12269
+ buttonAction: () => {
12270
+ onExitEditMode(dashboard);
12271
+ }
12272
+ });
12273
+ }
12274
+ } else {
12275
+ if (currentUser && dashboard.is_being_modified && dashboard.modified_author_id !== currentUser.id && modifiedAuthorUser) {
12276
+ // We're in View mode for a published dashboard that is being edited by someone else.
12277
+ const bannerText = jsx(DotTypography, {
12278
+ children: jsxs("div", {
12279
+ children: ["This Dashboard is currently being edited by", ' ', jsxs("strong", {
12280
+ children: [modifiedAuthorUser.given_name, " ", modifiedAuthorUser.family_name]
12281
+ }), ". You will be able to see the updated dashboard once the changes are published."]
12282
+ })
12283
+ });
12284
+ return jsx(DotDashboardBanner, {
12285
+ bannerSeverity: "info",
12286
+ bannerText: bannerText
12287
+ });
12288
+ }
12289
+ }
12290
+ }
11943
12291
  function DotDashboardHeader({
11944
12292
  accountId,
11945
12293
  dashboard,
12294
+ currentUser,
11946
12295
  isEdit = false,
11947
12296
  canEdit = false,
11948
12297
  isFullscreen = false,
@@ -11952,10 +12301,14 @@ function DotDashboardHeader({
11952
12301
  onStatusChanged,
11953
12302
  onDeleted,
11954
12303
  onDuplicated,
12304
+ onRevertChanges,
12305
+ onViewOriginal,
11955
12306
  onToggleFullscreen,
11956
12307
  onViewMode,
11957
- showStatus = false
12308
+ showStatus = false,
12309
+ modifiedAuthorUser = null
11958
12310
  }) {
12311
+ const [dashboardToPublish, setDashboardToPublish] = useState(null);
11959
12312
  const {
11960
12313
  applications,
11961
12314
  applicationsError,
@@ -11966,6 +12319,18 @@ function DotDashboardHeader({
11966
12319
  metadataLoading,
11967
12320
  dashboardsError
11968
12321
  } = useDotMetadataApiContext();
12322
+ const handleStartPublishChanges = useCallback(publishDashboard => {
12323
+ setDashboardToPublish(publishDashboard);
12324
+ }, []);
12325
+ const handlePublishConfirmClose = useCallback(() => {
12326
+ setDashboardToPublish(null);
12327
+ }, []);
12328
+ const handlePublishConfirm = useCallback(publishedDashboard => {
12329
+ setDashboardToPublish(null);
12330
+ onStatusChanged && onStatusChanged(publishedDashboard);
12331
+ // Navigate to View Mode after publishing changes
12332
+ onViewMode && onViewMode(publishedDashboard, 'view');
12333
+ }, [onStatusChanged]);
11969
12334
  useEnqueueErrorMessage(!applicationsLoading && applicationsError);
11970
12335
  useEnqueueErrorMessage(!metadataLoading && dashboardsError);
11971
12336
  useEffect(() => {
@@ -11977,29 +12342,45 @@ function DotDashboardHeader({
11977
12342
  iconId: "back-solid",
11978
12343
  onClick: () => onBack(dashboard.id)
11979
12344
  });
11980
- return jsxs(StyledDashboardHeader, {
11981
- children: [jsxs(StyledDashboardHeaderTitleSection, {
11982
- children: [jsxs(DotTypography, {
11983
- component: "h2",
11984
- variant: "h2",
11985
- children: [backButton, dashboard === null || dashboard === void 0 ? void 0 : dashboard.name]
11986
- }), showStatus && jsx(DotDashboardStatusPill, {
11987
- status: dashboard.lifecycle_state
12345
+ const onExitEditMode = dashboardEdit => {
12346
+ onViewMode && onViewMode(dashboardEdit, 'view');
12347
+ };
12348
+ return jsxs(Fragment, {
12349
+ children: [jsx(DotDashboardPublishConfirm, {
12350
+ applicationList: applications,
12351
+ dashboardToPublish: dashboardToPublish,
12352
+ dashboardToUnpublish: null,
12353
+ onClose: handlePublishConfirmClose,
12354
+ onStatusChanged: handlePublishConfirm,
12355
+ currentUser: currentUser ? currentUser : null
12356
+ }), jsxs(StyledDashboardHeader, {
12357
+ children: [jsxs(StyledDashboardHeaderTitleSection, {
12358
+ children: [jsxs(DotTypography, {
12359
+ component: "h2",
12360
+ variant: "h2",
12361
+ children: [backButton, dashboard === null || dashboard === void 0 ? void 0 : dashboard.name]
12362
+ }), showStatus && dashboard && jsx(DotDashboardStatusPill, {
12363
+ dashboard: dashboard,
12364
+ currentUser: currentUser ? currentUser : null
12365
+ })]
12366
+ }), jsx(DotDashboardActions, {
12367
+ applications: applications,
12368
+ canEdit: canEdit,
12369
+ dashboard: dashboard,
12370
+ isEdit: isEdit,
12371
+ isFullscreen: isFullscreen,
12372
+ onClose: onClose,
12373
+ onFavorite: onFavorite,
12374
+ onRevertChanges: onRevertChanges,
12375
+ onStatusChanged: onStatusChanged,
12376
+ onDeleted: onDeleted,
12377
+ onDuplicated: onDuplicated,
12378
+ onToggleFullscreen: onToggleFullscreen,
12379
+ onViewMode: onViewMode,
12380
+ onViewOriginal: onViewOriginal,
12381
+ currentUser: currentUser ? currentUser : null
11988
12382
  })]
11989
- }), jsx(DotDashboardActions, {
11990
- applications: applications,
11991
- canEdit: canEdit,
11992
- dashboard: dashboard,
11993
- isEdit: isEdit,
11994
- isFullscreen: isFullscreen,
11995
- onClose: onClose,
11996
- onFavorite: onFavorite,
11997
- onStatusChanged: onStatusChanged,
11998
- onDeleted: onDeleted,
11999
- onDuplicated: onDuplicated,
12000
- onToggleFullscreen: onToggleFullscreen,
12001
- onViewMode: onViewMode
12002
- })]
12383
+ }), dashboard && dashboard.lifecycle_state === 'PUBLISHED' && getDashboardBanner(dashboard, isEdit, onExitEditMode, handleStartPublishChanges, currentUser ? currentUser : null, modifiedAuthorUser ? modifiedAuthorUser : null)]
12003
12384
  });
12004
12385
  }
12005
12386
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@digital-ai/dot-components",
3
- "version": "3.22.0",
3
+ "version": "3.23.0",
4
4
  "private": false,
5
5
  "license": "SEE LICENSE IN <LICENSE.md>",
6
6
  "contributors": [
@@ -1,7 +1,8 @@
1
- import { ApplicationModel } from '../../core-api/openapi';
1
+ import { ApplicationModel, UserModel } from '../../core-api/openapi';
2
2
  import { DashboardView } from '../metadata-api/openapi/';
3
3
  interface DashboardActionsCommonProps {
4
4
  canEdit?: boolean;
5
+ currentUser?: UserModel;
5
6
  dashboard: DashboardView;
6
7
  isEdit?: boolean;
7
8
  isFullscreen?: boolean;
@@ -9,12 +10,14 @@ interface DashboardActionsCommonProps {
9
10
  onDeleted?: (id: string, result: boolean) => void;
10
11
  onDuplicated?: (dashboard: DashboardView, isDone?: boolean) => void;
11
12
  onFavorite?: (id: string, value: boolean) => void;
13
+ onRevertChanges?: (dashboard: DashboardView) => void;
12
14
  onStatusChanged?: (dashboard: DashboardView) => void;
13
15
  onToggleFullscreen?: (newValue: boolean) => void;
14
16
  onViewMode?: (dashboard: DashboardView, mode: string) => void;
17
+ onViewOriginal?: (dashboard: DashboardView) => void;
15
18
  }
16
19
  interface DashboardActionsProps extends DashboardActionsCommonProps {
17
20
  applications: ApplicationModel[];
18
21
  }
19
- declare function DotDashboardActions({ applications, dashboard, isEdit, canEdit, isFullscreen, onClose, onFavorite, onStatusChanged, onDeleted, onDuplicated, onToggleFullscreen, onViewMode, }: DashboardActionsProps): import("react/jsx-runtime").JSX.Element;
20
- export { DashboardActionsCommonProps, DotDashboardActions };
22
+ declare function DotDashboardActions({ applications, dashboard, isEdit, canEdit, isFullscreen, onClose, onFavorite, onStatusChanged, onDeleted, onDuplicated, onToggleFullscreen, onViewMode, onViewOriginal, onRevertChanges, currentUser, }: DashboardActionsProps): import("react/jsx-runtime").JSX.Element;
23
+ export { DashboardActionsCommonProps, DotDashboardActions, DashboardActionsProps, };
@@ -1,14 +1,18 @@
1
1
  import { PopperPlacement } from '../../menu/Menu';
2
2
  import { DashboardView } from '../metadata-api/openapi';
3
+ import { UserModel } from '../../core-api/openapi';
3
4
  interface DashboardOptionsMenuProps {
5
+ currentUser?: UserModel;
4
6
  dashboard: DashboardView;
5
7
  isEdit?: boolean;
6
8
  menuPlacement?: PopperPlacement;
7
9
  onDetails?: (dashboard: DashboardView) => void;
8
10
  onStartDelete?: (dashboard: DashboardView) => void;
9
11
  onStartDuplicate?: (dashboard: DashboardView) => void;
12
+ onStartRevert?: (dashboard: DashboardView) => void;
10
13
  onStartStatusChange?: (dashboard: DashboardView, status: DashboardView.lifecycle_state) => void;
11
14
  onViewMode?: (dashboard: DashboardView, mode: string) => void;
15
+ onViewOriginal?: (dashboard: DashboardView) => void;
12
16
  }
13
- export declare function DotDashboardOptionsMenu({ dashboard, isEdit, menuPlacement, onStartDelete, onStartDuplicate, onStartStatusChange, onViewMode, onDetails, }: DashboardOptionsMenuProps): import("react/jsx-runtime").JSX.Element;
17
+ export declare function DotDashboardOptionsMenu({ dashboard, currentUser, isEdit, menuPlacement, onStartDelete, onStartDuplicate, onStartStatusChange, onStartRevert, onViewOriginal, onViewMode, onDetails, }: DashboardOptionsMenuProps): import("react/jsx-runtime").JSX.Element;
14
18
  export {};
@@ -1,8 +1,10 @@
1
- import { ApplicationModel } from '../../core-api/openapi';
1
+ import { ApplicationModel, UserModel } from '../../core-api/openapi';
2
2
  import { DashboardView } from '../metadata-api/openapi';
3
3
  interface DashboardPublishConfirmProps {
4
4
  /** List of applications the dashboard can be published to **/
5
5
  applicationList: ApplicationModel[];
6
+ /** Current User, used to determine if they have in-progress edits. **/
7
+ currentUser?: UserModel;
6
8
  /** Dashboard to confirm publishing for **/
7
9
  dashboardToPublish: DashboardView;
8
10
  /** Dashboard to confirm unpublishing for **/
@@ -12,5 +14,5 @@ interface DashboardPublishConfirmProps {
12
14
  /** When a dashboard is updated, this function is called with the updated dashboard **/
13
15
  onStatusChanged: (updatedDashboard: DashboardView) => void;
14
16
  }
15
- export declare function DotDashboardPublishConfirm({ applicationList, dashboardToPublish, dashboardToUnpublish, onClose, onStatusChanged, }: Readonly<DashboardPublishConfirmProps>): import("react/jsx-runtime").JSX.Element;
17
+ export declare function DotDashboardPublishConfirm({ applicationList, dashboardToPublish, dashboardToUnpublish, onClose, onStatusChanged, currentUser, }: Readonly<DashboardPublishConfirmProps>): import("react/jsx-runtime").JSX.Element;
16
18
  export {};
@@ -1,6 +1,7 @@
1
1
  import { MouseEvent } from 'react';
2
2
  import { CommonProps } from '../../CommonProps';
3
3
  import { DashboardView } from '../metadata-api/openapi';
4
+ import { UserModel } from '../../core-api/openapi';
4
5
  interface CommonDashboardDetailsProps extends CommonProps {
5
6
  onClose?: (event: MouseEvent | KeyboardEvent) => void;
6
7
  onFavorite?: (dashboardId: string, favoriteValue: boolean) => void;
@@ -8,12 +9,14 @@ interface CommonDashboardDetailsProps extends CommonProps {
8
9
  zIndex?: number;
9
10
  }
10
11
  interface DashboardDetailsViewProps extends CommonDashboardDetailsProps {
12
+ currentUser?: UserModel;
11
13
  dashboard: DashboardView;
12
14
  open: boolean;
13
15
  }
14
- export declare const DotDashboardDetailsView: ({ className, dashboard, onClose, onFavorite, open, yOffset, zIndex, }: DashboardDetailsViewProps) => import("react/jsx-runtime").JSX.Element;
16
+ export declare const DotDashboardDetailsView: ({ className, dashboard, onClose, onFavorite, open, yOffset, zIndex, currentUser, }: DashboardDetailsViewProps) => import("react/jsx-runtime").JSX.Element;
15
17
  export interface DashboardDetailsProps extends CommonDashboardDetailsProps {
18
+ currentUser?: UserModel;
16
19
  dashboard?: DashboardView;
17
20
  }
18
- export declare const DotDashboardDetails: ({ dashboard, onClose, onFavorite, ...commonProps }: DashboardDetailsProps) => import("react/jsx-runtime").JSX.Element;
21
+ export declare const DotDashboardDetails: ({ dashboard, onClose, onFavorite, currentUser, ...commonProps }: DashboardDetailsProps) => import("react/jsx-runtime").JSX.Element;
19
22
  export {};
@@ -1,5 +1,8 @@
1
+ import { DashboardView } from '../metadata-api/openapi';
2
+ import { UserModel } from '../../core-api/openapi';
1
3
  interface DashboardStatusPillProps {
2
- status: string;
4
+ currentUser?: UserModel;
5
+ dashboard: DashboardView;
3
6
  }
4
- declare function DotDashboardStatusPill({ status, }: Readonly<DashboardStatusPillProps>): import("react/jsx-runtime").JSX.Element;
7
+ declare function DotDashboardStatusPill({ dashboard, currentUser, }: Readonly<DashboardStatusPillProps>): import("react/jsx-runtime").JSX.Element;
5
8
  export { DashboardStatusPillProps, DotDashboardStatusPill };
@@ -1,8 +1,10 @@
1
+ import { UserModel } from '../../core-api/openapi';
1
2
  import { DashboardActionsCommonProps } from '../dashboard-actions/DashboardActions';
2
3
  interface DashboardHeaderProps extends DashboardActionsCommonProps {
3
4
  accountId?: string;
5
+ modifiedAuthorUser?: UserModel;
4
6
  onBack?: (dashboardId?: string) => void;
5
7
  showStatus?: boolean;
6
8
  }
7
- declare function DotDashboardHeader({ accountId, dashboard, isEdit, canEdit, isFullscreen, onBack, onClose, onFavorite, onStatusChanged, onDeleted, onDuplicated, onToggleFullscreen, onViewMode, showStatus, }: DashboardHeaderProps): import("react/jsx-runtime").JSX.Element;
9
+ declare function DotDashboardHeader({ accountId, dashboard, currentUser, isEdit, canEdit, isFullscreen, onBack, onClose, onFavorite, onStatusChanged, onDeleted, onDuplicated, onRevertChanges, onViewOriginal, onToggleFullscreen, onViewMode, showStatus, modifiedAuthorUser, }: DashboardHeaderProps): import("react/jsx-runtime").JSX.Element;
8
10
  export { DashboardHeaderProps, DotDashboardHeader };
@@ -1,2 +1,3 @@
1
1
  export declare const StyledDashboardHeader: import("styled-components").StyledComponent<({ ariaLabel, children, className, "data-testid": dataTestId, variant, }: import("../../action-toolbar/ActionToolbar").DotActionBarProps) => import("react/jsx-runtime").JSX.Element, any, {}, never>;
2
+ export declare const StyledDashboardBanner: import("styled-components").StyledComponent<"div", any, {}, never>;
2
3
  export declare const StyledDashboardHeaderTitleSection: import("styled-components").StyledComponent<"div", any, {}, never>;
@@ -14,10 +14,13 @@ interface DotMetadataApiContextProps {
14
14
  favoriteDashboard: (dashboardId: string, favoriteValue: boolean) => Promise<DashboardView>;
15
15
  getAuthors: (appType: string, publishedOnly?: boolean) => Promise<Author[]>;
16
16
  getCategories: (appType: string, publishedOnly?: boolean) => Promise<string[]>;
17
+ getDashboard: (dashboardId: string, viewModified?: boolean) => Promise<DashboardView>;
17
18
  getDashboardHelpContent: (helpContentId: string) => Promise<string>;
18
19
  metadataLoading: boolean;
19
20
  openedDashboardDetails: DashboardView;
20
21
  platformConsoleUrl: string;
22
+ publishDashboardChanges: (dashboardId: string, dashboard: DashboardPatchBody, isSync?: boolean) => Promise<DashboardView>;
23
+ revertDashboardChanges: (dashboardId: string) => Promise<DashboardView>;
21
24
  searchDashboards: (search: DashboardFilters) => Promise<DashboardView[]>;
22
25
  setOpenedDashboardDetails: (dashboard: DashboardView) => void;
23
26
  setOverrideAccountId: (accountId: string) => void;
@@ -99,6 +99,14 @@ export type DashboardView = {
99
99
  * Timestamp of the latest modification
100
100
  */
101
101
  updated_dt?: string | null;
102
+ /**
103
+ * Whether a published dashboard is currently being modified.
104
+ */
105
+ is_being_modified?: boolean | null;
106
+ /**
107
+ * The platform id of the author currently modifying the dashboard.
108
+ */
109
+ modified_author_id?: string | null;
102
110
  };
103
111
  export declare namespace DashboardView {
104
112
  /**
@@ -15,7 +15,7 @@ export declare class DashboardsService {
15
15
  * @param sort Sort ordering to apply to the query.
16
16
  * @param filter List of filters (each filter is a separate query param, and they are OR'ed).
17
17
  *
18
- * * **Filterable field names**: author_fullname, author_id, bi_type, categories, created_dt, description, external_embedding_id, external_id, id, is_ootb_dashboard, lifecycle_state, name, target_apps, updated_by_fullname, updated_by_id, updated_dt
18
+ * * **Filterable field names**: author_fullname, author_id, bi_type, categories, created_dt, description, external_embedding_id, external_id, id, is_ootb_dashboard, lifecycle_state, modified_parent_id, name, target_apps, updated_by_fullname, updated_by_id, updated_dt
19
19
  * * **Searchable field names**: author_fullname, categories, description, name, updated_by_fullname
20
20
  *
21
21
  * @param favorite Boolean flag to only return dashboards marked as favorites.
@@ -47,11 +47,12 @@ export declare class DashboardsService {
47
47
  * Get one Dashboard definition.
48
48
  * Return a single Dashboard definition, selected by ID.
49
49
  * @param dashboardId
50
+ * @param viewModified Return the dashboard with modified changes if they exist for this user.
50
51
  * @returns DashboardView OK
51
52
  * @returns Error Default error response
52
53
  * @throws ApiError
53
54
  */
54
- static getDashboardsService1(dashboardId: string): Promise<DashboardView | Error>;
55
+ static getDashboardsService1(dashboardId: string, viewModified?: boolean): Promise<DashboardView | Error>;
55
56
  /**
56
57
  * Sets a single Dashboard definition.
57
58
  * Sets a Dashboard definition, selected by ID.
@@ -82,6 +83,26 @@ export declare class DashboardsService {
82
83
  * @throws ApiError
83
84
  */
84
85
  static deleteDashboardsService(dashboardId: string): Promise<Error>;
86
+ /**
87
+ * Publish modifications to a dashboard
88
+ * Publish modifications to a dashboard
89
+ * @param dashboardId
90
+ * @param requestBody
91
+ * @param isSync Sync the dashboard with BI
92
+ * @returns DashboardView Dashboard published.
93
+ * @returns Error Default error response
94
+ * @throws ApiError
95
+ */
96
+ static postDashboardsService1(dashboardId: string, requestBody: DashboardPatchBody, isSync?: boolean): Promise<DashboardView | Error>;
97
+ /**
98
+ * Revert modifications to a dashboard
99
+ * Revert modifications to a dashboard
100
+ * @param dashboardId
101
+ * @returns DashboardView Dashboard changes reverted.
102
+ * @returns Error Default error response
103
+ * @throws ApiError
104
+ */
105
+ static postDashboardsService2(dashboardId: string): Promise<DashboardView | Error>;
85
106
  /**
86
107
  * Create a copy of existing dashboard
87
108
  * Create a copy of existing dashboard
@@ -91,7 +112,7 @@ export declare class DashboardsService {
91
112
  * @returns Error Default error response
92
113
  * @throws ApiError
93
114
  */
94
- static postDashboardsService1(dashboardId: string, requestBody?: DashboardCopyBody): Promise<DashboardView | Error>;
115
+ static postDashboardsService3(dashboardId: string, requestBody?: DashboardCopyBody): Promise<DashboardView | Error>;
95
116
  /**
96
117
  * Favorite a dashboard
97
118
  * Favorite a dashboard
@@ -100,7 +121,7 @@ export declare class DashboardsService {
100
121
  * @returns Error Default error response
101
122
  * @throws ApiError
102
123
  */
103
- static postDashboardsService2(dashboardId: string): Promise<DashboardView | Error>;
124
+ static postDashboardsService4(dashboardId: string): Promise<DashboardView | Error>;
104
125
  /**
105
126
  * Un-favorite a dashboard
106
127
  * Un-favorite a dashboard
@@ -10,3 +10,4 @@ export type { ApplicationModelWrapper } from './models/ApplicationModelWrapper';
10
10
  export type { PaginationModel } from './models/PaginationModel';
11
11
  export { AccountsService } from './services/AccountsService';
12
12
  export { ApplicationsService } from './services/ApplicationsService';
13
+ export type { UserModel } from './models/UserModel';
@@ -0,0 +1,70 @@
1
+ export type UserModel = {
2
+ /**
3
+ * UUID Account Identifier
4
+ */
5
+ account_id: string;
6
+ /**
7
+ * The user creation date in ISO format
8
+ */
9
+ created_date: string;
10
+ /**
11
+ * Email address
12
+ */
13
+ email?: string;
14
+ /**
15
+ * Whether the user is enabled or not
16
+ */
17
+ enabled: boolean;
18
+ /**
19
+ * A message when problems arise retrieving details of a user
20
+ */
21
+ readonly error?: string;
22
+ /**
23
+ * A numerical code when problems occur retrieving details of a user
24
+ */
25
+ readonly error_code?: number;
26
+ /**
27
+ * User's last name
28
+ */
29
+ family_name?: string;
30
+ /**
31
+ * User's first name
32
+ */
33
+ given_name?: string;
34
+ /**
35
+ * List of Group names
36
+ */
37
+ groups?: Array<string>;
38
+ /**
39
+ * UUID User Identifier
40
+ */
41
+ id: string;
42
+ /**
43
+ * The date of the user's most recent login in ISO format
44
+ */
45
+ last_login_date: string;
46
+ /**
47
+ * Whether the user is created via API
48
+ */
49
+ readonly local: boolean;
50
+ /**
51
+ * Whether the user is locked out or not
52
+ */
53
+ readonly locked?: boolean;
54
+ /**
55
+ * The date that the user was last modified on in ISO format
56
+ */
57
+ modified_date: string;
58
+ /**
59
+ * Whether the user is invited and not yet logged in
60
+ */
61
+ pending: boolean;
62
+ /**
63
+ * List of Role names
64
+ */
65
+ roles?: Array<string>;
66
+ /**
67
+ * Username
68
+ */
69
+ username: string;
70
+ };