@fluid-topics/ft-wc-utils 1.2.2 → 1.2.3

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.
@@ -1,14 +1,20 @@
1
1
  import { CancelablePromise } from "./CancelablePromise";
2
+ import { WithEventBus } from "./events";
3
+ export declare class ClearCacheEvent extends CustomEvent<{
4
+ clearedKeys: string[];
5
+ }> {
6
+ constructor(clearedKeys: string[]);
7
+ }
2
8
  export type CachedContent<T = any> = undefined | CancelablePromise<T> | T | Error;
3
- export declare class CacheRegistry<T = any> {
9
+ export declare class CacheRegistry<T = any> extends WithEventBus {
4
10
  private loaders;
5
11
  private content;
6
12
  private clearTimeouts;
7
13
  private finalContent;
8
14
  register(key: string, loader: () => Promise<T>): void;
9
15
  registerFinal(key: string, loader: () => Promise<T>): void;
10
- clearAll(): void;
11
- clear(key: string): void;
16
+ clearAll(dispatchEvent?: boolean): void;
17
+ clear(key: string, dispatchEvent?: boolean): string | undefined;
12
18
  private forceClear;
13
19
  private clearClearTimeout;
14
20
  set(key: string, value: T): void;
@@ -1,6 +1,13 @@
1
1
  import { cancelable, CancelablePromise } from "./CancelablePromise";
2
- export class CacheRegistry {
2
+ import { WithEventBus } from "./events";
3
+ export class ClearCacheEvent extends CustomEvent {
4
+ constructor(clearedKeys) {
5
+ super("clear-cache", { detail: { clearedKeys } });
6
+ }
7
+ }
8
+ export class CacheRegistry extends WithEventBus {
3
9
  constructor() {
10
+ super(...arguments);
4
11
  this.loaders = {};
5
12
  this.content = {};
6
13
  this.clearTimeouts = {};
@@ -14,15 +21,26 @@ export class CacheRegistry {
14
21
  this.loaders[key] = loader;
15
22
  this.finalContent.add(key);
16
23
  }
17
- clearAll() {
24
+ clearAll(dispatchEvent = true) {
25
+ const clearedKeys = [];
18
26
  for (let key in this.content) {
19
- this.clear(key);
27
+ if (this.clear(key, false) != undefined) {
28
+ clearedKeys.push(key);
29
+ }
30
+ }
31
+ if (dispatchEvent && clearedKeys.length > 0) {
32
+ this.dispatchEvent(new ClearCacheEvent(clearedKeys));
20
33
  }
21
34
  }
22
- clear(key) {
35
+ clear(key, dispatchEvent = true) {
23
36
  if (!this.finalContent.has(key)) {
24
37
  this.forceClear(key);
38
+ if (dispatchEvent) {
39
+ this.dispatchEvent(new ClearCacheEvent([key]));
40
+ }
41
+ return key;
25
42
  }
43
+ return undefined;
26
44
  }
27
45
  forceClear(key) {
28
46
  this.clearClearTimeout(key);
@@ -14,16 +14,21 @@ export declare enum SearchPlaceQueryParams {
14
14
  VALUE_FILTERS = "value-filters",
15
15
  DATE_FILTERS = "date-filters",
16
16
  RANGE_FILTERS = "range-filters",
17
- SORT = "sort"
17
+ SORT = "sort",
18
+ PER_PAGE = "per-page"
18
19
  }
19
20
  export declare function isSearchPlaceQueryParams(param: string): param is SearchPlaceQueryParams;
20
21
  export declare class SearchPlaceConverter {
21
22
  private readonly baseUrl;
22
23
  private readonly predefinedSorts;
24
+ private readonly defaultPerPage;
25
+ private readonly allLanguagesAllowed;
26
+ private readonly defaultContentLocale;
23
27
  private readonly scopeMapping;
24
- constructor(baseUrl: string, predefinedSorts: Record<string, Array<FtSearchSortCriterion>>);
28
+ constructor(baseUrl: string, predefinedSorts?: Record<string, Array<FtSearchSortCriterion>>, defaultPerPage?: number, allLanguagesAllowed?: boolean, defaultContentLocale?: string);
25
29
  serialize(request: EnrichedFtSearchRequest, searchPage?: string): string;
26
- toURLSearchParams(request: EnrichedFtSearchRequest): URLSearchParams;
30
+ serializeToCurrentPageIfPossible(request: EnrichedFtSearchRequest, searchPage?: string): string;
31
+ toURLSearchParams(request: EnrichedFtSearchRequest, omitContentLocaleIfDefault?: boolean): URLSearchParams;
27
32
  parse(url: string): EnrichedFtSearchRequest;
28
33
  fromURLSearchParams(params: URLSearchParams): EnrichedFtSearchRequest;
29
34
  private parseCompatFilters;
@@ -1,4 +1,5 @@
1
1
  import { FtDateFilterType, isFtDateFilterType, isFtVirtualField } from "@fluid-topics/public-api";
2
+ import { minmax } from "./helpers";
2
3
  function quote(value) {
3
4
  return `"${value}"`;
4
5
  }
@@ -10,7 +11,7 @@ function unquote(value) {
10
11
  }
11
12
  /** @deprecated replace with SearchPlaceConverter.serialize */
12
13
  export function serializeRequest(baseUrl, request) {
13
- return new SearchPlaceConverter(baseUrl, {}).serialize(request);
14
+ return new SearchPlaceConverter(baseUrl).serialize(request);
14
15
  }
15
16
  export var SearchPlaceQueryParams;
16
17
  (function (SearchPlaceQueryParams) {
@@ -24,15 +25,19 @@ export var SearchPlaceQueryParams;
24
25
  SearchPlaceQueryParams["DATE_FILTERS"] = "date-filters";
25
26
  SearchPlaceQueryParams["RANGE_FILTERS"] = "range-filters";
26
27
  SearchPlaceQueryParams["SORT"] = "sort";
28
+ SearchPlaceQueryParams["PER_PAGE"] = "per-page";
27
29
  })(SearchPlaceQueryParams || (SearchPlaceQueryParams = {}));
28
30
  const SearchPlaceQueryParamsValues = new Set(Object.values(SearchPlaceQueryParams));
29
31
  export function isSearchPlaceQueryParams(param) {
30
32
  return SearchPlaceQueryParamsValues.has(param);
31
33
  }
32
34
  export class SearchPlaceConverter {
33
- constructor(baseUrl, predefinedSorts) {
35
+ constructor(baseUrl, predefinedSorts = {}, defaultPerPage = 20, allLanguagesAllowed = false, defaultContentLocale = "en-US") {
34
36
  this.baseUrl = baseUrl;
35
37
  this.predefinedSorts = predefinedSorts;
38
+ this.defaultPerPage = defaultPerPage;
39
+ this.allLanguagesAllowed = allLanguagesAllowed;
40
+ this.defaultContentLocale = defaultContentLocale;
36
41
  this.scopeMapping = {
37
42
  "documents": "DOCUMENTS",
38
43
  "topics": "ALL_TOPICS",
@@ -43,16 +48,28 @@ export class SearchPlaceConverter {
43
48
  ["_", "\\\\\\\\_", "[ft-escaped-underscore-character]"],
44
49
  ];
45
50
  }
46
- serialize(request, searchPage = `/search`) {
51
+ serialize(request, searchPage) {
52
+ return this.serializeToCurrentPageIfPossible(request, searchPage !== null && searchPage !== void 0 ? searchPage : "/search");
53
+ }
54
+ serializeToCurrentPageIfPossible(request, searchPage) {
47
55
  const queryParams = this.toURLSearchParams(request).toString();
48
- return new URL(`${this.baseUrl.replace(/\/+$/, "")}${searchPage}?${queryParams}`).href;
49
- }
50
- toURLSearchParams(request) {
51
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
52
- const params = new URLSearchParams({
53
- [SearchPlaceQueryParams.LOCALE]: (_a = request.contentLocale) !== null && _a !== void 0 ? _a : "all",
54
- });
55
- if (((_b = request.query) === null || _b === void 0 ? void 0 : _b.length) > 0) {
56
+ const useCurrenLocation = searchPage == null || searchPage.trim().length === 0;
57
+ const url = new URL(useCurrenLocation ? window.location.href : `${this.baseUrl.replace(/\/+$/, "")}${searchPage}`);
58
+ url.search = queryParams;
59
+ return url.toString();
60
+ }
61
+ toURLSearchParams(request, omitContentLocaleIfDefault = false) {
62
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
63
+ const params = new URLSearchParams();
64
+ if (request.contentLocale) {
65
+ if (!omitContentLocaleIfDefault || request.contentLocale !== this.defaultContentLocale) {
66
+ params.append(SearchPlaceQueryParams.LOCALE, request.contentLocale);
67
+ }
68
+ }
69
+ else {
70
+ params.append(SearchPlaceQueryParams.LOCALE, this.allLanguagesAllowed ? "all" : this.defaultContentLocale);
71
+ }
72
+ if (((_a = request.query) === null || _a === void 0 ? void 0 : _a.length) > 0) {
56
73
  params.append(SearchPlaceQueryParams.QUERY, request.query);
57
74
  }
58
75
  if (request.scope && request.scope !== "DEFAULT") {
@@ -61,37 +78,40 @@ export class SearchPlaceConverter {
61
78
  if (request.virtualField && request.virtualField !== "EVERYWHERE") {
62
79
  params.append(SearchPlaceQueryParams.VIRTUAL_FIELD, request.virtualField.toLowerCase());
63
80
  }
64
- if (((_c = request.sort) === null || _c === void 0 ? void 0 : _c.length) > 0 && request.sort[0].key === "ft:lastEdition") {
81
+ if (((_b = request.sort) === null || _b === void 0 ? void 0 : _b.length) > 0 && request.sort[0].key === "ft:lastEdition") {
65
82
  params.append(SearchPlaceQueryParams.SORT, "last_update");
66
83
  }
67
- const valueFilters = (_e = (_d = request.metadataFilters) === null || _d === void 0 ? void 0 : _d.filter(f => f.valueFilter)) !== null && _e !== void 0 ? _e : [];
84
+ const valueFilters = (_d = (_c = request.metadataFilters) === null || _c === void 0 ? void 0 : _c.filter(f => f.valueFilter)) !== null && _d !== void 0 ? _d : [];
68
85
  if (valueFilters.length > 0) {
69
86
  const serializedValues = valueFilters.map(f => {
70
87
  var _a, _b;
71
88
  const values = ((_b = (_a = f.valueFilter) === null || _a === void 0 ? void 0 : _a.values) !== null && _b !== void 0 ? _b : [])
72
89
  .map(value => this.escapeFilters(value))
73
- .map(value => encodeURIComponent(quote(value)))
90
+ .map(value => encodeURIComponent(quote(unquote(value))))
74
91
  .join("_");
75
92
  return `${f.key}~${values}`;
76
93
  }).join("*");
77
94
  params.append(SearchPlaceQueryParams.VALUE_FILTERS, serializedValues);
78
95
  }
79
- const dateFilters = (_g = (_f = request.metadataFilters) === null || _f === void 0 ? void 0 : _f.filter(f => f.dateFilter)) !== null && _g !== void 0 ? _g : [];
96
+ const dateFilters = (_f = (_e = request.metadataFilters) === null || _e === void 0 ? void 0 : _e.filter(f => f.dateFilter)) !== null && _f !== void 0 ? _f : [];
80
97
  if (dateFilters.length > 0) {
81
98
  const serializedDates = dateFilters.map(f => { var _a; return `${f.key}~${(_a = f.dateFilter) === null || _a === void 0 ? void 0 : _a.type.toLowerCase()}`; })
82
99
  .join("*");
83
100
  params.append(SearchPlaceQueryParams.DATE_FILTERS, serializedDates);
84
101
  }
85
- const rangeFilters = (_j = (_h = request.metadataFilters) === null || _h === void 0 ? void 0 : _h.filter(f => f.rangeFilter)) !== null && _j !== void 0 ? _j : [];
102
+ const rangeFilters = (_h = (_g = request.metadataFilters) === null || _g === void 0 ? void 0 : _g.filter(f => f.rangeFilter)) !== null && _h !== void 0 ? _h : [];
86
103
  if (rangeFilters.length > 0) {
87
104
  const serializedRanges = rangeFilters.map(f => { var _a, _b; return `${f.key}~${(_a = f.rangeFilter) === null || _a === void 0 ? void 0 : _a.from}_${(_b = f.rangeFilter) === null || _b === void 0 ? void 0 : _b.to}`; })
88
105
  .join("*");
89
106
  params.append(SearchPlaceQueryParams.RANGE_FILTERS, serializedRanges);
90
107
  }
91
- const otherQueryParams = (_k = request.otherQueryParams) !== null && _k !== void 0 ? _k : {};
108
+ const otherQueryParams = (_j = request.otherQueryParams) !== null && _j !== void 0 ? _j : {};
92
109
  for (let key in otherQueryParams) {
93
110
  params.append(key, otherQueryParams[key]);
94
111
  }
112
+ if (((_k = request.paging) === null || _k === void 0 ? void 0 : _k.perPage) && ((_m = (_l = request.paging) === null || _l === void 0 ? void 0 : _l.perPage) !== null && _m !== void 0 ? _m : this.defaultPerPage) != this.defaultPerPage) {
113
+ params.append(SearchPlaceQueryParams.PER_PAGE, String(request.paging.perPage));
114
+ }
95
115
  return params;
96
116
  }
97
117
  parse(url) {
@@ -103,9 +123,11 @@ export class SearchPlaceConverter {
103
123
  }
104
124
  fromURLSearchParams(params) {
105
125
  var _a, _b, _c, _d, _e, _f, _g, _h;
126
+ const contentLocale = params.get(SearchPlaceQueryParams.LOCALE) === "all" ? undefined : params.get(SearchPlaceQueryParams.LOCALE);
106
127
  const virtualField = ((_a = params.get(SearchPlaceQueryParams.VIRTUAL_FIELD)) !== null && _a !== void 0 ? _a : "EVERYWHERE").toUpperCase();
107
128
  const sortType = ((_b = params.get(SearchPlaceQueryParams.SORT)) !== null && _b !== void 0 ? _b : "DEFAULT").toUpperCase();
108
129
  const scope = (_c = params.get(SearchPlaceQueryParams.SCOPE)) !== null && _c !== void 0 ? _c : "default";
130
+ const perPage = +((_d = params.get(SearchPlaceQueryParams.PER_PAGE)) !== null && _d !== void 0 ? _d : this.defaultPerPage);
109
131
  const otherQueryParams = {};
110
132
  for (let key of params.keys()) {
111
133
  if (!isSearchPlaceQueryParams(key)) {
@@ -113,14 +135,17 @@ export class SearchPlaceConverter {
113
135
  }
114
136
  }
115
137
  return {
116
- contentLocale: params.get(SearchPlaceQueryParams.LOCALE) === "all" ? undefined : ((_d = params.get(SearchPlaceQueryParams.LOCALE)) !== null && _d !== void 0 ? _d : undefined),
138
+ contentLocale: contentLocale !== null && contentLocale !== void 0 ? contentLocale : (this.allLanguagesAllowed ? undefined : this.defaultContentLocale),
117
139
  query: decodeURIComponent((_e = params.get(SearchPlaceQueryParams.QUERY)) !== null && _e !== void 0 ? _e : ""),
118
140
  scope: (_f = this.scopeMapping[scope]) !== null && _f !== void 0 ? _f : "DEFAULT",
119
141
  virtualField: isFtVirtualField(virtualField) ? virtualField : "EVERYWHERE",
120
142
  sort: (_h = (_g = this.predefinedSorts[sortType]) !== null && _g !== void 0 ? _g : this.predefinedSorts["DEFAULT"]) !== null && _h !== void 0 ? _h : [],
121
143
  metadataFilters: this.parseCompatFilters(params),
122
144
  facets: [],
123
- paging: { page: 1, perPage: 20 },
145
+ paging: {
146
+ page: 1,
147
+ perPage: minmax(1, isNaN(perPage) ? this.defaultPerPage : perPage, 40)
148
+ },
124
149
  otherQueryParams,
125
150
  };
126
151
  }
package/build/events.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { Constructor } from "./generic-types";
1
2
  export type FtNotificationType = "info" | "warning" | "error";
2
3
  export interface FtNotificationEventDetail {
3
4
  type: FtNotificationType;
@@ -12,3 +13,13 @@ export declare class PreResizeEvent extends Event {
12
13
  export declare class PostResizeEvent extends Event {
13
14
  constructor();
14
15
  }
16
+ export interface WithEventBusInterface extends EventTarget {
17
+ eventBus: EventTarget;
18
+ addEventListener<T extends Event = Event>(type: string, callback: (e: T) => void, options?: AddEventListenerOptions | boolean): void;
19
+ removeEventListener<T extends Event = Event>(type: string, callback: (e: T) => void, options?: EventListenerOptions | boolean): void;
20
+ }
21
+ export declare function withEventBus<T extends Constructor>(Base: T, eventBus?: EventTarget): T & Constructor<WithEventBusInterface>;
22
+ declare const WithEventBus_base: ObjectConstructor & Constructor<WithEventBusInterface>;
23
+ export declare class WithEventBus extends WithEventBus_base {
24
+ }
25
+ export {};
package/build/events.js CHANGED
@@ -13,3 +13,22 @@ export class PostResizeEvent extends Event {
13
13
  super("ft-post-resize", { composed: true, bubbles: true });
14
14
  }
15
15
  }
16
+ export function withEventBus(Base, eventBus) {
17
+ return class extends Base {
18
+ constructor() {
19
+ super(...arguments);
20
+ this.eventBus = eventBus !== null && eventBus !== void 0 ? eventBus : document.createElement("span");
21
+ }
22
+ addEventListener(type, callback, options) {
23
+ this.eventBus.addEventListener(type, callback, options);
24
+ }
25
+ dispatchEvent(event) {
26
+ return this.eventBus.dispatchEvent(event);
27
+ }
28
+ removeEventListener(type, callback, options) {
29
+ this.eventBus.removeEventListener(type, callback, options);
30
+ }
31
+ };
32
+ }
33
+ export class WithEventBus extends withEventBus(Object) {
34
+ }
@@ -1,4 +1,4 @@
1
1
  export type Optional<T> = T | null | undefined;
2
- export type Constructor<T> = new (...args: any[]) => T;
2
+ export type Constructor<T = any> = new (...args: any[]) => T;
3
3
  export type Provider<T> = () => T;
4
4
  export type Consumer<T> = (value: T) => any;