@trackunit/filters-asset-filter-definitions 2.24.10 → 2.24.11

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.cjs.js CHANGED
@@ -17,6 +17,7 @@ var reactComponents = require('@trackunit/react-components');
17
17
  var stringTs = require('string-ts');
18
18
  var sharedUtils = require('@trackunit/shared-utils');
19
19
  var translationsMachineType = require('@trackunit/translations-machine-type');
20
+ var graphql = require('graphql');
20
21
  var criticalityIndicator = require('@trackunit/criticality-indicator');
21
22
  var translationsDevice = require('@trackunit/translations-device');
22
23
  var tailwindMerge = require('tailwind-merge');
@@ -269,7 +270,7 @@ const GET_ACCESS_MANAGEMENT_MODE_DESIRED_SUMMARY = client.gql `
269
270
  }
270
271
  }
271
272
  `;
272
- const FETCH_LIMIT$5 = 1000;
273
+ const FETCH_LIMIT = 1000;
273
274
  /**
274
275
  * Maps an access-management-mode value to its static translation key.
275
276
  *
@@ -306,7 +307,7 @@ const AccessManagementModeFilterView = ({ filterDefinition, filterState, filterB
306
307
  const { data, loading } = reactGraphqlHooks.useQuery(GET_ACCESS_MANAGEMENT_MODE_DESIRED_SUMMARY, {
307
308
  fetchPolicy: "cache-first",
308
309
  variables: {
309
- limit: FETCH_LIMIT$5,
310
+ limit: FETCH_LIMIT,
310
311
  filters: {
311
312
  ...activeFilters,
312
313
  accessManagementDesiredModes: null, // Omit the filters own values so list shows options correctly
@@ -5161,29 +5162,6 @@ const asSummaryConnectionNode = (node) => {
5161
5162
  * for a facet. `DefaultCheckboxFilter` pins the option carrying this key to the bottom of the list.
5162
5163
  */
5163
5164
  const UNDEFINED_SUMMARY_KEY = "UNDEFINED";
5164
- /**
5165
- * Flattens connection edges into plain summary entries, appending the bucket of assets without
5166
- * a value when one is reported.
5167
- *
5168
- * @param edges the edges of a key/count summary connection
5169
- * @param missing the number of assets without a value, counted by a separate query
5170
- * @param loading whether either query behind the facet is still fetching, which suppresses the
5171
- * entries until the first page arrives. The two queries resolve independently, and
5172
- * `FilterResults` only renders its loading state for an empty list, so without this a facet
5173
- * would briefly show whichever of the two landed first as its only content — the undefined
5174
- * bucket alone, or a set of values that the undefined bucket is about to be appended to.
5175
- * @returns {Array<{ key: string; count: number }>} the summary entries to render as filter options
5176
- */
5177
- const toSummaryEntries = (edges, missing, loading = false) => {
5178
- if (loading && edges.length === 0) {
5179
- return [];
5180
- }
5181
- const entries = edges.map(edge => asSummaryConnectionNode(edge.node));
5182
- if (typeof missing === "number" && missing > 0) {
5183
- entries.push({ key: UNDEFINED_SUMMARY_KEY, count: missing });
5184
- }
5185
- return entries;
5186
- };
5187
5165
  /**
5188
5166
  * Reads a group summary node.
5189
5167
  *
@@ -5205,6 +5183,11 @@ const asOwnerAccountConnectionNode = (node) => {
5205
5183
  return parsed.success ? parsed.data : { count: 0, ownerAccount: null };
5206
5184
  };
5207
5185
 
5186
+ /**
5187
+ * Stands in for the count document of a facet that has none, since the query hook has to run
5188
+ * unconditionally. It is always skipped, so it is never sent.
5189
+ */
5190
+ const NO_MISSING_COUNT_DOCUMENT = graphql.parse("query FacetWithoutMissingCount { __typename }");
5208
5191
  /**
5209
5192
  * Counts the assets that have no value for a facet.
5210
5193
  *
@@ -5212,16 +5195,16 @@ const asOwnerAccountConnectionNode = (node) => {
5212
5195
  * the facet search term and outside paging, so it is identical on every page and would only be
5213
5196
  * re-fetched for nothing if it rode along with the paginated query.
5214
5197
  *
5215
- * @param document the generated `…SummaryMissing` query
5198
+ * @param document the generated `…SummaryMissing` query, or undefined for a facet without a missing row
5216
5199
  * @param connectionField name of the connection field on `assetSummary`
5217
5200
  * @param filters the filters scoping the summary, the same ones the paginated query uses
5218
5201
  * @param options optional skip flag and Apollo context
5219
5202
  * @returns {object} the count of assets without a value, plus loading state
5220
5203
  */
5221
5204
  const useFacetMissingCount = (document, connectionField, filters, options = {}) => {
5222
- const { data, loading } = reactGraphqlHooks.useQuery(document, {
5205
+ const { data, loading } = reactGraphqlHooks.useQuery(document ?? NO_MISSING_COUNT_DOCUMENT, {
5223
5206
  variables: { filters: filters ?? null },
5224
- skip: options.skip,
5207
+ skip: options.skip || document === undefined,
5225
5208
  context: options.context,
5226
5209
  });
5227
5210
  const missing = react.useMemo(() => extractAssetSummaryConnection(data, connectionField)?.missing, [data, connectionField]);
@@ -5273,29 +5256,62 @@ const useFleetSummaryConnection = (document, connectionField, queryVariables, op
5273
5256
  }), [connectionData, edges, loading, pagination]);
5274
5257
  };
5275
5258
 
5259
+ /**
5260
+ * Everything `DefaultCheckboxFilter` needs for a facet backed by a paginated `assetSummary` connection:
5261
+ * the shared search box, the paged options with the optional missing row, and the loading state.
5262
+ *
5263
+ * `loading` is only true while there is nothing to show yet, so refreshing a list on screen does not
5264
+ * flash the loading state.
5265
+ *
5266
+ * @param filterState the filter state handed to the filter view
5267
+ * @param config the facet's data source and how its nodes become options
5268
+ * @returns {object} props to spread into `DefaultCheckboxFilter`
5269
+ */
5270
+ const useFacetConnectionOptions = (filterState, config) => {
5271
+ const activeFilters = filtersGraphqlHook.useActiveAssetFilters(filterState.values);
5272
+ const { debouncedSearch, customSearch } = filtersFilterBar.useFilterSearch();
5273
+ const filters = config.scope(activeFilters);
5274
+ const { edges, loading: loadingValues, pagination, } = useFleetSummaryConnection(config.document, config.connectionField, { search: debouncedSearch, filters }, { context: config.context });
5275
+ const { missing, loading: loadingMissing } = useFacetMissingCount(config.missing?.document, config.connectionField, filters, { context: config.context });
5276
+ const loading = loadingValues || loadingMissing;
5277
+ // Reading a node validates it, so it is memoized on the pages alone: callers usually pass the
5278
+ // config inline, which reruns the cheap option mapping below on every render.
5279
+ const read = config.node?.read;
5280
+ const customNodes = react.useMemo(() => (read ? edges.map(edge => read(edge.node)) : []), [edges, read]);
5281
+ const summaryEntries = react.useMemo(() => (read ? [] : edges.map(edge => asSummaryConnectionNode(edge.node))), [edges, read]);
5282
+ const options = react.useMemo(() => {
5283
+ // The two queries resolve independently, so until the first page is in, show nothing rather
5284
+ // than whichever of the values or the missing row happened to land first.
5285
+ if (loading && edges.length === 0) {
5286
+ return [];
5287
+ }
5288
+ const missingRow = config.missing && typeof missing === "number" && missing > 0
5289
+ ? { key: UNDEFINED_SUMMARY_KEY, count: missing }
5290
+ : undefined;
5291
+ const facetOptions = config.node === undefined
5292
+ ? (missingRow ? [...summaryEntries, missingRow] : summaryEntries).map(config.toOption)
5293
+ : [
5294
+ ...customNodes.map(config.node.toOption),
5295
+ ...(config.missing && missingRow ? [{ ...missingRow, label: config.missing.label }] : []),
5296
+ ];
5297
+ return config.showCount === false ? facetOptions.map(option => ({ ...option, count: undefined })) : facetOptions;
5298
+ }, [config, customNodes, summaryEntries, missing, loading, edges.length]);
5299
+ return react.useMemo(() => ({ customSearch, loading: loading && options.length === 0, options, pagination }), [customSearch, loading, options, pagination]);
5300
+ };
5301
+
5276
5302
  /**
5277
5303
  * React component for rendering the brand filter.
5278
5304
  */
5279
5305
  const BrandFilterView = (props) => {
5280
5306
  const { getMachineTypeTranslation } = translationsMachineType.useMachineTypeTranslations();
5281
- const activeFilters = filtersGraphqlHook.useActiveAssetFilters(props.filterState.values);
5282
- const [searchText, setSearchText] = react.useState("");
5283
- const debouncedSearch = reactComponents.useDebounce(searchText, { delay: 500 });
5284
- const filters = { ...activeFilters, brands: null };
5285
- const { edges, loading: loadingValues, pagination, } = useFleetSummaryConnection(GetFleetBrandsSummaryConnectionDocument, "brandsConnection", {
5286
- search: debouncedSearch,
5287
- filters,
5307
+ const facet = useFacetConnectionOptions(props.filterState, {
5308
+ document: GetFleetBrandsSummaryConnectionDocument,
5309
+ connectionField: "brandsConnection",
5310
+ scope: filters => ({ ...filters, brands: null }),
5311
+ missing: { document: GetFleetBrandsSummaryMissingDocument },
5312
+ toOption: entry => ({ ...entry, label: getMachineTypeTranslation(entry.key) }),
5288
5313
  });
5289
- const { missing, loading: loadingMissing } = useFacetMissingCount(GetFleetBrandsSummaryMissingDocument, "brandsConnection", filters);
5290
- const loading = loadingValues || loadingMissing;
5291
- const options = react.useMemo(() => {
5292
- return toSummaryEntries(edges, missing, loading).map(entry => ({
5293
- key: entry.key,
5294
- count: entry.count,
5295
- label: getMachineTypeTranslation(entry.key),
5296
- }));
5297
- }, [edges, missing, loading, getMachineTypeTranslation]);
5298
- return (jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, customSearch: { value: searchText, onChange: setSearchText, onClear: () => setSearchText("") }, loading: Boolean(loading && options.length === 0), options: options, pagination: pagination }));
5314
+ return jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, ...facet });
5299
5315
  };
5300
5316
  /**
5301
5317
  * Brand filter definition
@@ -5323,35 +5339,25 @@ const useBrandFilter = () => {
5323
5339
  */
5324
5340
  const Can1ProfileFilter = ({ filterDefinition, filterState, filterBarActions, ...props }) => {
5325
5341
  const [t] = useTranslation();
5326
- const activeFilters = filtersGraphqlHook.useActiveAssetFilters(filterState.values);
5327
- const [searchText, setSearchText] = react.useState("");
5328
- const debouncedSearch = reactComponents.useDebounce(searchText, { delay: 500 });
5329
- const filters = { ...activeFilters, can1Profile: null };
5330
- const { edges, loading: loadingValues, pagination, } = useFleetSummaryConnection(GetFleetCan1ProfileSummaryConnectionDocument, "can1ProfileSummaryConnection", {
5331
- search: debouncedSearch,
5332
- filters,
5333
- });
5334
- const { missing, loading: loadingMissing } = useFacetMissingCount(GetFleetCan1ProfileSummaryMissingDocument, "can1ProfileSummaryConnection", filters);
5335
- const loading = loadingValues || loadingMissing;
5336
5342
  const { data: profileNamesData } = reactGraphqlHooks.useQuery(TelematicsDeviceCan1ProfileNamesDocument, {
5337
5343
  context: { headers: { "TU-PREVIEW": "TELEMATICS_DEVICE_PREVIEW" } },
5338
5344
  fetchPolicy: "cache-first",
5339
5345
  });
5340
5346
  const profileNameByKey = react.useMemo(() => new Map(profileNamesData?.telematicsDeviceSummary?.can1Profiles?.summary?.map(profile => [profile.key, profile.name]) ??
5341
5347
  []), [profileNamesData?.telematicsDeviceSummary?.can1Profiles?.summary]);
5342
- const options = react.useMemo(() => {
5343
- return toSummaryEntries(edges, missing, loading).map(entry => {
5344
- if (entry.key === UNDEFINED_SUMMARY_KEY) {
5345
- return { key: entry.key, count: entry.count, label: t(`machine.types.Unknown`) };
5346
- }
5347
- return {
5348
- key: entry.key,
5349
- count: entry.count,
5350
- label: profileNameByKey.get(entry.key) ?? entry.key,
5351
- };
5352
- });
5353
- }, [edges, missing, loading, profileNameByKey, t]);
5354
- return (jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, customSearch: { value: searchText, onChange: setSearchText, onClear: () => setSearchText("") }, filterBarActions: filterBarActions, filterDefinition: filterDefinition, filterState: filterState, loading: Boolean(loading && options.length === 0), options: options, pagination: pagination }));
5348
+ const facet = useFacetConnectionOptions(filterState, {
5349
+ document: GetFleetCan1ProfileSummaryConnectionDocument,
5350
+ connectionField: "can1ProfileSummaryConnection",
5351
+ scope: filters => ({ ...filters, can1Profile: null }),
5352
+ missing: { document: GetFleetCan1ProfileSummaryMissingDocument },
5353
+ toOption: entry => ({
5354
+ ...entry,
5355
+ label: entry.key === UNDEFINED_SUMMARY_KEY
5356
+ ? t(`machine.types.Unknown`)
5357
+ : (profileNameByKey.get(entry.key) ?? entry.key),
5358
+ }),
5359
+ });
5360
+ return (jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, ...facet, filterBarActions: filterBarActions, filterDefinition: filterDefinition, filterState: filterState }));
5355
5361
  };
5356
5362
 
5357
5363
  /**
@@ -5377,35 +5383,25 @@ const useCan1ProfileFilter = () => {
5377
5383
  */
5378
5384
  const Can2ProfileFilter = ({ filterDefinition, filterState, filterBarActions, ...props }) => {
5379
5385
  const [t] = useTranslation();
5380
- const activeFilters = filtersGraphqlHook.useActiveAssetFilters(filterState.values);
5381
- const [searchText, setSearchText] = react.useState("");
5382
- const debouncedSearch = reactComponents.useDebounce(searchText, { delay: 500 });
5383
- const filters = { ...activeFilters, can2Profile: null };
5384
- const { edges, loading: loadingValues, pagination, } = useFleetSummaryConnection(GetFleetCan2ProfileSummaryConnectionDocument, "can2ProfileSummaryConnection", {
5385
- search: debouncedSearch,
5386
- filters,
5387
- });
5388
- const { missing, loading: loadingMissing } = useFacetMissingCount(GetFleetCan2ProfileSummaryMissingDocument, "can2ProfileSummaryConnection", filters);
5389
- const loading = loadingValues || loadingMissing;
5390
5386
  const { data: profileNamesData } = reactGraphqlHooks.useQuery(TelematicsDeviceCan2ProfileNamesDocument, {
5391
5387
  context: { headers: { "TU-PREVIEW": "TELEMATICS_DEVICE_PREVIEW" } },
5392
5388
  fetchPolicy: "cache-first",
5393
5389
  });
5394
5390
  const profileNameByKey = react.useMemo(() => new Map(profileNamesData?.telematicsDeviceSummary?.can2Profiles?.summary?.map(profile => [profile.key, profile.name]) ??
5395
5391
  []), [profileNamesData?.telematicsDeviceSummary?.can2Profiles?.summary]);
5396
- const options = react.useMemo(() => {
5397
- return toSummaryEntries(edges, missing, loading).map(entry => {
5398
- if (entry.key === UNDEFINED_SUMMARY_KEY) {
5399
- return { key: entry.key, count: entry.count, label: t(`machine.types.Unknown`) };
5400
- }
5401
- return {
5402
- key: entry.key,
5403
- count: entry.count,
5404
- label: profileNameByKey.get(entry.key) ?? entry.key,
5405
- };
5406
- });
5407
- }, [edges, missing, loading, profileNameByKey, t]);
5408
- return (jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, customSearch: { value: searchText, onChange: setSearchText, onClear: () => setSearchText("") }, filterBarActions: filterBarActions, filterDefinition: filterDefinition, filterState: filterState, loading: Boolean(loading && options.length === 0), options: options, pagination: pagination }));
5392
+ const facet = useFacetConnectionOptions(filterState, {
5393
+ document: GetFleetCan2ProfileSummaryConnectionDocument,
5394
+ connectionField: "can2ProfileSummaryConnection",
5395
+ scope: filters => ({ ...filters, can2Profile: null }),
5396
+ missing: { document: GetFleetCan2ProfileSummaryMissingDocument },
5397
+ toOption: entry => ({
5398
+ ...entry,
5399
+ label: entry.key === UNDEFINED_SUMMARY_KEY
5400
+ ? t(`machine.types.Unknown`)
5401
+ : (profileNameByKey.get(entry.key) ?? entry.key),
5402
+ }),
5403
+ });
5404
+ return (jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, ...facet, filterBarActions: filterBarActions, filterDefinition: filterDefinition, filterState: filterState }));
5409
5405
  };
5410
5406
 
5411
5407
  /**
@@ -5703,22 +5699,50 @@ const useCriticalityFilter = () => {
5703
5699
  return result;
5704
5700
  };
5705
5701
 
5706
- const FETCH_LIMIT$4 = 1000;
5702
+ /** How many rows a limited facet fetches. A full page means there may be more, so the user is asked to search. */
5703
+ const FACET_FETCH_LIMIT = 1000;
5704
+ /**
5705
+ * Supplies a `DefaultCheckboxFilter` whose options come from one summary query capped at
5706
+ * {@link FACET_FETCH_LIMIT} rows. The search text is sent as typed once debounced.
5707
+ *
5708
+ * @param filterState the filter view's state, used to resolve the active asset filters
5709
+ * @param config which query to run and how to turn its rows into options
5710
+ * @returns {object} props to spread onto `DefaultCheckboxFilter`; `loading` is only true while there are no options yet
5711
+ */
5712
+ const useFacetLimitedOptions = (filterState, config) => {
5713
+ const activeFilters = filtersGraphqlHook.useActiveAssetFilters(filterState.values);
5714
+ const { debouncedSearch, customSearch } = filtersFilterBar.useFilterSearch();
5715
+ const { data, loading } = reactGraphqlHooks.useQuery(config.document, {
5716
+ fetchPolicy: "cache-first",
5717
+ variables: { limit: FACET_FETCH_LIMIT, search: debouncedSearch, filters: config.scope(activeFilters) },
5718
+ });
5719
+ const options = react.useMemo(() => {
5720
+ const items = data ? (config.read(data) ?? []) : [];
5721
+ const facetOptions = items.map(item => config.toOption(item));
5722
+ return config.showCount === false ? facetOptions.map(option => ({ ...option, count: undefined })) : facetOptions;
5723
+ }, [config, data]);
5724
+ return react.useMemo(() => ({
5725
+ customSearch,
5726
+ loading: loading && options.length === 0,
5727
+ options,
5728
+ showRequestMoreUseSearch: options.length === FACET_FETCH_LIMIT,
5729
+ }), [customSearch, loading, options]);
5730
+ };
5731
+
5707
5732
  /**
5708
5733
  * Custom hook to fetch customer summary data based on active filters and search text.
5709
5734
  *
5710
5735
  * @param filterValues - The current values from the filter bar.
5711
5736
  * @param customerId - The ID of the customer that owns the customers shown in the filter bar.
5712
- * @returns {object} An object containing the fetched data, loading state, and a function to set search text.
5737
+ * @returns {object} The fetched data, `loading` (only true while there are no customers yet) and the `customSearch` for the filter.
5713
5738
  */
5714
5739
  const useCustomerData = (filterValues, customerId) => {
5715
5740
  const activeFilters = filtersGraphqlHook.useActiveAssetFilters(filterValues);
5716
- const [searchText, setSearchText] = react.useState("");
5717
- const debouncedSearch = reactComponents.useDebounce(searchText, { delay: 500 });
5741
+ const { debouncedSearch, customSearch } = filtersFilterBar.useFilterSearch();
5718
5742
  const { data, loading } = reactGraphqlHooks.useQuery(GetCustomerIdSummaryDocument, {
5719
5743
  fetchPolicy: "cache-first",
5720
5744
  variables: {
5721
- limit: FETCH_LIMIT$4,
5745
+ limit: FACET_FETCH_LIMIT,
5722
5746
  search: debouncedSearch,
5723
5747
  filters: {
5724
5748
  ...activeFilters,
@@ -5726,7 +5750,8 @@ const useCustomerData = (filterValues, customerId) => {
5726
5750
  },
5727
5751
  },
5728
5752
  });
5729
- return react.useMemo(() => ({ data, loading, searchText, setSearchText }), [data, loading, searchText, setSearchText]);
5753
+ const hasCustomers = (data?.assetSummary?.customers?.summary.length ?? 0) > 0;
5754
+ return react.useMemo(() => ({ data, loading: loading && !hasCustomers, customSearch }), [data, loading, hasCustomers, customSearch]);
5730
5755
  };
5731
5756
 
5732
5757
  /**
@@ -5836,13 +5861,10 @@ const useCustomerHierarchy = (customerSummary) => {
5836
5861
  * @returns {ReactElement} A customer ID filter component for rendering in the UI.
5837
5862
  */
5838
5863
  const CustomerIdsFilterView = ({ customerId, hasCount = true, ...props }) => {
5839
- const { data, loading, searchText, setSearchText } = useCustomerData(props.filterState.values, customerId);
5864
+ const { data, loading, customSearch } = useCustomerData(props.filterState.values, customerId);
5840
5865
  const hierarchicalOptions = useCustomerHierarchy(data?.assetSummary?.customers?.summary);
5841
5866
  const valueNameArrayFilterDefinition = props.filterDefinition;
5842
- return (jsxRuntime.jsx(filtersFilterBar.HierarchicalCheckboxFilter, { cascadeSelection: true, customSearch: {
5843
- value: searchText,
5844
- onChange: setSearchText,
5845
- }, filterBarActions: props.filterBarActions, filterDefinition: valueNameArrayFilterDefinition, filterState: props.filterState, loading: loading, options: hierarchicalOptions, setValue: props.setValue, showCount: hasCount, value: props.value }));
5867
+ return (jsxRuntime.jsx(filtersFilterBar.HierarchicalCheckboxFilter, { cascadeSelection: true, customSearch: customSearch, filterBarActions: props.filterBarActions, filterDefinition: valueNameArrayFilterDefinition, filterState: props.filterState, loading: loading, options: hierarchicalOptions, setValue: props.setValue, showCount: hasCount, value: props.value }));
5846
5868
  };
5847
5869
  /**
5848
5870
  * Custom hook to create and configure a customer IDs filter definition.
@@ -6023,6 +6045,21 @@ const useDeviceHealthIssueStatusFilter = (hookProps) => {
6023
6045
  }, [t, hookProps?.deviceHealthStates, hookProps?.deviceHealthDateTimeRange]);
6024
6046
  };
6025
6047
 
6048
+ /**
6049
+ * Supplies a `DefaultCheckboxFilter` whose options are all fetched up front and searched locally.
6050
+ * Matching is on the label, trimmed and case-insensitive, once the search is debounced.
6051
+ *
6052
+ * @param allOptions every option the facet can show
6053
+ * @param loading whether the query behind `allOptions` is loading
6054
+ * @returns {object} props to spread onto `DefaultCheckboxFilter`; `loading` is only true while there are no options yet
6055
+ */
6056
+ const useFacetLocalOptions = (allOptions, loading) => {
6057
+ const { debouncedSearch, customSearch } = filtersFilterBar.useFilterSearch();
6058
+ const needle = debouncedSearch.trim().toLocaleLowerCase();
6059
+ const options = react.useMemo(() => (needle ? allOptions.filter(option => option.label.toLowerCase().includes(needle)) : allOptions), [allOptions, needle]);
6060
+ return react.useMemo(() => ({ customSearch, loading: loading && allOptions.length === 0, options }), [customSearch, loading, allOptions.length, options]);
6061
+ };
6062
+
6026
6063
  /**
6027
6064
  * Get a record of device health issue type display names
6028
6065
  *
@@ -6056,8 +6093,6 @@ const useDeviceHealthIssueTypeDisplayNames = () => {
6056
6093
  const DeviceHealthIssueTypeFilter = ({ deviceHealthStates, deviceHealthDateTimeRange, ...props }) => {
6057
6094
  const issueTypeDisplayNames = useDeviceHealthIssueTypeDisplayNames();
6058
6095
  const filters = filtersGraphqlHook.useActiveAssetFilters(props.filterState.values);
6059
- const [searchQuery, setSearchQuery] = react.useState("");
6060
- const debouncedSearchQuery = reactComponents.useDebounce(searchQuery.trim().toLocaleLowerCase(), { delay: 300 });
6061
6096
  const { data, loading } = reactGraphqlHooks.useQuery(DeviceHealthIssueTypeSummariesDocument, {
6062
6097
  variables: {
6063
6098
  filters: {
@@ -6069,11 +6104,12 @@ const DeviceHealthIssueTypeFilter = ({ deviceHealthStates, deviceHealthDateTimeR
6069
6104
  },
6070
6105
  },
6071
6106
  });
6072
- const { options } = useFleetHealthFilterUtils({
6107
+ const { options: allOptions } = useFleetHealthFilterUtils({
6073
6108
  filterSummaries: data?.assetSummary?.deviceHealthTypesSummary.summary,
6074
6109
  filterTranslations: issueTypeDisplayNames,
6075
6110
  });
6076
- return (jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, customSearch: { value: searchQuery, onChange: setSearchQuery }, loading: loading, options: options.filter(option => option.label.toLowerCase().includes(debouncedSearchQuery)) }));
6111
+ const facet = useFacetLocalOptions(allOptions, loading);
6112
+ return jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, ...facet });
6077
6113
  };
6078
6114
 
6079
6115
  /**
@@ -6104,16 +6140,15 @@ const useDeviceHealthIssueTypeFilter = (hookProps) => {
6104
6140
  const DeviceTypesFilter = (props) => {
6105
6141
  const { deviceTypeDisplayNames } = translationsDevice.useDeviceTypeTranslations();
6106
6142
  const filters = filtersGraphqlHook.useActiveAssetFilters(props.filterState.values);
6107
- const [searchQuery, setSearchQuery] = react.useState("");
6108
- const debouncedSearchQuery = reactComponents.useDebounce(searchQuery.trim().toLocaleLowerCase(), { delay: 300 });
6109
6143
  const { data, loading } = reactGraphqlHooks.useQuery(DeviceTypesSummaryDocument, {
6110
6144
  variables: { filters: { ...filters, deviceTypes: undefined } },
6111
6145
  });
6112
- const { options } = useFleetHealthFilterUtils({
6146
+ const { options: allOptions } = useFleetHealthFilterUtils({
6113
6147
  filterSummaries: data?.assetSummary?.deviceTypesSummary?.summary,
6114
6148
  filterTranslations: deviceTypeDisplayNames,
6115
6149
  });
6116
- return (jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, customSearch: { value: searchQuery, onChange: setSearchQuery }, loading: loading, options: options.filter(option => option.label.toLowerCase().includes(debouncedSearchQuery)) }));
6150
+ const facet = useFacetLocalOptions(allOptions, loading);
6151
+ return jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, ...facet });
6117
6152
  };
6118
6153
 
6119
6154
  /**
@@ -6140,24 +6175,17 @@ const useDeviceTypesFilter = (showInFilterBar) => {
6140
6175
  */
6141
6176
  const FirmwareVersionFilter = ({ filterDefinition, filterState, filterBarActions, ...props }) => {
6142
6177
  const [t] = useTranslation();
6143
- const activeFilters = filtersGraphqlHook.useActiveAssetFilters(filterState.values);
6144
- const [searchText, setSearchText] = react.useState("");
6145
- const debouncedSearch = reactComponents.useDebounce(searchText, { delay: 500 });
6146
- const filters = { ...activeFilters, firmwareVersion: null };
6147
- const { edges, loading: loadingValues, pagination, } = useFleetSummaryConnection(GetFleetFirmwareVersionSummaryConnectionDocument, "firmwareVersionSummaryConnection", {
6148
- search: debouncedSearch,
6149
- filters,
6150
- });
6151
- const { missing, loading: loadingMissing } = useFacetMissingCount(GetFleetFirmwareVersionSummaryMissingDocument, "firmwareVersionSummaryConnection", filters);
6152
- const loading = loadingValues || loadingMissing;
6153
- const options = react.useMemo(() => {
6154
- return toSummaryEntries(edges, missing, loading).map(entry => ({
6155
- key: entry.key,
6156
- count: entry.count,
6178
+ const facet = useFacetConnectionOptions(filterState, {
6179
+ document: GetFleetFirmwareVersionSummaryConnectionDocument,
6180
+ connectionField: "firmwareVersionSummaryConnection",
6181
+ scope: filters => ({ ...filters, firmwareVersion: null }),
6182
+ missing: { document: GetFleetFirmwareVersionSummaryMissingDocument },
6183
+ toOption: entry => ({
6184
+ ...entry,
6157
6185
  label: entry.key === UNDEFINED_SUMMARY_KEY ? t(`machine.types.Unknown`) : entry.key,
6158
- }));
6159
- }, [edges, missing, loading, t]);
6160
- return (jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, customSearch: { value: searchText, onChange: setSearchText, onClear: () => setSearchText("") }, filterBarActions: filterBarActions, filterDefinition: filterDefinition, filterState: filterState, loading: Boolean(loading && options.length === 0), options: options, pagination: pagination }));
6186
+ }),
6187
+ });
6188
+ return (jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, ...facet, filterBarActions: filterBarActions, filterDefinition: filterDefinition, filterState: filterState }));
6161
6189
  };
6162
6190
 
6163
6191
  /**
@@ -6227,38 +6255,22 @@ const useFollowedFilter = () => {
6227
6255
  */
6228
6256
  const GroupIdsFilterView = (props) => {
6229
6257
  const [t] = useTranslation();
6230
- const activeFilters = filtersGraphqlHook.useActiveAssetFilters(props.filterState.values);
6231
- const [searchText, setSearchText] = react.useState("");
6232
- const debouncedSearch = reactComponents.useDebounce(searchText, { delay: 500 });
6233
- const filters = { ...activeFilters, groups: null };
6234
- const { edges, loading: loadingValues, pagination, } = useFleetSummaryConnection(GetFleetGroupSummaryConnectionDocument, "groupsConnection", {
6235
- search: debouncedSearch,
6236
- filters,
6237
- });
6238
- const { missing, loading: loadingMissing } = useFacetMissingCount(GetFleetGroupSummaryMissingDocument, "groupsConnection", filters);
6239
- const loading = loadingValues || loadingMissing;
6240
- const options = react.useMemo(() => {
6241
- if (loading && edges.length === 0) {
6242
- return [];
6243
- }
6244
- const result = edges.map(edge => {
6245
- const node = asGroupConnectionNode(edge.node);
6246
- return {
6258
+ const facet = useFacetConnectionOptions(props.filterState, {
6259
+ document: GetFleetGroupSummaryConnectionDocument,
6260
+ connectionField: "groupsConnection",
6261
+ scope: filters => ({ ...filters, groups: null }),
6262
+ missing: { document: GetFleetGroupSummaryMissingDocument, label: t("assetFilters.groupFilter.missingGroup") },
6263
+ node: {
6264
+ read: asGroupConnectionNode,
6265
+ toOption: node => ({
6247
6266
  key: node.group?.groupId || "unknown",
6248
- count: props.hasCount ? node.count || 0 : undefined,
6267
+ count: node.count || 0,
6249
6268
  label: node.group?.name || t("machine.types.Unknown"),
6250
- };
6251
- });
6252
- if (typeof missing === "number" && missing > 0) {
6253
- result.push({
6254
- key: UNDEFINED_SUMMARY_KEY,
6255
- count: props.hasCount ? missing : undefined,
6256
- label: t("assetFilters.groupFilter.missingGroup"),
6257
- });
6258
- }
6259
- return result;
6260
- }, [edges, missing, loading, props.hasCount, t]);
6261
- return (jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, customSearch: { value: searchText, onChange: setSearchText, onClear: () => setSearchText("") }, loading: Boolean(loading && options.length === 0), options: options, pagination: pagination }));
6269
+ }),
6270
+ },
6271
+ showCount: Boolean(props.hasCount),
6272
+ });
6273
+ return jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, ...facet });
6262
6274
  };
6263
6275
  /**
6264
6276
  * GroupIds filter definition
@@ -7047,16 +7059,6 @@ const useMetadataCompletenessFilter = ({ isDefault } = {}) => {
7047
7059
  */
7048
7060
  const ModbusProfileFilter = ({ filterDefinition, filterState, filterBarActions, ...props }) => {
7049
7061
  const [t] = useTranslation();
7050
- const activeFilters = filtersGraphqlHook.useActiveAssetFilters(filterState.values);
7051
- const [searchText, setSearchText] = react.useState("");
7052
- const debouncedSearch = reactComponents.useDebounce(searchText, { delay: 500 });
7053
- const filters = { ...activeFilters, modbusProfile: null };
7054
- const { edges, loading: loadingValues, pagination, } = useFleetSummaryConnection(GetFleetModbusProfileSummaryConnectionDocument, "modbusProfileSummaryConnection", {
7055
- search: debouncedSearch,
7056
- filters,
7057
- });
7058
- const { missing, loading: loadingMissing } = useFacetMissingCount(GetFleetModbusProfileSummaryMissingDocument, "modbusProfileSummaryConnection", filters);
7059
- const loading = loadingValues || loadingMissing;
7060
7062
  const { data: profileNamesData } = reactGraphqlHooks.useQuery(TelematicsDeviceModbusProfileNamesDocument, {
7061
7063
  context: { headers: { "TU-PREVIEW": "TELEMATICS_DEVICE_PREVIEW" } },
7062
7064
  fetchPolicy: "cache-first",
@@ -7065,19 +7067,19 @@ const ModbusProfileFilter = ({ filterDefinition, filterState, filterBarActions,
7065
7067
  profile.key,
7066
7068
  profile.name,
7067
7069
  ]) ?? []), [profileNamesData?.telematicsDeviceSummary?.modbusProfiles?.summary]);
7068
- const options = react.useMemo(() => {
7069
- return toSummaryEntries(edges, missing, loading).map(entry => {
7070
- if (entry.key === UNDEFINED_SUMMARY_KEY) {
7071
- return { key: entry.key, count: entry.count, label: t(`machine.types.Unknown`) };
7072
- }
7073
- return {
7074
- key: entry.key,
7075
- count: entry.count,
7076
- label: profileNameByKey.get(entry.key) ?? entry.key,
7077
- };
7078
- });
7079
- }, [edges, missing, loading, profileNameByKey, t]);
7080
- return (jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, customSearch: { value: searchText, onChange: setSearchText, onClear: () => setSearchText("") }, filterBarActions: filterBarActions, filterDefinition: filterDefinition, filterState: filterState, loading: Boolean(loading && options.length === 0), options: options, pagination: pagination }));
7070
+ const facet = useFacetConnectionOptions(filterState, {
7071
+ document: GetFleetModbusProfileSummaryConnectionDocument,
7072
+ connectionField: "modbusProfileSummaryConnection",
7073
+ scope: filters => ({ ...filters, modbusProfile: null }),
7074
+ missing: { document: GetFleetModbusProfileSummaryMissingDocument },
7075
+ toOption: entry => ({
7076
+ ...entry,
7077
+ label: entry.key === UNDEFINED_SUMMARY_KEY
7078
+ ? t(`machine.types.Unknown`)
7079
+ : (profileNameByKey.get(entry.key) ?? entry.key),
7080
+ }),
7081
+ });
7082
+ return (jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, ...facet, filterBarActions: filterBarActions, filterDefinition: filterDefinition, filterState: filterState }));
7081
7083
  };
7082
7084
 
7083
7085
  /**
@@ -7107,24 +7109,14 @@ const useModbusProfileFilter = () => {
7107
7109
  */
7108
7110
  const ModelsFilterView = (props) => {
7109
7111
  const { getMachineTypeTranslation } = translationsMachineType.useMachineTypeTranslations();
7110
- const activeFilters = filtersGraphqlHook.useActiveAssetFilters(props.filterState.values);
7111
- const [searchText, setSearchText] = react.useState("");
7112
- const debouncedSearch = reactComponents.useDebounce(searchText, { delay: 500 });
7113
- const filters = { ...activeFilters, models: null };
7114
- const { edges, loading: loadingValues, pagination, } = useFleetSummaryConnection(GetFleetModelsSummaryConnectionDocument, "modelsConnection", {
7115
- search: debouncedSearch,
7116
- filters,
7112
+ const facet = useFacetConnectionOptions(props.filterState, {
7113
+ document: GetFleetModelsSummaryConnectionDocument,
7114
+ connectionField: "modelsConnection",
7115
+ scope: filters => ({ ...filters, models: null }),
7116
+ missing: { document: GetFleetModelsSummaryMissingDocument },
7117
+ toOption: entry => ({ ...entry, label: getMachineTypeTranslation(entry.key) }),
7117
7118
  });
7118
- const { missing, loading: loadingMissing } = useFacetMissingCount(GetFleetModelsSummaryMissingDocument, "modelsConnection", filters);
7119
- const loading = loadingValues || loadingMissing;
7120
- const options = react.useMemo(() => {
7121
- return toSummaryEntries(edges, missing, loading).map(entry => ({
7122
- key: entry.key,
7123
- count: entry.count,
7124
- label: getMachineTypeTranslation(entry.key),
7125
- }));
7126
- }, [edges, missing, loading, getMachineTypeTranslation]);
7127
- return (jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, customSearch: { value: searchText, onChange: setSearchText, onClear: () => setSearchText("") }, loading: Boolean(loading && options.length === 0), options: options, pagination: pagination }));
7119
+ return jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, ...facet });
7128
7120
  };
7129
7121
  /**
7130
7122
  *
@@ -7287,7 +7279,6 @@ const useNameFilter = (props) => {
7287
7279
  return result;
7288
7280
  };
7289
7281
 
7290
- const FETCH_LIMIT$3 = 1000;
7291
7282
  /**
7292
7283
  * Maps a network-technology summary key to its localized label.
7293
7284
  * Falls back to the raw key for values that have no translation yet (e.g. future technologies).
@@ -7322,31 +7313,13 @@ const networkTechnologyLabel = (t, key) => {
7322
7313
  */
7323
7314
  const NetworkTechnologyFilter = ({ filterDefinition, filterState, filterBarActions, ...props }) => {
7324
7315
  const [t] = useTranslation();
7325
- const activeFilters = filtersGraphqlHook.useActiveAssetFilters(filterState.values);
7326
- const [showRequestMoreUseSearch, setShowRequestMoreUseSearch] = react.useState(false);
7327
- const [searchText, setSearchText] = react.useState("");
7328
- const debouncedSearch = reactComponents.useDebounce(searchText, { delay: 500 });
7329
- const { data, loading } = reactGraphqlHooks.useQuery(GetFleetNetworkTechnologySummaryDocument, {
7330
- variables: {
7331
- limit: FETCH_LIMIT$3,
7332
- search: debouncedSearch,
7333
- filters: {
7334
- ...activeFilters,
7335
- networkTechnology: null, // Omit the filter's own values so the list shows all options correctly
7336
- },
7337
- },
7338
- fetchPolicy: "cache-first",
7316
+ const facet = useFacetLimitedOptions(filterState, {
7317
+ document: GetFleetNetworkTechnologySummaryDocument,
7318
+ scope: filters => ({ ...filters, networkTechnology: null }),
7319
+ read: data => data.assetSummary?.networkTechnologySummary?.summary,
7320
+ toOption: networkTechnology => ({ ...networkTechnology, label: networkTechnologyLabel(t, networkTechnology.key) }),
7339
7321
  });
7340
- const options = react.useMemo(() => {
7341
- return (data?.assetSummary?.networkTechnologySummary?.summary.map(networkTechnology => ({
7342
- ...networkTechnology,
7343
- label: networkTechnologyLabel(t, networkTechnology.key),
7344
- })) ?? []);
7345
- }, [data?.assetSummary?.networkTechnologySummary?.summary, t]);
7346
- react.useEffect(() => {
7347
- setShowRequestMoreUseSearch(options.length === FETCH_LIMIT$3);
7348
- }, [options]);
7349
- return (jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, customSearch: { value: searchText, onChange: setSearchText, onClear: () => setSearchText("") }, filterBarActions: filterBarActions, filterDefinition: filterDefinition, filterState: filterState, loading: loading, options: options, showRequestMoreUseSearch: showRequestMoreUseSearch }));
7322
+ return (jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, ...facet, filterBarActions: filterBarActions, filterDefinition: filterDefinition, filterState: filterState }));
7350
7323
  };
7351
7324
 
7352
7325
  /**
@@ -7375,27 +7348,20 @@ const useNetworkTechnologyFilter = () => {
7375
7348
  */
7376
7349
  const OwnerAccountIdsFilterView = (props) => {
7377
7350
  const [t] = useTranslation();
7378
- const activeFilters = filtersGraphqlHook.useActiveAssetFilters(props.filterState.values);
7379
- const [searchText, setSearchText] = react.useState("");
7380
- const debouncedSearch = reactComponents.useDebounce(searchText, { delay: 500 });
7381
- const { edges, loading, pagination } = useFleetSummaryConnection(GetFleetOwnerAccountSummaryConnectionDocument, "ownerAccountsConnection", {
7382
- search: debouncedSearch,
7383
- filters: {
7384
- ...activeFilters,
7385
- ownerAccountIds: null,
7386
- },
7387
- });
7388
- const options = react.useMemo(() => {
7389
- return edges.map(edge => {
7390
- const node = asOwnerAccountConnectionNode(edge.node);
7391
- return {
7351
+ const facet = useFacetConnectionOptions(props.filterState, {
7352
+ document: GetFleetOwnerAccountSummaryConnectionDocument,
7353
+ connectionField: "ownerAccountsConnection",
7354
+ scope: filters => ({ ...filters, ownerAccountIds: null }),
7355
+ node: {
7356
+ read: asOwnerAccountConnectionNode,
7357
+ toOption: node => ({
7392
7358
  key: node.ownerAccount?.accountId || "unknown",
7393
7359
  count: node.count || 0,
7394
7360
  label: node.ownerAccount?.name || t("machine.types.Unknown"),
7395
- };
7396
- });
7397
- }, [edges, t]);
7398
- return (jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, customSearch: { value: searchText, onChange: setSearchText, onClear: () => setSearchText("") }, loading: Boolean(loading && options.length === 0), options: options, pagination: pagination }));
7361
+ }),
7362
+ },
7363
+ });
7364
+ return jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, ...facet });
7399
7365
  };
7400
7366
  /**
7401
7367
  * OwnerAccountIds filter definition
@@ -7527,7 +7493,6 @@ const usePeriodFilter = () => {
7527
7493
  return result;
7528
7494
  };
7529
7495
 
7530
- const FETCH_LIMIT$2 = 1000;
7531
7496
  /**
7532
7497
  * Production Year Filter View component.
7533
7498
  *
@@ -7542,32 +7507,16 @@ const FETCH_LIMIT$2 = 1000;
7542
7507
  */
7543
7508
  const ProductionYearFilterView = ({ filterDefinition, filterState, filterBarActions, ...props }) => {
7544
7509
  const [t] = useTranslation();
7545
- const activeFilters = filtersGraphqlHook.useActiveAssetFilters(filterState.values);
7546
- const [showRequestMoreUseSearch, setShowRequestMoreUseSearch] = react.useState(false);
7547
- const [searchText, setSearchText] = react.useState("");
7548
- const debouncedSearch = reactComponents.useDebounce(searchText, { delay: 500 });
7549
- const { data, loading } = reactGraphqlHooks.useQuery(GetFleetProductionYearsSummaryDocument, {
7550
- variables: {
7551
- limit: FETCH_LIMIT$2,
7552
- search: debouncedSearch,
7553
- filters: {
7554
- ...activeFilters,
7555
- productionYears: null, // Omit the filters own values so list shows options correctly
7556
- },
7557
- },
7558
- fetchPolicy: "cache-first",
7559
- });
7560
- const options = react.useMemo(() => {
7561
- const result = data?.assetSummary?.productionYears?.summary.map(productionYear => ({
7510
+ const facet = useFacetLimitedOptions(filterState, {
7511
+ document: GetFleetProductionYearsSummaryDocument,
7512
+ scope: filters => ({ ...filters, productionYears: null }),
7513
+ read: data => data.assetSummary?.productionYears?.summary,
7514
+ toOption: productionYear => ({
7562
7515
  ...productionYear,
7563
7516
  label: productionYear.key.toUpperCase() === "UNDEFINED" ? t(`machine.types.Unknown`) : productionYear.key,
7564
- })) ?? [];
7565
- return result;
7566
- }, [data?.assetSummary?.productionYears?.summary, t]);
7567
- react.useEffect(() => {
7568
- setShowRequestMoreUseSearch(options.length === FETCH_LIMIT$2);
7569
- }, [options]);
7570
- return (jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, customSearch: { value: searchText, onChange: setSearchText, onClear: () => setSearchText("") }, filterBarActions: filterBarActions, filterDefinition: filterDefinition, filterState: filterState, loading: loading, options: options, showRequestMoreUseSearch: showRequestMoreUseSearch }));
7517
+ }),
7518
+ });
7519
+ return (jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, ...facet, filterBarActions: filterBarActions, filterDefinition: filterDefinition, filterState: filterState }));
7571
7520
  };
7572
7521
  /**
7573
7522
  * Production year filter definition
@@ -7653,10 +7602,8 @@ const useRentalActiveContractItemOnRentDatesDateRangeFilter = ({ showInFilterBar
7653
7602
  };
7654
7603
 
7655
7604
  const RENTAL_PREVIEW_CONTEXT$3 = {
7656
- context: {
7657
- headers: {
7658
- "TU-PREVIEW": "dragonfruit-monty",
7659
- },
7605
+ headers: {
7606
+ "TU-PREVIEW": "dragonfruit-monty",
7660
7607
  },
7661
7608
  };
7662
7609
  /**
@@ -7664,27 +7611,22 @@ const RENTAL_PREVIEW_CONTEXT$3 = {
7664
7611
  */
7665
7612
  const RentalContractCustomerParentExternalReferenceFilterView = (props) => {
7666
7613
  const [t] = useTranslation();
7667
- const activeFilters = filtersGraphqlHook.useActiveAssetFilters(props.filterState.values);
7668
- const [searchText, setSearchText] = react.useState("");
7669
- const debouncedSearch = reactComponents.useDebounce(searchText, { delay: 500 });
7670
- const filters = {
7671
- ...activeFilters,
7672
- rentalActiveContractFilters: {
7673
- ...activeFilters.rentalActiveContractFilters,
7674
- customerParentExternalReferences: null,
7675
- },
7676
- };
7677
- const { edges, loading: loadingValues, pagination, } = useFleetSummaryConnection(GetFleetRentalCustomerParentExternalReferenceSummaryConnectionDocument, "rentalContractCustomerParentExternalReferencesConnection", { search: debouncedSearch, filters }, RENTAL_PREVIEW_CONTEXT$3);
7678
- const { missing, loading: loadingMissing } = useFacetMissingCount(GetFleetRentalCustomerParentExternalReferenceSummaryMissingDocument, "rentalContractCustomerParentExternalReferencesConnection", filters, RENTAL_PREVIEW_CONTEXT$3);
7679
- const loading = loadingValues || loadingMissing;
7680
- const options = react.useMemo(() => {
7681
- return toSummaryEntries(edges, missing, loading).map(entry => ({
7614
+ const facet = useFacetConnectionOptions(props.filterState, {
7615
+ document: GetFleetRentalCustomerParentExternalReferenceSummaryConnectionDocument,
7616
+ connectionField: "rentalContractCustomerParentExternalReferencesConnection",
7617
+ scope: filters => ({
7618
+ ...filters,
7619
+ rentalActiveContractFilters: { ...filters.rentalActiveContractFilters, customerParentExternalReferences: null },
7620
+ }),
7621
+ missing: { document: GetFleetRentalCustomerParentExternalReferenceSummaryMissingDocument },
7622
+ toOption: entry => ({
7682
7623
  key: entry.key || "unknown",
7683
7624
  count: entry.count,
7684
7625
  label: entry.key && entry.key !== UNDEFINED_SUMMARY_KEY ? entry.key : t(`machine.types.Unknown`),
7685
- }));
7686
- }, [edges, missing, loading, t]);
7687
- return (jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, customSearch: { value: searchText, onChange: setSearchText, onClear: () => setSearchText("") }, loading: Boolean(loading && options.length === 0), options: options, pagination: pagination }));
7626
+ }),
7627
+ context: RENTAL_PREVIEW_CONTEXT$3,
7628
+ });
7629
+ return jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, ...facet });
7688
7630
  };
7689
7631
  /**
7690
7632
  * Rental contract customer parent external reference filter definition
@@ -7706,10 +7648,8 @@ const useRentalContractCustomerParentExternalReferenceFilter = (props) => {
7706
7648
  };
7707
7649
 
7708
7650
  const RENTAL_PREVIEW_CONTEXT$2 = {
7709
- context: {
7710
- headers: {
7711
- "TU-PREVIEW": "dragonfruit-monty",
7712
- },
7651
+ headers: {
7652
+ "TU-PREVIEW": "dragonfruit-monty",
7713
7653
  },
7714
7654
  };
7715
7655
  /**
@@ -7717,27 +7657,22 @@ const RENTAL_PREVIEW_CONTEXT$2 = {
7717
7657
  */
7718
7658
  const RentalContractCustomerParentNameFilterView = (props) => {
7719
7659
  const [t] = useTranslation();
7720
- const activeFilters = filtersGraphqlHook.useActiveAssetFilters(props.filterState.values);
7721
- const [searchText, setSearchText] = react.useState("");
7722
- const debouncedSearch = reactComponents.useDebounce(searchText, { delay: 500 });
7723
- const filters = {
7724
- ...activeFilters,
7725
- rentalActiveContractFilters: {
7726
- ...activeFilters.rentalActiveContractFilters,
7727
- customerParentNames: null,
7728
- },
7729
- };
7730
- const { edges, loading: loadingValues, pagination, } = useFleetSummaryConnection(GetFleetRentalCustomerParentNameSummaryConnectionDocument, "rentalContractCustomerParentNamesConnection", { search: debouncedSearch, filters }, RENTAL_PREVIEW_CONTEXT$2);
7731
- const { missing, loading: loadingMissing } = useFacetMissingCount(GetFleetRentalCustomerParentNameSummaryMissingDocument, "rentalContractCustomerParentNamesConnection", filters, RENTAL_PREVIEW_CONTEXT$2);
7732
- const loading = loadingValues || loadingMissing;
7733
- const options = react.useMemo(() => {
7734
- return toSummaryEntries(edges, missing, loading).map(entry => ({
7660
+ const facet = useFacetConnectionOptions(props.filterState, {
7661
+ document: GetFleetRentalCustomerParentNameSummaryConnectionDocument,
7662
+ connectionField: "rentalContractCustomerParentNamesConnection",
7663
+ scope: filters => ({
7664
+ ...filters,
7665
+ rentalActiveContractFilters: { ...filters.rentalActiveContractFilters, customerParentNames: null },
7666
+ }),
7667
+ missing: { document: GetFleetRentalCustomerParentNameSummaryMissingDocument },
7668
+ toOption: entry => ({
7735
7669
  key: entry.key || "unknown",
7736
7670
  count: entry.count,
7737
7671
  label: entry.key && entry.key !== UNDEFINED_SUMMARY_KEY ? entry.key : t(`machine.types.Unknown`),
7738
- }));
7739
- }, [edges, missing, loading, t]);
7740
- return (jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, customSearch: { value: searchText, onChange: setSearchText, onClear: () => setSearchText("") }, loading: Boolean(loading && options.length === 0), options: options, pagination: pagination }));
7672
+ }),
7673
+ context: RENTAL_PREVIEW_CONTEXT$2,
7674
+ });
7675
+ return jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, ...facet });
7741
7676
  };
7742
7677
  /**
7743
7678
  * Rental contract customer parent name filter definition
@@ -7759,10 +7694,8 @@ const useRentalContractCustomerParentNameFilter = (props) => {
7759
7694
  };
7760
7695
 
7761
7696
  const RENTAL_PREVIEW_CONTEXT$1 = {
7762
- context: {
7763
- headers: {
7764
- "TU-PREVIEW": "dragonfruit-monty",
7765
- },
7697
+ headers: {
7698
+ "TU-PREVIEW": "dragonfruit-monty",
7766
7699
  },
7767
7700
  };
7768
7701
  /**
@@ -7770,21 +7703,19 @@ const RENTAL_PREVIEW_CONTEXT$1 = {
7770
7703
  */
7771
7704
  const RentalContractOrderNumberFilterView = (props) => {
7772
7705
  const [t] = useTranslation();
7773
- const activeFilters = filtersGraphqlHook.useActiveAssetFilters(props.filterState.values);
7774
- const [searchText, setSearchText] = react.useState("");
7775
- const debouncedSearch = reactComponents.useDebounce(searchText, { delay: 500 });
7776
- const filters = { ...activeFilters, rentalContractOrderNumbers: null };
7777
- const { edges, loading: loadingValues, pagination, } = useFleetSummaryConnection(GetFleetRentalContractOrderNumberSummaryConnectionDocument, "rentalContractOrderNumbersConnection", { search: debouncedSearch, filters }, RENTAL_PREVIEW_CONTEXT$1);
7778
- const { missing, loading: loadingMissing } = useFacetMissingCount(GetFleetRentalContractOrderNumberSummaryMissingDocument, "rentalContractOrderNumbersConnection", filters, RENTAL_PREVIEW_CONTEXT$1);
7779
- const loading = loadingValues || loadingMissing;
7780
- const options = react.useMemo(() => {
7781
- return toSummaryEntries(edges, missing, loading).map(entry => ({
7706
+ const facet = useFacetConnectionOptions(props.filterState, {
7707
+ document: GetFleetRentalContractOrderNumberSummaryConnectionDocument,
7708
+ connectionField: "rentalContractOrderNumbersConnection",
7709
+ scope: filters => ({ ...filters, rentalContractOrderNumbers: null }),
7710
+ missing: { document: GetFleetRentalContractOrderNumberSummaryMissingDocument },
7711
+ toOption: entry => ({
7782
7712
  key: entry.key || "unknown",
7783
7713
  count: entry.count,
7784
7714
  label: entry.key && entry.key !== UNDEFINED_SUMMARY_KEY ? entry.key : t(`machine.types.Unknown`),
7785
- }));
7786
- }, [edges, missing, loading, t]);
7787
- return (jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, customSearch: { value: searchText, onChange: setSearchText, onClear: () => setSearchText("") }, loading: Boolean(loading && options.length === 0), options: options, pagination: pagination }));
7715
+ }),
7716
+ context: RENTAL_PREVIEW_CONTEXT$1,
7717
+ });
7718
+ return jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, ...facet });
7788
7719
  };
7789
7720
  /**
7790
7721
  * Rental contract order number filter definition
@@ -7836,10 +7767,8 @@ const useRentalContractReferenceCodeDescriptionFilter = (props) => {
7836
7767
  };
7837
7768
 
7838
7769
  const RENTAL_PREVIEW_CONTEXT = {
7839
- context: {
7840
- headers: {
7841
- "TU-PREVIEW": "dragonfruit-monty",
7842
- },
7770
+ headers: {
7771
+ "TU-PREVIEW": "dragonfruit-monty",
7843
7772
  },
7844
7773
  };
7845
7774
  /**
@@ -7847,21 +7776,19 @@ const RENTAL_PREVIEW_CONTEXT = {
7847
7776
  */
7848
7777
  const RentalContractReferenceCodeFilterView = (props) => {
7849
7778
  const [t] = useTranslation();
7850
- const activeFilters = filtersGraphqlHook.useActiveAssetFilters(props.filterState.values);
7851
- const [searchText, setSearchText] = react.useState("");
7852
- const debouncedSearch = reactComponents.useDebounce(searchText, { delay: 500 });
7853
- const filters = { ...activeFilters, rentalContractReferenceCodes: null };
7854
- const { edges, loading: loadingValues, pagination, } = useFleetSummaryConnection(GetFleetRentalContractReferenceCodesSummaryConnectionDocument, "rentalContractReferenceCodesConnection", { search: debouncedSearch, filters }, RENTAL_PREVIEW_CONTEXT);
7855
- const { missing, loading: loadingMissing } = useFacetMissingCount(GetFleetRentalContractReferenceCodesSummaryMissingDocument, "rentalContractReferenceCodesConnection", filters, RENTAL_PREVIEW_CONTEXT);
7856
- const loading = loadingValues || loadingMissing;
7857
- const options = react.useMemo(() => {
7858
- return toSummaryEntries(edges, missing, loading).map(entry => ({
7779
+ const facet = useFacetConnectionOptions(props.filterState, {
7780
+ document: GetFleetRentalContractReferenceCodesSummaryConnectionDocument,
7781
+ connectionField: "rentalContractReferenceCodesConnection",
7782
+ scope: filters => ({ ...filters, rentalContractReferenceCodes: null }),
7783
+ missing: { document: GetFleetRentalContractReferenceCodesSummaryMissingDocument },
7784
+ toOption: entry => ({
7859
7785
  key: entry.key || "unknown",
7860
7786
  count: entry.count,
7861
7787
  label: entry.key && entry.key !== UNDEFINED_SUMMARY_KEY ? entry.key : t(`machine.types.Unknown`),
7862
- }));
7863
- }, [edges, missing, loading, t]);
7864
- return (jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, customSearch: { value: searchText, onChange: setSearchText, onClear: () => setSearchText("") }, loading: Boolean(loading && options.length === 0), options: options, pagination: pagination }));
7788
+ }),
7789
+ context: RENTAL_PREVIEW_CONTEXT,
7790
+ });
7791
+ return jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, ...facet });
7865
7792
  };
7866
7793
  /**
7867
7794
  * Rental contract reference code filter definition
@@ -8081,7 +8008,6 @@ const useServicePlanStatusFilter = ({ servicePlanStatusToShow = SERVICE_PLAN_STA
8081
8008
  return result;
8082
8009
  };
8083
8010
 
8084
- const FETCH_LIMIT$1 = 1000;
8085
8011
  /**
8086
8012
  * Component for rendering a filter view specific to site depot ownership.
8087
8013
  *
@@ -8090,35 +8016,19 @@ const FETCH_LIMIT$1 = 1000;
8090
8016
  */
8091
8017
  const SiteDepotOwnershipIdsFilterView = (props) => {
8092
8018
  const [t] = useTranslation();
8093
- const activeFilters = filtersGraphqlHook.useActiveAssetFilters(props.filterState.values);
8094
- const [showRequestMoreUseSearch, setShowRequestMoreUseSearch] = react.useState(false);
8095
- const [searchText, setSearchText] = react.useState("");
8096
- const debouncedSearch = reactComponents.useDebounce(searchText, { delay: 500 });
8097
- const { data, loading } = reactGraphqlHooks.useQuery(GetSiteDepotOwnershipIdSummaryDocument, {
8098
- fetchPolicy: "cache-first",
8099
- variables: {
8100
- limit: FETCH_LIMIT$1,
8101
- search: debouncedSearch,
8102
- filters: {
8103
- ...activeFilters,
8104
- owningDepotSiteIds: null, // Omit the filters own values so list shows options correctly
8105
- },
8106
- },
8107
- });
8108
- const options = react.useMemo(() => {
8109
- const result = data?.assetSummary?.owningDepots?.summary.map(owningDepotEdge => ({
8110
- key: owningDepotEdge.site?.siteId ? owningDepotEdge.site.siteId || "unknown" : "UNDEFINED",
8019
+ const facet = useFacetLimitedOptions(props.filterState, {
8020
+ document: GetSiteDepotOwnershipIdSummaryDocument,
8021
+ scope: filters => ({ ...filters, owningDepotSiteIds: null }),
8022
+ read: data => data.assetSummary?.owningDepots?.summary,
8023
+ toOption: owningDepotEdge => ({
8024
+ key: owningDepotEdge.site?.siteId || "UNDEFINED",
8111
8025
  count: owningDepotEdge.count || 0,
8112
8026
  label: owningDepotEdge.site?.name === "UNDEFINED"
8113
8027
  ? t("siteOwningDepot.notOwned")
8114
8028
  : owningDepotEdge.site?.name || t("siteOwningDepot.unknown"),
8115
- })) ?? [];
8116
- return result;
8117
- }, [data?.assetSummary?.owningDepots?.summary, t]);
8118
- react.useEffect(() => {
8119
- setShowRequestMoreUseSearch(options.length === FETCH_LIMIT$1);
8120
- }, [options]);
8121
- return (jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, customSearch: { value: searchText, onChange: setSearchText, onClear: () => setSearchText("") }, loading: loading, options: options, showRequestMoreUseSearch: showRequestMoreUseSearch }));
8029
+ }),
8030
+ });
8031
+ return jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, ...facet });
8122
8032
  };
8123
8033
  /**
8124
8034
  * Site depot ownership filter definition
@@ -8142,7 +8052,6 @@ const useSiteDepotOwnershipIdsFilter = (props) => {
8142
8052
  return result;
8143
8053
  };
8144
8054
 
8145
- const FETCH_LIMIT = 1000;
8146
8055
  /**
8147
8056
  * Filter view component for selecting Site IDs.
8148
8057
  *
@@ -8153,33 +8062,19 @@ const FETCH_LIMIT = 1000;
8153
8062
  * @returns {ReactElement} The rendered Site IDs filter view component.
8154
8063
  */
8155
8064
  const SiteIdsFilterView = (props) => {
8156
- const activeFilters = filtersGraphqlHook.useActiveAssetFilters(props.filterState.values);
8157
- const [showRequestMoreUseSearch, setShowRequestMoreUseSearch] = react.useState(false);
8158
- const [searchText, setSearchText] = react.useState("");
8159
- const debouncedSearch = reactComponents.useDebounce(searchText, { delay: 500 });
8160
- const { data, loading } = reactGraphqlHooks.useQuery(GetSiteIdSummaryDocument, {
8161
- fetchPolicy: "cache-first",
8162
- variables: {
8163
- limit: FETCH_LIMIT,
8164
- search: debouncedSearch,
8165
- filters: {
8166
- ...activeFilters,
8167
- siteIds: null, // Omit the filters own values so list shows options correctly
8168
- },
8169
- },
8170
- });
8171
- const options = react.useMemo(() => {
8172
- const result = data?.assetSummary?.sites?.summary.map(siteEdge => ({
8065
+ const [t] = useTranslation();
8066
+ const facet = useFacetLimitedOptions(props.filterState, {
8067
+ document: GetSiteIdSummaryDocument,
8068
+ scope: filters => ({ ...filters, siteIds: null }),
8069
+ read: data => data.assetSummary?.sites?.summary,
8070
+ toOption: siteEdge => ({
8173
8071
  key: siteEdge.site?.siteId || "unknown",
8174
- count: props.hasCount ? siteEdge.count || 0 : undefined,
8175
- label: siteEdge.site?.name || "Unknown",
8176
- })) ?? [];
8177
- return result;
8178
- }, [data?.assetSummary?.sites?.summary, props.hasCount]);
8179
- react.useEffect(() => {
8180
- setShowRequestMoreUseSearch(options.length === FETCH_LIMIT);
8181
- }, [options]);
8182
- return (jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, customSearch: { value: searchText, onChange: setSearchText, onClear: () => setSearchText("") }, loading: loading, options: options, showRequestMoreUseSearch: showRequestMoreUseSearch }));
8072
+ count: siteEdge.count || 0,
8073
+ label: siteEdge.site?.name || t("machine.types.Unknown"),
8074
+ }),
8075
+ showCount: Boolean(props.hasCount),
8076
+ });
8077
+ return jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, ...facet });
8183
8078
  };
8184
8079
  /**
8185
8080
  *
@@ -8443,24 +8338,14 @@ const useTelematicsConnectedFilter = () => {
8443
8338
  */
8444
8339
  const TypesFilterView = (props) => {
8445
8340
  const { getMachineTypeTranslation } = translationsMachineType.useMachineTypeTranslations();
8446
- const activeFilters = filtersGraphqlHook.useActiveAssetFilters(props.filterState.values);
8447
- const [searchText, setSearchText] = react.useState("");
8448
- const debouncedSearch = reactComponents.useDebounce(searchText, { delay: 500 });
8449
- const filters = { ...activeFilters, types: null };
8450
- const { edges, loading: loadingValues, pagination, } = useFleetSummaryConnection(GetFleetTypesSummaryConnectionDocument, "typesConnection", {
8451
- search: debouncedSearch,
8452
- filters,
8341
+ const facet = useFacetConnectionOptions(props.filterState, {
8342
+ document: GetFleetTypesSummaryConnectionDocument,
8343
+ connectionField: "typesConnection",
8344
+ scope: filters => ({ ...filters, types: null }),
8345
+ missing: { document: GetFleetTypesSummaryMissingDocument },
8346
+ toOption: entry => ({ ...entry, label: getMachineTypeTranslation(entry.key) }),
8453
8347
  });
8454
- const { missing, loading: loadingMissing } = useFacetMissingCount(GetFleetTypesSummaryMissingDocument, "typesConnection", filters);
8455
- const loading = loadingValues || loadingMissing;
8456
- const options = react.useMemo(() => {
8457
- return toSummaryEntries(edges, missing, loading).map(entry => ({
8458
- key: entry.key,
8459
- count: entry.count,
8460
- label: getMachineTypeTranslation(entry.key),
8461
- }));
8462
- }, [edges, missing, loading, getMachineTypeTranslation]);
8463
- return (jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, customSearch: { value: searchText, onChange: setSearchText, onClear: () => setSearchText("") }, loading: Boolean(loading && options.length === 0), options: options, pagination: pagination }));
8348
+ return jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, ...facet });
8464
8349
  };
8465
8350
  /**
8466
8351
  * Types filter definition