@orangelogic/orange-dam-content-browser-sdk 2.4.7 → 2.4.8

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.
@@ -60,6 +60,7 @@ export type GetAssetsRawResponse = {
60
60
  };
61
61
  export type GetAssetsResponse = {
62
62
  facets: Facet[];
63
+ isError: boolean;
63
64
  items: Array<Asset & Record<string, string | boolean>>;
64
65
  totalCount: number;
65
66
  };
@@ -133,6 +133,7 @@ export default class CxContentBrowser extends CortexElement {
133
133
  private handleGridResize;
134
134
  private clearInitialFolderPending;
135
135
  private releaseInitialFolder;
136
+ private handleRetry;
136
137
  private handleGridClick;
137
138
  private handleVersionHistoryOpen;
138
139
  private handleFavoriteChange;
@@ -2,6 +2,8 @@ import '@lit-labs/virtualizer';
2
2
  import CortexElement from '../../base/element';
3
3
  import { Asset } from '../../types/asset';
4
4
  import { GridView } from '../../types/content-browser';
5
+ import CxButton from '@orangelogic/design-system/components/button';
6
+ import CxIcon from '@orangelogic/design-system/components/icon';
5
7
  import CxProgressBar from '@orangelogic/design-system/components/progress-bar';
6
8
  import CxResizeObserver from '@orangelogic/design-system/components/resize-observer';
7
9
  import CxContentBrowserAssetCard from '../content-browser-asset-card/content-browser-asset-card';
@@ -11,8 +13,10 @@ export default class CxContentBrowserGrid extends CortexElement {
11
13
  #private;
12
14
  static readonly styles: CSSResultGroup;
13
15
  static readonly dependencies: {
16
+ 'cx-button': typeof CxButton;
14
17
  'cx-content-browser-asset-card': typeof CxContentBrowserAssetCard;
15
18
  'cx-content-browser-no-result': typeof CxContentBrowserNoResult;
19
+ 'cx-icon': typeof CxIcon;
16
20
  'cx-progress-bar': typeof CxProgressBar;
17
21
  'cx-resize-observer': typeof CxResizeObserver;
18
22
  };
@@ -21,6 +25,8 @@ export default class CxContentBrowserGrid extends CortexElement {
21
25
  private readonly virtualizerEl;
22
26
  assets: Asset[];
23
27
  empty: boolean;
28
+ /** The last search request got an error. With no rows, the error replaces the grid. With rows, it shows at the bottom. */
29
+ error: boolean;
24
30
  view: GridView;
25
31
  hasMore: boolean;
26
32
  loading: boolean;
@@ -44,6 +50,9 @@ export default class CxContentBrowserGrid extends CortexElement {
44
50
  private handleScroll;
45
51
  private readonly debouncedHandleScrollEnd;
46
52
  private handleScrollEnd;
53
+ private handleRetry;
54
+ private renderRetry;
55
+ private renderContent;
47
56
  render(): import("lit-html").TemplateResult<1>;
48
57
  }
49
58
  declare global {
@@ -12126,6 +12126,7 @@ let CxContentBrowserNoResult = class extends CortexElement {
12126
12126
  <div class="content-browser-no-result" data-testid="no-results">
12127
12127
  <cx-icon name=${this.icon}></cx-icon>
12128
12128
  ${this.message}
12129
+ <slot></slot>
12129
12130
  </div>
12130
12131
  `;
12131
12132
  }
@@ -12278,7 +12279,28 @@ const styles$2 = i$7`
12278
12279
  }
12279
12280
 
12280
12281
  .content-browser-grid {
12282
+ display: flex;
12283
+ flex-direction: column;
12281
12284
  height: 100%;
12285
+ position: relative;
12286
+ }
12287
+
12288
+ .content-browser-grid__list {
12289
+ flex: 1 1 auto;
12290
+ min-height: 0;
12291
+ overflow-x: hidden;
12292
+ }
12293
+
12294
+ .content-browser-grid__page-error {
12295
+ flex: none;
12296
+ display: flex;
12297
+ align-items: center;
12298
+ justify-content: center;
12299
+ gap: var(--cx-spacing-small, 8px);
12300
+ padding: var(--cx-spacing-small, 8px);
12301
+ border-top: 1px solid var(--cx-color-neutral-200, #e5e5e5);
12302
+ background-color: var(--cx-color-neutral-0, #fff);
12303
+ color: var(--cx-color-neutral);
12282
12304
  }
12283
12305
 
12284
12306
  .content-browser-grid-loading {
@@ -12315,6 +12337,7 @@ let CxContentBrowserGrid = class extends CortexElement {
12315
12337
  this.localize = new LocalizeController(this);
12316
12338
  this.assets = [];
12317
12339
  this.empty = false;
12340
+ this.error = false;
12318
12341
  this.view = GridView.Medium;
12319
12342
  this.hasMore = false;
12320
12343
  this.loading = false;
@@ -12454,6 +12477,63 @@ let CxContentBrowserGrid = class extends CortexElement {
12454
12477
  this.emit("cx-content-browser-grid-scroll-end");
12455
12478
  }
12456
12479
  }
12480
+ handleRetry() {
12481
+ this.emit("cx-content-browser-grid-retry");
12482
+ }
12483
+ renderRetry() {
12484
+ return b`
12485
+ <cx-button class="content-browser-grid__retry" variant="primary" @click=${this.handleRetry}>
12486
+ ${this.localize.term("retry")}
12487
+ </cx-button>
12488
+ `;
12489
+ }
12490
+ renderContent() {
12491
+ if (this.error && this.assets.length === 0) {
12492
+ return b`
12493
+ <cx-content-browser-no-result
12494
+ class="content-browser-grid__empty"
12495
+ icon="error_outline"
12496
+ message=${this.localize.term("oopsSomethingWentWrong")}
12497
+ role="alert"
12498
+ >
12499
+ ${this.renderRetry()}
12500
+ </cx-content-browser-no-result>
12501
+ `;
12502
+ }
12503
+ if (this.empty) {
12504
+ return b`
12505
+ <cx-content-browser-no-result
12506
+ class="content-browser-grid__empty"
12507
+ icon="search_off"
12508
+ message=${this.localize.term("noResults")}
12509
+ ></cx-content-browser-no-result>
12510
+ `;
12511
+ }
12512
+ return b`
12513
+ <lit-virtualizer
12514
+ class="content-browser-grid__list"
12515
+ scroller
12516
+ .layout=${grid({
12517
+ gap: `${__privateGet2(this, _gutter)}px`,
12518
+ itemSize: {
12519
+ height: `${Math.max(this.columnWidth, 150)}px`,
12520
+ width: `${this.columnWidth}px`
12521
+ },
12522
+ flex: { preserve: "aspect-ratio" }
12523
+ })}
12524
+ .items=${this.assets}
12525
+ .renderItem=${this.renderItem}
12526
+ @scroll=${this.handleScroll}
12527
+ ></lit-virtualizer>
12528
+ ${n$5(this.error, () => b`
12529
+ <div class="content-browser-grid__page-error" role="alert">
12530
+ <cx-icon name="error_outline"></cx-icon>
12531
+ ${this.localize.term("oopsSomethingWentWrong")}
12532
+ ${this.renderRetry()}
12533
+ </div>
12534
+ `)}
12535
+ `;
12536
+ }
12457
12537
  render() {
12458
12538
  return b`
12459
12539
  <div
@@ -12467,36 +12547,7 @@ let CxContentBrowserGrid = class extends CortexElement {
12467
12547
  </div>
12468
12548
  <cx-resize-observer @cx-resize=${this.handleResize}>
12469
12549
  <div class="content-browser-grid">
12470
- ${n$5(
12471
- this.empty,
12472
- () => b`
12473
- <cx-content-browser-no-result
12474
- class="content-browser-grid__empty"
12475
- icon="search_off"
12476
- message=${this.localize.term("noResults")}
12477
- ></cx-content-browser-no-result>
12478
- `,
12479
- () => b`
12480
- <lit-virtualizer
12481
- scroller
12482
- style=${o$1({
12483
- height: "100%",
12484
- "overflow-x": "hidden"
12485
- })}
12486
- .layout=${grid({
12487
- gap: `${__privateGet2(this, _gutter)}px`,
12488
- itemSize: {
12489
- height: `${Math.max(this.columnWidth, 150)}px`,
12490
- width: `${this.columnWidth}px`
12491
- },
12492
- flex: { preserve: "aspect-ratio" }
12493
- })}
12494
- .items=${this.assets}
12495
- .renderItem=${this.renderItem}
12496
- @scroll=${this.handleScroll}
12497
- ></lit-virtualizer>
12498
- `
12499
- )}
12550
+ ${this.renderContent()}
12500
12551
  </div>
12501
12552
  </cx-resize-observer>
12502
12553
  `;
@@ -12507,8 +12558,10 @@ _lastHeight = /* @__PURE__ */ new WeakMap();
12507
12558
  _lastWidth = /* @__PURE__ */ new WeakMap();
12508
12559
  CxContentBrowserGrid.styles = [componentStyles, styles$2];
12509
12560
  CxContentBrowserGrid.dependencies = {
12561
+ "cx-button": CxButton,
12510
12562
  "cx-content-browser-asset-card": CxContentBrowserAssetCard,
12511
12563
  "cx-content-browser-no-result": CxContentBrowserNoResult,
12564
+ "cx-icon": CxIcon,
12512
12565
  "cx-progress-bar": CxProgressBar,
12513
12566
  "cx-resize-observer": CxResizeObserver
12514
12567
  };
@@ -12524,6 +12577,9 @@ __decorateClass$2([
12524
12577
  __decorateClass$2([
12525
12578
  n$6({ attribute: "empty", reflect: true, type: Boolean })
12526
12579
  ], CxContentBrowserGrid.prototype, "empty", 2);
12580
+ __decorateClass$2([
12581
+ n$6({ attribute: "error", reflect: true, type: Boolean })
12582
+ ], CxContentBrowserGrid.prototype, "error", 2);
12527
12583
  __decorateClass$2([
12528
12584
  n$6({ attribute: "view", reflect: true, type: String })
12529
12585
  ], CxContentBrowserGrid.prototype, "view", 2);
@@ -12872,6 +12928,17 @@ function resolveAssetExtraFilters(selectedFacets) {
12872
12928
  function isCortexErrorResponse(response) {
12873
12929
  return response && typeof response === "object" && "ErrorCode" in response;
12874
12930
  }
12931
+ function isSearchFacet(facet) {
12932
+ const details = facet == null ? void 0 : facet.facetDetails;
12933
+ return !!facet && !!details && typeof details === "object" && !Array.isArray(details) && typeof details.facetFieldName === "string" && typeof details.displayName === "string" && Array.isArray(facet.values) && facet.values.every((facetValue) => !!facetValue && typeof facetValue.value === "string");
12934
+ }
12935
+ function isSearchResponse(response) {
12936
+ if (!response || typeof response !== "object" || Array.isArray(response)) {
12937
+ return false;
12938
+ }
12939
+ const { contentItems, facets, totalCount } = response;
12940
+ return Array.isArray(facets) && facets.every(isSearchFacet) && Number.isFinite(totalCount) && (contentItems === void 0 || Array.isArray(contentItems));
12941
+ }
12875
12942
  const POST_UNSUPPORTED_STATUSES = /* @__PURE__ */ new Set([405, 501]);
12876
12943
  const postUnsupportedOrigins = /* @__PURE__ */ new Set();
12877
12944
  function createId() {
@@ -13244,6 +13311,14 @@ function apiGetAssets(_0) {
13244
13311
  ...Array.isArray(http.defaults.transformResponse) ? http.defaults.transformResponse : [],
13245
13312
  (rawResponse) => {
13246
13313
  var _a2, _b2;
13314
+ if (!isSearchResponse(rawResponse)) {
13315
+ return {
13316
+ facets: [],
13317
+ isError: true,
13318
+ items: [],
13319
+ totalCount: 0
13320
+ };
13321
+ }
13247
13322
  const mappedItems = (_b2 = (_a2 = rawResponse.contentItems) == null ? void 0 : _a2.map((item) => {
13248
13323
  var _a3, _b3, _c2, _d2, _e2, _f2, _g, _h, _i, _j, _k, _l;
13249
13324
  let extension = (_a3 = item.fields[FIELD_EXTENSION]) != null ? _a3 : "";
@@ -13272,6 +13347,7 @@ function apiGetAssets(_0) {
13272
13347
  })) != null ? _b2 : [];
13273
13348
  return {
13274
13349
  facets: rawResponse.facets,
13350
+ isError: false,
13275
13351
  items: mappedItems,
13276
13352
  totalCount: rawResponse.totalCount
13277
13353
  };
@@ -13283,6 +13359,7 @@ function apiGetAssets(_0) {
13283
13359
  } catch (error) {
13284
13360
  return {
13285
13361
  facets: [],
13362
+ isError: true,
13286
13363
  items: [],
13287
13364
  totalCount: 0
13288
13365
  };
@@ -13780,6 +13857,7 @@ class FetchAndMergeAssetsController {
13780
13857
  this.items = [];
13781
13858
  this.totalCount = 0;
13782
13859
  this.lastRequest = null;
13860
+ this.failedRequest = null;
13783
13861
  this.sortOrders = {};
13784
13862
  this.parameters = null;
13785
13863
  this.availableExtensions = null;
@@ -14005,6 +14083,14 @@ class FetchAndMergeAssetsController {
14005
14083
  return yield apiGetFolders(request);
14006
14084
  });
14007
14085
  }
14086
+ /** Sends the last search that got an error again, with the same page and controls. */
14087
+ retrySearch() {
14088
+ return __async(this, null, function* () {
14089
+ if (this.failedRequest) {
14090
+ yield this.fetchAndMergeAssets(this.failedRequest);
14091
+ }
14092
+ });
14093
+ }
14008
14094
  /**
14009
14095
  * A folder switch (or any refetch) can return a facet list that no longer includes a
14010
14096
  * currently-selected value. Keep those selected-but-missing values visible (count 0) instead
@@ -14051,6 +14137,7 @@ class FetchAndMergeAssetsController {
14051
14137
  }
14052
14138
  const generation = __privateGet(this, _generation);
14053
14139
  this.loading = true;
14140
+ this.failedRequest = null;
14054
14141
  this.host.requestUpdate();
14055
14142
  if (this._debounceTimeout) {
14056
14143
  clearTimeout(this._debounceTimeout);
@@ -14105,17 +14192,25 @@ class FetchAndMergeAssetsController {
14105
14192
  if (generation !== __privateGet(this, _generation)) {
14106
14193
  return;
14107
14194
  }
14108
- if (isRestart) {
14109
- this.items = assets.items;
14195
+ if (assets.isError) {
14196
+ this.failedRequest = request;
14197
+ if (isRestart) {
14198
+ this.items = [];
14199
+ this.totalCount = 0;
14200
+ }
14110
14201
  } else {
14111
- this.items = uniqBy([...this.items, ...assets.items], "recordId");
14202
+ if (isRestart) {
14203
+ this.items = assets.items;
14204
+ } else {
14205
+ this.items = uniqBy([...this.items, ...assets.items], "recordId");
14206
+ }
14207
+ this.facets = this.mergeFacetsWithSelected(assets.facets, this.facets, request.selectedFacets);
14208
+ this.totalCount = assets.totalCount;
14209
+ __privateSet(this, _lastPage, {
14210
+ pageSize: request.pageSize || assets.items.length,
14211
+ start: (_g = request.start) != null ? _g : 0
14212
+ });
14112
14213
  }
14113
- this.facets = this.mergeFacetsWithSelected(assets.facets, this.facets, request.selectedFacets);
14114
- this.totalCount = assets.totalCount;
14115
- __privateSet(this, _lastPage, {
14116
- pageSize: request.pageSize || assets.items.length,
14117
- start: (_g = request.start) != null ? _g : 0
14118
- });
14119
14214
  __privateSet(this, _hasFetchedOnce, true);
14120
14215
  if (this._debounceResolve) {
14121
14216
  this._debounceResolve(this.lastRequest);
@@ -14326,6 +14421,7 @@ class FetchAndMergeAssetsController {
14326
14421
  ) : (_b2 = this.parameters.supportedRepresentativeSubtypes) != null ? _b2 : []
14327
14422
  }) : null,
14328
14423
  request: this.lastRequest,
14424
+ searchError: this.failedRequest !== null,
14329
14425
  sortOrders: this.sortOrders,
14330
14426
  totalCount: this.totalCount,
14331
14427
  userInfo: this.userInfo
@@ -14695,6 +14791,9 @@ let CxContentBrowser = class extends CortexElement {
14695
14791
  }
14696
14792
  handleScrollEnd() {
14697
14793
  return __async(this, null, function* () {
14794
+ if (this.fetchAndMergeAssetsController.getData().searchError) {
14795
+ return;
14796
+ }
14698
14797
  const nextPage = this.fetchAndMergeAssetsController.getNextPage();
14699
14798
  if (!nextPage) {
14700
14799
  return;
@@ -14752,9 +14851,9 @@ let CxContentBrowser = class extends CortexElement {
14752
14851
  if (!nextPage) {
14753
14852
  return;
14754
14853
  }
14755
- const totalCount = this.fetchAndMergeAssetsController.getData().totalCount;
14854
+ const { searchError, totalCount } = this.fetchAndMergeAssetsController.getData();
14756
14855
  const newStart = nextPage.start;
14757
- if (newPageSize <= nextPage.lastPageSize || newPageSize === 0 || newStart > totalCount) {
14856
+ if (searchError || newPageSize <= nextPage.lastPageSize || newPageSize === 0 || newStart > totalCount) {
14758
14857
  return;
14759
14858
  }
14760
14859
  this.lastRequest = __spreadProps(__spreadValues({}, this.lastRequest), {
@@ -14780,6 +14879,11 @@ let CxContentBrowser = class extends CortexElement {
14780
14879
  }
14781
14880
  });
14782
14881
  }
14882
+ handleRetry() {
14883
+ return __async(this, null, function* () {
14884
+ yield this.fetchAndMergeAssetsController.retrySearch();
14885
+ });
14886
+ }
14783
14887
  handleGridClick(event) {
14784
14888
  return __async(this, null, function* () {
14785
14889
  const { id } = event.detail;
@@ -14960,6 +15064,7 @@ let CxContentBrowser = class extends CortexElement {
14960
15064
  loading,
14961
15065
  parameters,
14962
15066
  request,
15067
+ searchError,
14963
15068
  sortOrders,
14964
15069
  totalCount,
14965
15070
  userInfo
@@ -15048,7 +15153,8 @@ let CxContentBrowser = class extends CortexElement {
15048
15153
  ></cx-content-browser-control-bar>
15049
15154
  <cx-content-browser-grid
15050
15155
  .assets=${items}
15051
- ?empty=${!loading && !this.initialFolderPending && items.length === 0}
15156
+ ?empty=${!loading && !this.initialFolderPending && !searchError && items.length === 0}
15157
+ ?error=${searchError}
15052
15158
  ?has-more=${items.length < totalCount}
15053
15159
  ?loading=${loading || this.initialFolderPending}
15054
15160
  ?show-title=${this.showTitle}
@@ -15059,6 +15165,7 @@ let CxContentBrowser = class extends CortexElement {
15059
15165
  view=${this.view}
15060
15166
  @cx-content-browser-grid-scroll-end=${this.handleScrollEnd}
15061
15167
  @cx-content-browser-grid-resize=${this.handleGridResize}
15168
+ @cx-content-browser-grid-retry=${this.handleRetry}
15062
15169
  @cx-content-browser-grid-click=${this.handleGridClick}
15063
15170
  ></cx-content-browser-grid>
15064
15171
  </cx-resize-observer>
@@ -0,0 +1,6 @@
1
+ export type CxContentBrowserGridRetryEvent = CustomEvent<Record<PropertyKey, never>>;
2
+ declare global {
3
+ interface GlobalEventHandlersEventMap {
4
+ 'cx-content-browser-grid-retry': CxContentBrowserGridRetryEvent;
5
+ }
6
+ }
@@ -13,6 +13,7 @@ export * from './cx-content-browser-format-dialog-proxy-confirm';
13
13
  export * from './cx-content-browser-format-dialog-version-history-open';
14
14
  export * from './cx-content-browser-grid-click';
15
15
  export * from './cx-content-browser-grid-resize';
16
+ export * from './cx-content-browser-grid-retry';
16
17
  export * from './cx-content-browser-grid-scroll-end';
17
18
  export * from './cx-content-browser-header-close';
18
19
  export * from './cx-content-browser-header-logout';