@bundle-stats/ui 4.17.0 → 4.18.0-beta.1

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.
Files changed (60) hide show
  1. package/lib/components/asset-info/asset-info.i18n.js +11 -0
  2. package/lib/components/asset-info/asset-info.i18n.js.map +1 -0
  3. package/lib/components/asset-info/asset-info.js +16 -16
  4. package/lib/components/asset-info/asset-info.js.map +1 -1
  5. package/lib/components/bundle-assets/bundle-assets.i18n.js +9 -1
  6. package/lib/components/bundle-assets/bundle-assets.i18n.js.map +1 -1
  7. package/lib/components/bundle-assets/bundle-assets.js +9 -112
  8. package/lib/components/bundle-assets/bundle-assets.js.map +1 -1
  9. package/lib/components/bundle-assets/bundle-assets.utils.js +136 -23
  10. package/lib/components/bundle-assets/bundle-assets.utils.js.map +1 -1
  11. package/lib/components/bundle-assets/index.js +8 -26
  12. package/lib/components/bundle-assets/index.js.map +1 -1
  13. package/lib/components/metrics-table/metrics-table.js.map +1 -1
  14. package/lib/components/metrics-table-header/metrics-table-header.js.map +1 -1
  15. package/lib/hooks/rows-sort.js +14 -2
  16. package/lib/hooks/rows-sort.js.map +1 -1
  17. package/lib/hooks/search-params.js.map +1 -1
  18. package/lib-esm/components/asset-info/asset-info.i18n.js +8 -0
  19. package/lib-esm/components/asset-info/asset-info.i18n.js.map +1 -0
  20. package/lib-esm/components/asset-info/asset-info.js +17 -17
  21. package/lib-esm/components/asset-info/asset-info.js.map +1 -1
  22. package/lib-esm/components/bundle-assets/bundle-assets.i18n.js +8 -0
  23. package/lib-esm/components/bundle-assets/bundle-assets.i18n.js.map +1 -1
  24. package/lib-esm/components/bundle-assets/bundle-assets.js +10 -113
  25. package/lib-esm/components/bundle-assets/bundle-assets.js.map +1 -1
  26. package/lib-esm/components/bundle-assets/bundle-assets.utils.js +111 -22
  27. package/lib-esm/components/bundle-assets/bundle-assets.utils.js.map +1 -1
  28. package/lib-esm/components/bundle-assets/index.js +9 -24
  29. package/lib-esm/components/bundle-assets/index.js.map +1 -1
  30. package/lib-esm/components/metrics-table/metrics-table.js.map +1 -1
  31. package/lib-esm/components/metrics-table-header/metrics-table-header.js.map +1 -1
  32. package/lib-esm/hooks/rows-sort.js +14 -2
  33. package/lib-esm/hooks/rows-sort.js.map +1 -1
  34. package/lib-esm/hooks/search-params.js.map +1 -1
  35. package/package.json +3 -3
  36. package/src/components/asset-info/asset-info.i18n.ts +7 -0
  37. package/src/components/asset-info/asset-info.tsx +36 -38
  38. package/src/components/bundle-assets/__tests__/add-metric-report-asset-row-data.ts +2 -2
  39. package/src/components/bundle-assets/bundle-assets.i18n.ts +8 -0
  40. package/src/components/bundle-assets/bundle-assets.stories.tsx +99 -0
  41. package/src/components/bundle-assets/{bundle-assets.jsx → bundle-assets.tsx} +67 -149
  42. package/src/components/bundle-assets/bundle-assets.utils.ts +276 -0
  43. package/src/components/bundle-assets/{index.jsx → index.tsx} +43 -29
  44. package/src/components/metrics-table/metrics-table.tsx +3 -3
  45. package/src/components/metrics-table-header/metrics-table-header.tsx +4 -4
  46. package/src/components/sort-button/sort-button.tsx +1 -1
  47. package/src/hooks/rows-sort.ts +21 -3
  48. package/src/hooks/search-params.js +0 -1
  49. package/src/types.d.ts +5 -1
  50. package/types/components/asset-info/asset-info.d.ts +4 -13
  51. package/types/components/asset-info/asset-info.i18n.d.ts +7 -0
  52. package/types/components/bundle-assets/bundle-assets.d.ts +24 -55
  53. package/types/components/bundle-assets/bundle-assets.i18n.d.ts +8 -0
  54. package/types/components/bundle-assets/bundle-assets.utils.d.ts +17 -5
  55. package/types/components/bundle-assets/index.d.ts +10 -22
  56. package/types/components/metrics-table/metrics-table.d.ts +3 -2
  57. package/types/components/metrics-table-header/metrics-table-header.d.ts +1 -2
  58. package/types/components/sort-button/sort-button.d.ts +1 -2
  59. package/types/hooks/rows-sort.d.ts +1 -1
  60. package/src/components/bundle-assets/bundle-assets.utils.js +0 -149
@@ -1,17 +1,11 @@
1
- import React, { useCallback, useMemo, useState } from 'react';
2
- import PropTypes from 'prop-types';
1
+ import type { ElementType, ReactNode } from 'react';
2
+ import React, { ComponentProps, useCallback, useMemo, useState } from 'react';
3
3
  import cx from 'classnames';
4
- import get from 'lodash/get';
5
4
  import escapeRegExp from 'lodash/escapeRegExp';
6
- import {
7
- ASSET_ENTRY_TYPE,
8
- ASSET_FILE_TYPE,
9
- ASSET_FILTERS,
10
- COMPONENT,
11
- FILE_TYPE_LABELS,
12
- SECTIONS,
13
- } from '@bundle-stats/utils';
5
+ import type { Job, ReportMetricRow, WebpackChunk } from '@bundle-stats/utils';
6
+ import { COMPONENT, SECTIONS } from '@bundle-stats/utils';
14
7
 
8
+ import type { ReportMetricAssetRow, SortAction } from '../../types';
15
9
  import config from '../../config.json';
16
10
  import I18N from '../../i18n';
17
11
  import { MetricsDisplayType } from '../../constants';
@@ -26,6 +20,7 @@ import { Filters } from '../../ui/filters';
26
20
  import { EmptySet } from '../../ui/empty-set';
27
21
  import { Toolbar } from '../../ui/toolbar';
28
22
  import { AssetInfo } from '../asset-info';
23
+ import { AssetName } from '../asset-name';
29
24
  import { ComponentLink } from '../component-link';
30
25
  import { MetricsTable } from '../metrics-table';
31
26
  import { MetricsTableExport } from '../metrics-table-export';
@@ -34,59 +29,26 @@ import { MetricsTableTitle } from '../metrics-table-title';
34
29
  import { MetricsDisplaySelector } from '../metrics-display-selector';
35
30
  import { MetricsTableHeader } from '../metrics-table-header';
36
31
  import { MetricsTreemap, getTreemapNodes, getTreemapNodesGroupedByPath } from '../metrics-treemap';
37
- import { SEARCH_PLACEHOLDER } from './bundle-assets.i18n';
32
+ import * as BUNDLE_ASSETS_I18N from './bundle-assets.i18n';
33
+ import { getFilters } from './bundle-assets.utils';
38
34
  import css from './bundle-assets.module.css';
39
- import { AssetName } from '../asset-name';
40
35
 
41
36
  const DISPLAY_TYPE_GROUPS = {
42
37
  [MetricsDisplayType.TREEMAP]: ['folder'],
43
38
  };
44
39
 
45
- const getFileTypeFilters = (filters) =>
46
- Object.entries(FILE_TYPE_LABELS).map(([key, label]) => ({
47
- key,
48
- label,
49
- defaultValue: get(filters, `${ASSET_FILE_TYPE}.${key}`, true),
50
- }));
51
-
52
- const getFilters = ({ compareMode, filters }) => ({
53
- [ASSET_FILTERS.CHANGED]: {
54
- label: 'Changed',
55
- defaultValue: filters[ASSET_FILTERS.CHANGED],
56
- disabled: !compareMode,
57
- },
58
- [ASSET_ENTRY_TYPE]: {
59
- label: 'Type',
60
- children: [
61
- {
62
- key: ASSET_FILTERS.ENTRY,
63
- label: 'Entry',
64
- defaultValue: get(filters, `${ASSET_ENTRY_TYPE}.${ASSET_FILTERS.ENTRY}`, true),
65
- },
66
- {
67
- key: ASSET_FILTERS.INITIAL,
68
- label: 'Initial',
69
- defaultValue: get(filters, `${ASSET_ENTRY_TYPE}.${ASSET_FILTERS.INITIAL}`, true),
70
- },
71
- {
72
- key: ASSET_FILTERS.CHUNK,
73
- label: 'Chunk',
74
- defaultValue: get(filters, `${ASSET_ENTRY_TYPE}.${ASSET_FILTERS.CHUNK}`, true),
75
- },
76
- {
77
- key: ASSET_FILTERS.OTHER,
78
- label: 'Other',
79
- defaultValue: get(filters, `${ASSET_ENTRY_TYPE}.${ASSET_FILTERS.OTHER}`, true),
80
- },
81
- ],
82
- },
83
- [ASSET_FILE_TYPE]: {
84
- label: 'File type',
85
- children: getFileTypeFilters(filters),
86
- },
87
- });
40
+ interface ViewMetricsTreemapProps {
41
+ metricsTableTitle: ReactNode;
42
+ jobs: Array<Job>;
43
+ items: Array<ReportMetricAssetRow>;
44
+ displayType: { value: MetricsDisplayType; groupBy?: string };
45
+ emptyMessage: ReactNode;
46
+ showEntryInfo: (entryId: string) => void;
47
+ updateSearch: (search: string) => void;
48
+ search: string;
49
+ }
88
50
 
89
- const ViewMetricsTreemap = (props) => {
51
+ const ViewMetricsTreemap = (props: ViewMetricsTreemapProps) => {
90
52
  const {
91
53
  metricsTableTitle,
92
54
  jobs,
@@ -109,7 +71,7 @@ const ViewMetricsTreemap = (props) => {
109
71
 
110
72
  // Search based on the group path on group title click
111
73
  const onGroupClick = useCallback(
112
- (groupPath) => {
74
+ (groupPath: string) => {
113
75
  // Clear seach when groupPath is emty (root)
114
76
  if (groupPath === '') {
115
77
  updateSearch('');
@@ -147,22 +109,29 @@ const ViewMetricsTreemap = (props) => {
147
109
  );
148
110
  };
149
111
 
150
- ViewMetricsTreemap.propTypes = {
151
- jobs: PropTypes.arrayOf(PropTypes.object).isRequired, // eslint-disable-line react/forbid-prop-types
152
- items: PropTypes.arrayOf(PropTypes.object).isRequired, // eslint-disable-line react/forbid-prop-types
153
- metricsTableTitle: PropTypes.node.isRequired,
154
- displayType: PropTypes.shape({
155
- groupBy: PropTypes.string,
156
- }).isRequired,
157
- emptyMessage: PropTypes.node.isRequired,
158
- showEntryInfo: PropTypes.func.isRequired,
159
- updateSearch: PropTypes.func.isRequired,
160
- search: PropTypes.string.isRequired,
161
- };
112
+ export interface BundleAssetsProps extends ComponentProps<typeof Stack> {
113
+ jobs: Array<Job>;
114
+ chunks: Array<WebpackChunk>;
115
+ items: Array<ReportMetricAssetRow>;
116
+ allItems: Array<ReportMetricAssetRow>;
117
+ filters: Record<string, boolean>;
118
+ updateFilters: (newFilters: Record<string, boolean>) => void;
119
+ resetFilters: () => void;
120
+ resetAllFilters: () => void;
121
+ totalRowCount?: number;
122
+ entryId?: string;
123
+ sort: SortAction;
124
+ updateSort: (params: SortAction) => void;
125
+ search: string;
126
+ updateSearch: (search: string) => void;
127
+ customComponentLink?: ElementType;
128
+ hideEntryInfo: () => void;
129
+ showEntryInfo: (entryId: string) => void;
130
+ }
162
131
 
163
- export const BundleAssets = (props) => {
132
+ export const BundleAssets = (props: BundleAssetsProps) => {
164
133
  const {
165
- className,
134
+ className = '',
166
135
  jobs,
167
136
  chunks,
168
137
  items,
@@ -170,15 +139,14 @@ export const BundleAssets = (props) => {
170
139
  updateFilters,
171
140
  resetFilters,
172
141
  resetAllFilters,
173
- totalRowCount,
142
+ totalRowCount = 0,
174
143
  filters,
175
- entryId,
176
- hasActiveFilters,
144
+ entryId = '',
177
145
  sort,
178
146
  updateSort,
179
147
  search,
180
148
  updateSearch,
181
- customComponentLink: CustomComponentLink,
149
+ customComponentLink: CustomComponentLink = ComponentLink,
182
150
  hideEntryInfo,
183
151
  showEntryInfo,
184
152
  } = props;
@@ -187,9 +155,9 @@ export const BundleAssets = (props) => {
187
155
 
188
156
  const [displayType, setDisplayType] = useMetricsDisplayType(DISPLAY_TYPE_GROUPS);
189
157
 
190
- const dropdownFilters = useMemo(
191
- () => getFilters({ compareMode: jobs?.length > 1, filters }),
192
- [jobs, filters],
158
+ const filterFieldsData = useMemo(
159
+ () => getFilters({ compareMode: jobs?.length > 1, filters, chunks }),
160
+ [jobs, filters, chunks],
193
161
  );
194
162
 
195
163
  const metricsTableTitle = useMemo(
@@ -205,7 +173,10 @@ export const BundleAssets = (props) => {
205
173
  );
206
174
 
207
175
  const EntryComponentLink = useCallback(
208
- ({ entryId: assetEntryId, ...assetNameRestProps }) => (
176
+ ({
177
+ entryId: assetEntryId,
178
+ ...assetNameRestProps
179
+ }: { entryId: string } & ComponentProps<typeof CustomComponentLink>) => (
209
180
  <CustomComponentLink
210
181
  section={SECTIONS.ASSETS}
211
182
  params={{
@@ -224,8 +195,12 @@ export const BundleAssets = (props) => {
224
195
  );
225
196
 
226
197
  const renderRowHeader = useCallback(
227
- (row) => (
228
- <AssetName row={row} EntryComponentLink={EntryComponentLink} className={css.assetName} />
198
+ (row: ReportMetricRow) => (
199
+ <AssetName
200
+ row={row as ReportMetricAssetRow}
201
+ EntryComponentLink={EntryComponentLink}
202
+ className={css.assetName}
203
+ />
229
204
  ),
230
205
  [EntryComponentLink],
231
206
  );
@@ -251,12 +226,15 @@ export const BundleAssets = (props) => {
251
226
  }, [allItems, entryId]);
252
227
 
253
228
  const exportDialog = useDialogState();
254
- const [exportSourceType, setExportSourceType] = useState(undefined);
229
+ const [exportSourceType, setExportSourceType] = useState<string>();
255
230
 
256
- const handleExportClick = useCallback((sourceType) => {
257
- setExportSourceType(sourceType);
258
- exportDialog.toggle();
259
- }, []);
231
+ const handleExportClick = useCallback(
232
+ (sourceType: string) => {
233
+ setExportSourceType(sourceType);
234
+ exportDialog.toggle();
235
+ },
236
+ [exportDialog, setExportSourceType],
237
+ );
260
238
 
261
239
  return (
262
240
  <>
@@ -281,14 +259,13 @@ export const BundleAssets = (props) => {
281
259
  <FlexStack space="xxsmall">
282
260
  <InputSearch
283
261
  className={css.toolbarSearch}
284
- placeholder={SEARCH_PLACEHOLDER}
262
+ placeholder={BUNDLE_ASSETS_I18N.SEARCH_PLACEHOLDER}
285
263
  defaultValue={search}
286
264
  onChange={updateSearch}
287
265
  />
288
266
  <Filters
289
267
  className={css.toolbarFilters}
290
- filters={dropdownFilters}
291
- hasActiveFilters={hasActiveFilters}
268
+ filters={filterFieldsData}
292
269
  onChange={updateFilters}
293
270
  />
294
271
  </FlexStack>
@@ -344,62 +321,3 @@ export const BundleAssets = (props) => {
344
321
  </>
345
322
  );
346
323
  };
347
-
348
- BundleAssets.defaultProps = {
349
- className: '',
350
- totalRowCount: 0,
351
- hasActiveFilters: false,
352
- customComponentLink: ComponentLink,
353
- entryId: '',
354
- };
355
-
356
- BundleAssets.propTypes = {
357
- className: PropTypes.string,
358
- jobs: PropTypes.arrayOf(
359
- PropTypes.shape({
360
- internalBuildNumber: PropTypes.number,
361
- label: PropTypes.string,
362
- }),
363
- ).isRequired,
364
- chunks: PropTypes.arrayOf({
365
- id: PropTypes.string,
366
- name: PropTypes.string,
367
- }).isRequired,
368
- items: PropTypes.arrayOf(
369
- PropTypes.shape({
370
- key: PropTypes.string,
371
- label: PropTypes.string,
372
- runs: PropTypes.arrayOf(
373
- PropTypes.shape({
374
- displayValue: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
375
- displayDelta: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
376
- }),
377
- ),
378
- }),
379
- ).isRequired,
380
- updateFilters: PropTypes.func.isRequired,
381
- resetFilters: PropTypes.func.isRequired,
382
- resetAllFilters: PropTypes.func.isRequired,
383
- totalRowCount: PropTypes.number,
384
- filters: PropTypes.shape({
385
- changed: PropTypes.bool,
386
- id: PropTypes.string,
387
- }).isRequired,
388
- entryId: PropTypes.string,
389
- hasActiveFilters: PropTypes.bool,
390
- search: PropTypes.string.isRequired,
391
- updateSearch: PropTypes.func.isRequired,
392
- sort: PropTypes.shape({
393
- field: PropTypes.string,
394
- direction: PropTypes.string,
395
- }).isRequired,
396
- updateSort: PropTypes.func.isRequired,
397
- allItems: PropTypes.arrayOf(
398
- PropTypes.shape({
399
- key: PropTypes.string,
400
- }),
401
- ).isRequired,
402
- customComponentLink: PropTypes.elementType,
403
- hideEntryInfo: PropTypes.func.isRequired,
404
- showEntryInfo: PropTypes.func.isRequired,
405
- };
@@ -0,0 +1,276 @@
1
+ import get from 'lodash/get';
2
+ import intersection from 'lodash/intersection';
3
+ import isEmpty from 'lodash/isEmpty';
4
+ import orderBy from 'lodash/orderBy';
5
+ import type { ReportMetricRow, WebpackChunk } from '@bundle-stats/utils';
6
+ import type { AssetMetricRun } from '@bundle-stats/utils/types/webpack';
7
+ import {
8
+ ASSET_CHUNK,
9
+ ASSET_ENTRY_TYPE,
10
+ ASSET_FILE_TYPE,
11
+ ASSET_FILTERS,
12
+ FILE_TYPE_LABELS,
13
+ getFileType,
14
+ } from '@bundle-stats/utils';
15
+
16
+ import type {
17
+ FilterFieldsData,
18
+ ReportMetricAssetRow,
19
+ ReportMetricAssetRowMetaStatus,
20
+ FilterGroupFieldData,
21
+ } from '../../types';
22
+ import * as I18N from './bundle-assets.i18n';
23
+
24
+ const NO_CHUNK_FILTER = 'NO_CHUNK';
25
+
26
+ /**
27
+ * Check if the asset cache is not predictive
28
+ */
29
+ export const getIsNotPredictive = (row: ReportMetricRow): boolean => {
30
+ const { key, runs } = row;
31
+
32
+ return runs.reduce((agg, run, index) => {
33
+ if (agg) {
34
+ return agg;
35
+ }
36
+
37
+ if (index + 1 === runs.length) {
38
+ return agg;
39
+ }
40
+
41
+ const preRun = runs[index + 1];
42
+
43
+ if (
44
+ run &&
45
+ preRun &&
46
+ key !== run.name &&
47
+ run.name === preRun.name &&
48
+ run.value !== preRun.value
49
+ ) {
50
+ return true;
51
+ }
52
+
53
+ return agg;
54
+ }, false);
55
+ };
56
+
57
+ /**
58
+ * Return asset meta status
59
+ */
60
+ export const getAssetMetaStatus = (
61
+ values: Array<boolean | undefined>,
62
+ ): ReportMetricAssetRowMetaStatus | boolean => {
63
+ if (!values.includes(true)) {
64
+ return false;
65
+ }
66
+
67
+ // filter empty runs
68
+ const metaValues = values.filter((value) => typeof value !== 'undefined');
69
+
70
+ const current = metaValues[0];
71
+ const metaValuesLength = metaValues.length;
72
+
73
+ if (metaValuesLength === 1) {
74
+ return Boolean(current);
75
+ }
76
+
77
+ const baseline = metaValues[metaValuesLength - 1];
78
+
79
+ if (current && !baseline) {
80
+ return 'added';
81
+ }
82
+
83
+ if (!current && baseline) {
84
+ return 'removed';
85
+ }
86
+
87
+ return true;
88
+ };
89
+
90
+ /**
91
+ * Add asset row flags
92
+ */
93
+ export const addMetricReportAssetRowData = (row: ReportMetricRow): ReportMetricAssetRow => {
94
+ const { changed, runs } = row;
95
+
96
+ // Collect meta for each run
97
+ const runsEntry: Array<boolean | undefined> = [];
98
+ const runsInitial: Array<boolean | undefined> = [];
99
+ const runsChunk: Array<boolean | undefined> = [];
100
+
101
+ (runs as Array<AssetMetricRun | null>).forEach((run) => {
102
+ runsEntry.push(run?.isEntry);
103
+ runsInitial.push(run?.isInitial);
104
+ runsChunk.push(run?.isChunk);
105
+ });
106
+
107
+ const isEntry = getAssetMetaStatus(runsEntry);
108
+ const isInitial = getAssetMetaStatus(runsInitial);
109
+ const isChunk = getAssetMetaStatus(runsChunk);
110
+ const isAsset = !(isEntry || isInitial || isChunk);
111
+ const isNotPredictive = getIsNotPredictive(row);
112
+ const fileType = getFileType(row.key);
113
+
114
+ // Flag asset as changed if name and value are identical, if one of the meta tags is changed
115
+ const assetChanged =
116
+ changed ||
117
+ typeof isEntry !== 'boolean' ||
118
+ typeof isInitial !== 'boolean' ||
119
+ typeof isChunk !== 'boolean';
120
+
121
+ return {
122
+ ...row,
123
+ changed: assetChanged,
124
+ isEntry,
125
+ isInitial,
126
+ isChunk,
127
+ isAsset,
128
+ isNotPredictive,
129
+ fileType,
130
+ };
131
+ };
132
+
133
+ type GenerateGetRowFilterOptions = {
134
+ chunkIds: Array<string>;
135
+ };
136
+
137
+ export const getCustomSort = (item: ReportMetricAssetRow): Array<boolean | string> => [
138
+ !item.isNotPredictive,
139
+ !item.changed,
140
+ !item.isInitial,
141
+ !item.isEntry,
142
+ !item.isChunk,
143
+ item.key,
144
+ ];
145
+
146
+ /* eslint-disable prettier/prettier */
147
+ const getFileTypeFilters = (filters: Record<string, unknown>): FilterGroupFieldData['children'] => Object.entries(FILE_TYPE_LABELS).map(([key, label]) => ({
148
+ key,
149
+ label,
150
+ defaultValue: get(filters, `${ASSET_FILE_TYPE}.${key}`, true) as boolean,
151
+ }));
152
+
153
+ type GetFiltersOptions = {
154
+ compareMode: boolean;
155
+ filters: Record<string, boolean>;
156
+ chunks: Array<WebpackChunk>;
157
+ };
158
+
159
+ export const getFilters = ({
160
+ compareMode,
161
+ filters,
162
+ chunks,
163
+ }: GetFiltersOptions): FilterFieldsData => {
164
+ const result: FilterFieldsData = {
165
+ [ASSET_FILTERS.CHANGED]: {
166
+ label: I18N.CHANGED,
167
+ defaultValue: filters[ASSET_FILTERS.CHANGED],
168
+ disabled: !compareMode,
169
+ },
170
+ };
171
+
172
+ if (!isEmpty(chunks)) {
173
+ const chunksFilter: FilterGroupFieldData = {
174
+ label: I18N.CHUNKS,
175
+ children: [
176
+ {
177
+ key: NO_CHUNK_FILTER,
178
+ label: I18N.NO_CHUNK,
179
+ defaultValue: filters[`${ASSET_CHUNK}.${NO_CHUNK_FILTER}`] ?? true,
180
+ },
181
+ ],
182
+ };
183
+
184
+ const chunksOrderedByName = orderBy(chunks, 'name');
185
+
186
+ chunksOrderedByName.forEach((chunk) => {
187
+ chunksFilter.children.push({
188
+ key: chunk.id,
189
+ label: chunk.name,
190
+ defaultValue: filters[`${ASSET_CHUNK}.${chunk.id}`] ?? true,
191
+ });
192
+ });
193
+
194
+ result[ASSET_CHUNK] = chunksFilter;
195
+ }
196
+
197
+ result[ASSET_ENTRY_TYPE] = {
198
+ label: I18N.FILE_TYPE,
199
+ children: [
200
+ {
201
+ key: ASSET_FILTERS.ENTRY,
202
+ label: I18N.ENTRY,
203
+ defaultValue: get(filters, `${ASSET_ENTRY_TYPE}.${ASSET_FILTERS.ENTRY}`, true),
204
+ },
205
+ {
206
+ key: ASSET_FILTERS.INITIAL,
207
+ label: I18N.INITIAL,
208
+ defaultValue: get(filters, `${ASSET_ENTRY_TYPE}.${ASSET_FILTERS.INITIAL}`, true),
209
+ },
210
+ {
211
+ key: ASSET_FILTERS.CHUNK,
212
+ label: I18N.CHUNK,
213
+ defaultValue: get(filters, `${ASSET_ENTRY_TYPE}.${ASSET_FILTERS.CHUNK}`, true),
214
+ },
215
+ {
216
+ key: ASSET_FILTERS.OTHER,
217
+ label: I18N.OTHER,
218
+ defaultValue: get(filters, `${ASSET_ENTRY_TYPE}.${ASSET_FILTERS.OTHER}`, true),
219
+ },
220
+ ],
221
+ };
222
+
223
+ result[ASSET_FILE_TYPE] = {
224
+ label: I18N.FILE_TYPE,
225
+ children: getFileTypeFilters(filters),
226
+ };
227
+
228
+ return result;
229
+ };
230
+
231
+ /* eslint-disable prettier/prettier */
232
+ export const generateGetRowFilter =
233
+ ({ chunkIds }: GenerateGetRowFilterOptions) => (filters: Record<string, unknown>) => {
234
+ // List of chunkIds with filter value set to `true`
235
+ const checkedChunkIds: Array<string> = [];
236
+ // List of chunks ids, including the NO_CHUNK
237
+ const filtersChunkIds = [NO_CHUNK_FILTER, ...chunkIds];
238
+
239
+ filtersChunkIds.forEach((chunkId) => {
240
+ if (filters[`${ASSET_CHUNK}.${chunkId}`]) {
241
+ checkedChunkIds.push(chunkId);
242
+ }
243
+ });
244
+
245
+ const hasChunkFilters =
246
+ checkedChunkIds.length > 0 && checkedChunkIds.length !== filtersChunkIds.length;
247
+
248
+ return (item: ReportMetricAssetRow) => {
249
+ if (filters[ASSET_FILTERS.CHANGED] && !item.changed) {
250
+ return false;
251
+ }
252
+
253
+ if (
254
+ !(
255
+ (filters[`${ASSET_ENTRY_TYPE}.${ASSET_FILTERS.ENTRY}`] && item.isEntry) ||
256
+ (filters[`${ASSET_ENTRY_TYPE}.${ASSET_FILTERS.INITIAL}`] && item.isInitial) ||
257
+ (filters[`${ASSET_ENTRY_TYPE}.${ASSET_FILTERS.CHUNK}`] && item.isChunk) ||
258
+ (filters[`${ASSET_ENTRY_TYPE}.${ASSET_FILTERS.OTHER}`] && item.isAsset)
259
+ )
260
+ ) {
261
+ return false;
262
+ }
263
+
264
+ if (!filters[`${ASSET_FILE_TYPE}.${item.fileType}`]) {
265
+ return false;
266
+ }
267
+
268
+ // Filter if any of the chunkIds are checked
269
+ if (hasChunkFilters) {
270
+ const rowRunsChunkIds = item?.runs?.map((run) => run?.chunkId || NO_CHUNK_FILTER) || [];
271
+ return intersection(rowRunsChunkIds, checkedChunkIds).length > 0;
272
+ }
273
+
274
+ return true;
275
+ };
276
+ };