@balena/ui-shared-components 15.2.4-build-drop-some-lodash-for-native-alternatives-2e2165e6ae9420fd623789747910f4a6e6d463fb-1 → 15.2.4-build-remove-column-management-experimental-code-79be8f7aaed914004e675a86a775e5a02eb4daa0-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.
@@ -7,8 +7,9 @@ import { ApplicationInstructions } from './ApplicationInstructions';
7
7
  import { DropDownButton } from '../DropDownButton';
8
8
  import pickBy from 'lodash/pickBy';
9
9
  import debounce from 'lodash/debounce';
10
+ import isEmpty from 'lodash/isEmpty';
10
11
  import { OsTypesEnum } from './models';
11
- import { uniq } from '../../utils/arrays';
12
+ import uniq from 'lodash/uniq';
12
13
  import { enqueueSnackbar } from 'notistack';
13
14
  import { DialogWithCloseButton } from '../DialogWithCloseButton';
14
15
  import { Callout } from '../Callout';
@@ -16,7 +17,6 @@ import { Spinner } from '../Spinner';
16
17
  import { faDownload } from '@fortawesome/free-solid-svg-icons';
17
18
  import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
18
19
  import * as semver from 'balena-semver';
19
- import { isObjectEmpty } from '../../utils/objects';
20
20
  const etcherLogoBase64 = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iODAwIiBoZWlnaHQ9IjYwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KIDxnPgogIDx0aXRsZT5FdGNoZXI8L3RpdGxlPgogIDxnIGlkPSJzdmdfMSIgc3Ryb2tlPSJudWxsIj4KICAgPHBhdGggaWQ9InN2Z18yIiBjbGFzcz0ic3QxIiBkPSJtNDEyLjkwMzgzLDM1OC4wNjcxM2wwLDE3MS40OTU4M2M3LjQ5MjU0LC0xLjY2NTAxIDE0LjE1MjU3LC0zLjMzMDAyIDIwLjgxMjYsLTcuNDkyNTRsMTQyLjM1ODE5LC04MS41ODUzOWMyMC44MTI2LC0xMS42NTUwNiAzMy4zMDAxNiwtMzQuMTMyNjYgMzMuMzAwMTYsLTU4LjI3NTI4bDAsLTE2Mi4zMzgyOGMwLC02LjY2MDAzIC0wLjgzMjUsLTEzLjMyMDA2IC0zLjMzMDAyLC0xOS4xNDc1OWwtMTU0LjAxMzI0LDg5LjA3NzkzYy0zMi40Njc2NiwyMi40Nzc2MSAtMzkuMTI3NjksNDMuMjkwMjEgLTM5LjEyNzY5LDY4LjI2NTMzbDAsLTAuMDAwMDF6IiBmaWxsPSIjQTVERTM3IiBzdHJva2U9Im51bGwiLz4KICAgPHBhdGggaWQ9InN2Z18zIiBjbGFzcz0ic3QyIiBkPSJtNjYyLjY1NTAzLDE2Ny40MjM3MWwtNTYuNjEwMjcsMzIuNDY3NjZjMS42NjUwMSw1LjgyNzUzIDMuMzMwMDIsMTIuNDg3NTYgMy4zMzAwMiwxOS4xNDc1OWwwLDE2My4xNzA3OWMwLDI0LjE0MjYyIC0xMy4zMjAwNiw0Ni42MjAyMiAtMzMuMzAwMTYsNTguMjc1MjhsLTE0Mi4zNTgxOSw4MS41ODUzOWMtNi42NjAwMywzLjMzMDAyIC0xMy4zMjAwNiw1LjgyNzUzIC0yMC44MTI2LDcuNDkyNTRsMCw2NC45MzUzMWM5Ljk5MDA1LC0xLjY2NTAxIDE5Ljk4MDEsLTQuOTk1MDIgMjguMzA1MTQsLTkuOTkwMDVsMTg0LjgxNTg5LC0xMDUuNzI4MDFjMjUuODA3NjIsLTE0Ljk4NTA3IDQxLjYyNTIsLTQyLjQ1NzcgNDEuNjI1MiwtNzIuNDI3ODVsMCwtMjExLjQ1NjAyYzAsLTkuMTU3NTQgLTEuNjY1MDEsLTE4LjMxNTA5IC00Ljk5NTAyLC0yNy40NzI2M2wtMC4wMDAwMSwweiIgZmlsbD0iI0M4RjE3OCIgc3Ryb2tlPSJudWxsIi8+CiAgIDxwYXRoIGlkPSJzdmdfNCIgY2xhc3M9InN0MSIgZD0ibTM5OS41ODM3NiwzMDMuOTU0MzZjOC4zMjUwNCwtMTMuMzIwMDYgMjAuODEyNiwtMjUuODA3NjIgMzkuMTI3NjksLTM2LjYzMDE4bDE1NS42NzgyNSwtODkuOTEwNDNjLTQuOTk1MDIsLTYuNjYwMDMgLTExLjY1NTA2LC0xMi40ODc1NiAtMTguMzE1MDksLTE2LjY1MDA4bC0xNDIuMzU4MTksLTgxLjU4NTM5Yy0yMC44MTI2LC0xMS42NTUwNiAtNDYuNjIwMjIsLTExLjY1NTA2IC02Ny40MzI4MiwwbC0xNDEuNTI1NjgsODEuNTg1MzljLTcuNDkyNTQsNC4xNjI1MiAtMTMuMzIwMDYsOS45OTAwNSAtMTkuMTQ3NTksMTYuNjUwMDhsMTU0Ljg0NTc1LDg5LjkxMDQzYzE4LjMxNTA5LDExLjY1NTA2IDMwLjgwMjY1LDIzLjMxMDExIDM5LjEyNzY5LDM2LjYzMDE4bC0wLjAwMDAxLDB6IiBmaWxsPSIjQTVERTM3IiBzdHJva2U9Im51bGwiLz4KICAgPHBhdGggaWQ9InN2Z181IiBjbGFzcz0ic3QyIiBkPSJtMjI0Ljc1NzkyLDE2MS41OTYxOGwxNDEuNTI1NjgsLTgxLjU4NTM5YzIwLjgxMjYsLTExLjY1NTA2IDQ2LjYyMDIyLC0xMS42NTUwNiA2Ny40MzI4MiwwbDE0Mi4zNTgxOSw4MS41ODUzOWM3LjQ5MjU0LDQuMTYyNTIgMTMuMzIwMDYsOS45OTAwNSAxOC4zMTUwOSwxNi42NTAwOGw1Ni42MTAyNywtMzIuNDY3NjZjLTYuNjYwMDMsLTkuMTU3NTQgLTE0Ljk4NTA3LC0xNi42NTAwOCAtMjQuOTc1MTIsLTIxLjY0NTFsLTE4NC44MTU4OSwtMTA3LjM5MzAyYy0yNS44MDc2MiwtMTQuOTg1MDcgLTU3LjQ0Mjc4LC0xNC45ODUwNyAtODMuMjUwNCwwbC0xODMuMTUwODgsMTA2LjU2MDUxYy05Ljk5MDA1LDUuODI3NTMgLTE4LjMxNTA5LDEzLjMyMDA2IC0yNC45NzUxMiwyMi40Nzc2MWw1Ni42MTAyNywzMi40Njc2NmM0LjE2MjUyLC02LjY2MDAzIDEwLjgyMjU1LC0xMi40ODc1NiAxOC4zMTUwOSwtMTYuNjUwMDh6IiBmaWxsPSIjQzhGMTc4IiBzdHJva2U9Im51bGwiLz4KICAgPHBhdGggaWQ9InN2Z182IiBjbGFzcz0ic3QyIiBkPSJtMzY2LjI4MzYsNTIyLjA3MDQxbC0xNDEuNTI1NjgsLTgxLjU4NTM5Yy0yMC44MTI2LC0xMS42NTUwNiAtMzMuMzAwMTYsLTM0LjEzMjY2IC0zMy4zMDAxNiwtNTguMjc1MjhsMCwtMTYzLjE3MDc5YzAsLTYuNjYwMDMgMC44MzI1LC0xMi40ODc1NiAyLjQ5NzUxLC0xOC4zMTUwOWwtNTYuNjEwMjcsLTMyLjQ2NzY2Yy0zLjMzMDAyLDkuMTU3NTQgLTQuOTk1MDIsMTcuNDgyNTggLTQuOTk1MDIsMjYuNjQwMTNsMCwyMTIuMjg4NTJjMCwyOS45NzAxNCAxNS44MTc1OCw1Ny40NDI3OCA0MS42MjUyLDcxLjU5NTM0bDE4My45ODMzOSwxMDUuNzI4MDFjOC4zMjUwNCw0Ljk5NTAyIDE4LjMxNTA5LDguMzI1MDQgMjguMzA1MTQsOS45OTAwNWwwLC02NC45MzUzMWMtNi42NjAwMywtMC44MzI1IC0xMy4zMjAwNiwtMy4zMzAwMiAtMTkuOTgwMSwtNy40OTI1NGwtMC4wMDAwMSwwLjAwMDAxeiIgZmlsbD0iI0M4RjE3OCIgc3Ryb2tlPSJudWxsIi8+CiAgIDxwYXRoIGlkPSJzdmdfNyIgY2xhc3M9InN0MSIgZD0ibTM0Ny4xMzYwMSwyODguOTY5MjlsLTE1My4xODA3NCwtODguMjQ1NDJjLTEuNjY1MDEsNS44Mjc1MyAtMi40OTc1MSwxMi40ODc1NiAtMi40OTc1MSwxOC4zMTUwOWwwLDE2My4xNzA3OWMwLDI0LjE0MjYyIDEyLjQ4NzU2LDQ2LjYyMDIyIDMzLjMwMDE2LDU4LjI3NTI4bDE0MS41MjU2OCw4MS41ODUzOWM2LjY2MDAzLDMuMzMwMDIgMTMuMzIwMDYsNS44Mjc1MyAyMC44MTI2LDcuNDkyNTRsMCwtMTcxLjQ5NTgzYy0wLjgzMjUsLTI0Ljk3NTEyIC03LjQ5MjU0LC00NS43ODc3MiAtMzkuOTYwMTksLTY5LjA5NzgzbDAsLTAuMDAwMDF6IiBmaWxsPSIjQTVERTM3IiBzdHJva2U9Im51bGwiLz4KICA8L2c+CiA8L2c+Cgo8L3N2Zz4=';
21
21
  const ETCHER_OPEN_IMAGE_URL = 'https://www.balena.io/etcher/open-image-url';
22
22
  export var ActionType;
@@ -26,10 +26,9 @@ export var ActionType;
26
26
  ActionType["downloadConfigFile"] = "download_config_file";
27
27
  })(ActionType || (ActionType = {}));
28
28
  const getUniqueOsTypes = (osVersions, deviceTypeSlug) => {
29
- var _a;
30
- if (isObjectEmpty(osVersions) ||
29
+ if (isEmpty(osVersions) ||
31
30
  !deviceTypeSlug ||
32
- ((_a = osVersions[deviceTypeSlug]) === null || _a === void 0 ? void 0 : _a.length) === 0) {
31
+ isEmpty(osVersions[deviceTypeSlug])) {
33
32
  return [];
34
33
  }
35
34
  return uniq(osVersions[deviceTypeSlug].map((x) => x.osType));
@@ -99,7 +98,7 @@ export const DownloadImageDialog = ({ open, applicationId, releaseId, compatible
99
98
  [initialDeviceType.slug]: osTypes.includes(OsTypesEnum.ESR),
100
99
  }
101
100
  : {});
102
- const [isFetching, setIsFetching] = useState(isObjectEmpty(osVersions));
101
+ const [isFetching, setIsFetching] = useState(isEmpty(osVersions));
103
102
  const [downloadSize, setDownloadSize] = useState(null);
104
103
  const [isValidatingUrl, setIsValidatingUrl] = useState(false);
105
104
  const defaultDisplayName = useMemo(() => { var _a, _b; return (_b = (_a = formModel.deviceType) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : '-'; }, [(_a = formModel.deviceType) === null || _a === void 0 ? void 0 : _a.name]);
@@ -266,7 +265,7 @@ export const DownloadImageDialog = ({ open, applicationId, releaseId, compatible
266
265
  sm: 12,
267
266
  md: 6,
268
267
  lg: 7,
269
- }, children: isFetching ? (_jsx(Spinner, {})) : (_jsxs(_Fragment, { children: [isObjectEmpty(osVersions) && (_jsx(Callout, { severity: "warning", children: "No OS versions available for download" })), !!osType && !!compatibleDeviceTypes && (_jsx(ImageForm, { applicationId: applicationId, releaseId: releaseId, compatibleDeviceTypes: compatibleDeviceTypes, osVersions: osVersions, isInitialDefault: isInitialDefault, hasEsrVersions: deviceTypeHasEsr[formModel.deviceType.slug], formElement: formElement, downloadUrl: downloadUrl, authToken: authToken, osType: osType, osTypes: osTypes, model: formModel, onSelectedOsTypeChange: setOsTypeCallback, onChange: handleChange }))] })) }), _jsxs(Grid, { pb: 0, size: {
268
+ }, children: isFetching ? (_jsx(Spinner, {})) : (_jsxs(_Fragment, { children: [isEmpty(osVersions) && (_jsx(Callout, { severity: "warning", children: "No OS versions available for download" })), !!osType && !!compatibleDeviceTypes && (_jsx(ImageForm, { applicationId: applicationId, releaseId: releaseId, compatibleDeviceTypes: compatibleDeviceTypes, osVersions: osVersions, isInitialDefault: isInitialDefault, hasEsrVersions: deviceTypeHasEsr[formModel.deviceType.slug], formElement: formElement, downloadUrl: downloadUrl, authToken: authToken, osType: osType, osTypes: osTypes, model: formModel, onSelectedOsTypeChange: setOsTypeCallback, onChange: handleChange }))] })) }), _jsxs(Grid, { pb: 0, size: {
270
269
  xs: 12,
271
270
  sm: 12,
272
271
  md: 6,
@@ -1,4 +1,4 @@
1
- import { uniq } from '../../utils/arrays';
1
+ import uniq from 'lodash/uniq';
2
2
  import partition from 'lodash/partition';
3
3
  export const transformVersions = (versions) => {
4
4
  const optsByVersion = {};
@@ -5,6 +5,7 @@ import { Button, ButtonGroup, MenuItem, Menu } from '@mui/material';
5
5
  import { ButtonWithTracking } from '../ButtonWithTracking';
6
6
  import { useAnalyticsContext } from '../../contexts/AnalyticsContext';
7
7
  import groupBy from 'lodash/groupBy';
8
+ import flatMap from 'lodash/flatMap';
8
9
  import { Tooltip } from '../Tooltip';
9
10
  import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
10
11
  import { faCaretDown, faCaretUp, faChevronDown, faChevronUp, } from '@fortawesome/free-solid-svg-icons';
@@ -21,17 +22,16 @@ export const DropDownButton = (_a) => {
21
22
  // const items = [{...menuItem, section: 'test1'}, {...menuItem, section: 'test2'}];
22
23
  // <Dropdown groupByProp='section' .../>
23
24
  const memoizedItems = useMemo(() => {
24
- var _a;
25
25
  if (!groupByProp) {
26
26
  return items;
27
27
  }
28
28
  const grouped = groupBy(items, (item) => item[groupByProp]);
29
- const entries = Object.entries(grouped);
30
- const lastKey = (_a = entries.at(-1)) === null || _a === void 0 ? void 0 : _a[0];
31
- return entries
32
- .flatMap(([key, value]) => value.map((v, index) => key !== lastKey && index === value.length - 1
33
- ? Object.assign(Object.assign({}, v), { divider: true }) : v))
34
- .filter(Boolean);
29
+ const keys = Object.keys(grouped);
30
+ const lastKey = keys[keys.length - 1];
31
+ return flatMap(grouped, (value, key) => [
32
+ ...value.map((v, index) => key !== lastKey && index === value.length - 1
33
+ ? Object.assign(Object.assign({}, v), { divider: true }) : v),
34
+ ]).filter((item) => item);
35
35
  }, [items, groupByProp]);
36
36
  const handleClick = (event) => {
37
37
  var _a, _b, _c;
@@ -7,7 +7,7 @@ import { IconButtonWithTracking, Tooltip } from '../../..';
7
7
  import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
8
8
  import { faCircleExclamation, faFile, faFileImage, faTrash, faUpload, } from '@fortawesome/free-solid-svg-icons';
9
9
  import { useRandomUUID } from '../../../hooks/useRandomUUID';
10
- import { uniq } from '../../../utils/arrays';
10
+ import uniq from 'lodash/uniq';
11
11
  import { token } from '../../../utils/token';
12
12
  const restingStyle = {
13
13
  borderColor: token('color.border'),
@@ -2,7 +2,6 @@ import { FULL_TEXT_SLUG, createModelFilter, } from '../components/Filters/Schema
2
2
  import { getDataTypeSchema } from './utils';
3
3
  import { getDataModel } from '.';
4
4
  import { getRefSchema, isJSONSchema } from '../schemaOps';
5
- import { isObjectEmpty } from '../../../utils/objects';
6
5
  export const operators = () => ({
7
6
  contains: 'contains',
8
7
  not_contains: 'does not contain',
@@ -18,7 +17,7 @@ const isArrayOfObjectSchema = (schema) => {
18
17
  };
19
18
  const buildFilterForPropertySchema = (field, operator, value, schema) => {
20
19
  const filter = getFilter(field, schema, value, operator);
21
- if (isObjectEmpty(filter)) {
20
+ if (!Object.keys(filter).length) {
22
21
  return {};
23
22
  }
24
23
  return {
@@ -56,7 +55,7 @@ const getFilter = (field, schema, value, operator) => {
56
55
  operator: effectiveOperator,
57
56
  value,
58
57
  });
59
- if (!filter || typeof filter !== 'object' || isObjectEmpty(filter)) {
58
+ if (!filter || typeof filter !== 'object' || !Object.keys(filter).length) {
60
59
  return {};
61
60
  }
62
61
  const recursiveFilter = hasPrimitiveItems
@@ -64,7 +63,7 @@ const getFilter = (field, schema, value, operator) => {
64
63
  : filter;
65
64
  return recursiveFilter &&
66
65
  isJSONSchema(recursiveFilter) &&
67
- !isObjectEmpty(recursiveFilter)
66
+ Object.keys(recursiveFilter).length
68
67
  ? wrapFilter(recursiveFilter)
69
68
  : {};
70
69
  };
@@ -1,31 +1,22 @@
1
+ import find from 'lodash/find';
1
2
  import { getDataTypeSchema, regexEscape } from './utils';
2
3
  import { FULL_TEXT_SLUG, createModelFilter, } from '../components/Filters/SchemaSieve';
3
4
  import { isJSONSchema, getRefSchema } from '../schemaOps';
5
+ import findKey from 'lodash/findKey';
4
6
  import pick from 'lodash/pick';
5
7
  import mapValues from 'lodash/mapValues';
6
- const findValueByDescription = (obj, description) => {
7
- return Object.values(obj !== null && obj !== void 0 ? obj : {}).find((property) => typeof property === 'object' &&
8
- 'description' in property &&
9
- property.description === description);
10
- };
11
- const findKeyByDescription = (obj, description) => {
12
- var _a;
13
- return (_a = Object.entries(obj !== null && obj !== void 0 ? obj : {}).find(([, value]) => typeof value === 'object' &&
14
- 'description' in value &&
15
- value.description === description)) === null || _a === void 0 ? void 0 : _a[0];
16
- };
17
8
  const getKeyLabel = (schema) => {
18
9
  var _a;
19
- const s = findValueByDescription(schema.properties, 'key');
10
+ const s = find(schema.properties, { description: 'key' });
20
11
  return (_a = s === null || s === void 0 ? void 0 : s.title) !== null && _a !== void 0 ? _a : 'key';
21
12
  };
22
13
  const getValueLabel = (schema) => {
23
14
  var _a;
24
- const s = findValueByDescription(schema.properties, 'value');
15
+ const s = find(schema.properties, { description: 'value' });
25
16
  return (_a = s === null || s === void 0 ? void 0 : s.title) !== null && _a !== void 0 ? _a : 'value';
26
17
  };
27
- export const isKeyValueObj = (schema) => !!findValueByDescription(schema.properties, 'key') ||
28
- !!findValueByDescription(schema.properties, 'value');
18
+ export const isKeyValueObj = (schema) => !!find(schema.properties, { description: 'key' }) ||
19
+ !!find(schema.properties, { description: 'value' });
29
20
  export const operators = (s) => {
30
21
  return Object.assign({ is: 'is', is_not: 'is not' }, (!isKeyValueObj(s)
31
22
  ? {
@@ -82,7 +73,7 @@ const getValueForOperation = (operator, schema, value) => {
82
73
  ? 'value'
83
74
  : null;
84
75
  const schemaProperty = schemaField
85
- ? findKeyByDescription(schema.properties, schemaField)
76
+ ? findKey(schema.properties, { description: schemaField })
86
77
  : null;
87
78
  // Return the appropriate value format based on the operation type
88
79
  return schemaProperty
@@ -150,8 +141,8 @@ export const createFilter = (field, operator, value, schema) => {
150
141
  }
151
142
  // TODO: this case does not cover complex objects for FULL_TEXT_SLUG
152
143
  if (operator === FULL_TEXT_SLUG && schema.properties) {
153
- const schemaKey = findKeyByDescription(schema.properties, 'key');
154
- const schemaValue = findKeyByDescription(schema.properties, 'value');
144
+ const schemaKey = findKey(schema.properties, { description: 'key' });
145
+ const schemaValue = findKey(schema.properties, { description: 'value' });
155
146
  const properties = [schemaKey, schemaValue]
156
147
  .map((key) => key
157
148
  ? {
@@ -1,10 +1,9 @@
1
1
  import { convertRefSchemeToSchemaPath, getRefSchemeTitle, getRefSchemePrefix, isJSONSchema, parseDescription, parseDescriptionProperty, } from '../schemaOps';
2
+ import isEmpty from 'lodash/isEmpty';
2
3
  import get from 'lodash/get';
3
- import { isObjectEmpty } from '../../../utils/objects';
4
4
  const X_FOREIGN_KEY_SCHEMA_SEPARATOR = '___ref_scheme_separator_';
5
5
  export const removeFieldsWithNoFilter = (schema) => {
6
6
  const processProperties = (properties, parentXNoFilterSet) => {
7
- var _a;
8
7
  if (!properties) {
9
8
  return undefined;
10
9
  }
@@ -41,10 +40,10 @@ export const removeFieldsWithNoFilter = (schema) => {
41
40
  newValue.items = Object.assign(Object.assign({}, value.items), { properties: processProperties(value.items.properties, xNoFilterSet) });
42
41
  }
43
42
  }
44
- const hasEmptyProperties = newValue.properties && isObjectEmpty(newValue.properties);
43
+ const hasEmptyProperties = newValue.properties && isEmpty(newValue.properties);
45
44
  const hasEmptyItemsProperties = isJSONSchema(newValue.items) &&
46
45
  'properties' in newValue.items &&
47
- isObjectEmpty((_a = newValue.items.properties) !== null && _a !== void 0 ? _a : {});
46
+ isEmpty(newValue.items.properties);
48
47
  if (hasEmptyProperties || hasEmptyItemsProperties) {
49
48
  continue;
50
49
  }
@@ -1,4 +1,5 @@
1
1
  import * as types from './types';
2
+ import uniq from 'lodash/uniq';
2
3
  const lenses = Object.values(types);
3
4
  // Returns an array of lenses that can be used to render `data`.
4
5
  export const getLenses = (data, customLenses) => {
@@ -7,7 +8,7 @@ export const getLenses = (data, customLenses) => {
7
8
  }
8
9
  const concatenatedLenses = lenses.concat(customLenses !== null && customLenses !== void 0 ? customLenses : []);
9
10
  const slugs = concatenatedLenses.map((lens) => lens.slug);
10
- if (slugs.length > new Set(slugs).size) {
11
+ if (slugs.length > uniq(slugs).length) {
11
12
  throw new Error('Lenses must have unique slugs');
12
13
  }
13
14
  return concatenatedLenses;
@@ -4,7 +4,6 @@ import addFormats from 'ajv-formats';
4
4
  import pickBy from 'lodash/pickBy';
5
5
  import Ajv from 'ajv';
6
6
  import { enqueueSnackbar } from 'notistack';
7
- import { isObjectEmpty } from '../../../../utils/objects';
8
7
  const ajv = new Ajv();
9
8
  ajvKeywords(ajv, ['regexp']);
10
9
  // TODO: check why is this needed
@@ -72,7 +71,9 @@ export const createFilter = (schema, formData) => {
72
71
  operator,
73
72
  value,
74
73
  });
75
- if (!filter || typeof filter !== 'object' || isObjectEmpty(filter)) {
74
+ if (!filter ||
75
+ typeof filter !== 'object' ||
76
+ !Object.keys(filter).length) {
76
77
  return {};
77
78
  }
78
79
  return Object.assign({ $id: randomUUID(), title: operator, description: JSON.stringify({
@@ -8,25 +8,20 @@ import { token } from '../../../../utils/token';
8
8
  import { DndContext } from '@dnd-kit/core';
9
9
  import { CSS } from '@dnd-kit/utilities';
10
10
  import { arrayMove, SortableContext, useSortable } from '@dnd-kit/sortable';
11
- import { useAnalyticsContext } from '../../../../contexts/AnalyticsContext';
12
11
  const SortableItem = ({ column, handleColumnSelection, }) => {
13
- var _a, _b, _c, _d;
14
- const { state: analyticsState } = useAnalyticsContext();
15
12
  const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id: column.key });
16
- return (_jsxs(MenuItem, Object.assign({ ref: setNodeRef }, attributes, { sx: { transform: CSS.Transform.toString(transform), transition }, children: [(((_b = (_a = analyticsState.featureFlags) === null || _a === void 0 ? void 0 : _a['column-ordering']) === null || _b === void 0 ? void 0 : _b.value) === 'on' ||
17
- ((_d = (_c = analyticsState.featureFlags) === null || _c === void 0 ? void 0 : _c['reduced-default-device-columns-and-reordering']) === null || _d === void 0 ? void 0 : _d.value) === 'on') && (_jsx(ListItemIcon, Object.assign({}, listeners, { sx: {
13
+ return (_jsxs(MenuItem, Object.assign({ ref: setNodeRef }, attributes, { sx: { transform: CSS.Transform.toString(transform), transition }, children: [_jsx(ListItemIcon, Object.assign({}, listeners, { sx: {
18
14
  cursor: 'grab',
19
15
  pr: 2,
20
16
  mx: 0,
21
17
  minWidth: 'auto !important',
22
- }, children: _jsx(FontAwesomeIcon, { icon: faGripVertical }) }))), _jsx(FormControlLabel, { sx: { flex: 1, width: '100%', m: 0 }, control: _jsx(Checkbox, { sx: { m: 0 }, onClick: () => {
18
+ }, children: _jsx(FontAwesomeIcon, { icon: faGripVertical }) })), _jsx(FormControlLabel, { sx: { flex: 1, width: '100%', m: 0 }, control: _jsx(Checkbox, { sx: { m: 0 }, onClick: () => {
23
19
  handleColumnSelection(column);
24
20
  }, checked: column.selected }), label: typeof column.label === 'string' ? column.label : column.title })] })));
25
21
  };
26
22
  export const TableActions = ({ columns, actions, onColumnPreferencesChange, onManageColumnsOpen, }) => {
27
23
  const [anchorEl, setAnchorEl] = React.useState();
28
24
  const theme = useTheme();
29
- const { state: analyticsState } = useAnalyticsContext();
30
25
  const matches = useMediaQuery(theme.breakpoints.up('sm'));
31
26
  const open = Boolean(anchorEl);
32
27
  const handleClick = (event) => {
@@ -48,13 +43,8 @@ export const TableActions = ({ columns, actions, onColumnPreferencesChange, onMa
48
43
  onColumnPreferencesChange(newColumns, 'display');
49
44
  }, [columns, onColumnPreferencesChange]);
50
45
  const handleDragEnd = (event) => {
51
- var _a, _b, _c, _d;
52
46
  const { active, over } = event;
53
- if (!active ||
54
- !over ||
55
- !onColumnPreferencesChange ||
56
- (!(((_b = (_a = analyticsState.featureFlags) === null || _a === void 0 ? void 0 : _a['column-reordering']) === null || _b === void 0 ? void 0 : _b.value) === 'on') &&
57
- !(((_d = (_c = analyticsState.featureFlags) === null || _c === void 0 ? void 0 : _c['reduced-default-device-columns-and-reordering']) === null || _d === void 0 ? void 0 : _d.value) === 'on'))) {
47
+ if (!active || !over || !onColumnPreferencesChange) {
58
48
  return;
59
49
  }
60
50
  const oldIndex = columns.findIndex((c) => c.key === active.id);
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useMemo, useState } from 'react';
3
3
  import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
4
4
  import { faPlus } from '@fortawesome/free-solid-svg-icons/faPlus';
5
- import { uniq } from '../../../../utils/arrays';
5
+ import uniq from 'lodash/uniq';
6
6
  import { useQuery } from '@tanstack/react-query';
7
7
  import { Stack } from '@mui/material';
8
8
  export function useTagActions(rjstContext, data) {
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import get from 'lodash/get';
3
3
  import invokeMap from 'lodash/invokeMap';
4
+ import isArray from 'lodash/isArray';
4
5
  import { UiOption, JsonTypes, widgetFactory, formatTimestamp } from '../utils';
5
6
  import { Truncate } from '../../../../Truncate';
6
7
  import { Typography } from '@mui/material';
@@ -35,7 +36,7 @@ const TxtWidget = widgetFactory('Txt', [
35
36
  variant: UiOption.string,
36
37
  })(({ value, schema, uiSchema }) => {
37
38
  var _a;
38
- let displayValue = Array.isArray(value)
39
+ let displayValue = isArray(value)
39
40
  ? getArrayValue(value, uiSchema)
40
41
  : value === null || value === void 0 ? void 0 : value.toString();
41
42
  if (DATE_TIME_FORMATS.includes((_a = schema === null || schema === void 0 ? void 0 : schema.format) !== null && _a !== void 0 ? _a : '')) {
@@ -1,5 +1,5 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
2
- import { toArray } from '../../../../utils/arrays';
2
+ import castArray from 'lodash/castArray';
3
3
  import { JsonTypes } from './utils';
4
4
  import { typeWidgets } from './Formats';
5
5
  import { getSchemaFormat, getSubSchemaFromRefScheme } from '../../schemaOps';
@@ -38,7 +38,7 @@ export const Widget = ({ value, resource, schema = {}, extraFormats, uiSchema, }
38
38
  }
39
39
  const processedValue = getValue(value, schema, uiSchema);
40
40
  const subSchema = getSubSchemaFromRefScheme(schema);
41
- const types = (subSchema === null || subSchema === void 0 ? void 0 : subSchema.type) != null ? toArray(subSchema.type) : [];
41
+ const types = (subSchema === null || subSchema === void 0 ? void 0 : subSchema.type) != null ? castArray(subSchema.type) : [];
42
42
  if (processedValue == null && !types.includes(JsonTypes.null)) {
43
43
  return null;
44
44
  }
@@ -1,4 +1,4 @@
1
- import { isObjectEmpty } from '../../../utils/objects';
1
+ import isEmpty from 'lodash/isEmpty';
2
2
  import { rjstJsonSchemaPick } from '../schemaOps';
3
3
  export const rjstDefaultPermissions = {
4
4
  read: [],
@@ -10,7 +10,7 @@ export const rjstRunTransformers = (data, transformers, context) => {
10
10
  if (!data) {
11
11
  return data;
12
12
  }
13
- if (!transformers || isObjectEmpty(transformers)) {
13
+ if (!transformers || isEmpty(transformers)) {
14
14
  return data;
15
15
  }
16
16
  const transformEntry = (entry) => {
@@ -1,7 +1,6 @@
1
1
  import get from 'lodash/get';
2
2
  import pick from 'lodash/pick';
3
3
  import { findInObject } from './utils';
4
- import { isObjectEmpty } from '../../utils/objects';
5
4
  export const isJson = (str) => {
6
5
  try {
7
6
  JSON.parse(str);
@@ -43,7 +42,7 @@ export const isJSONSchema = (value) => {
43
42
  return (typeof value === 'object' &&
44
43
  value !== null &&
45
44
  typeof value !== 'boolean' &&
46
- !isObjectEmpty(value));
45
+ !!Object.keys(value).length);
47
46
  };
48
47
  export const parseDescription = (filter) => {
49
48
  if (!filter.description) {
@@ -1,5 +1,5 @@
1
1
  import { getPropertyScheme } from './schemaOps';
2
- import { toArray } from '../../utils/arrays';
2
+ import castArray from 'lodash/castArray';
3
3
  import get from 'lodash/get';
4
4
  import { JsonTypes } from './components/Widget/utils';
5
5
  export const DEFAULT_ITEMS_PER_PAGE = 50;
@@ -119,7 +119,7 @@ const sortFn = (a, b, ref) => {
119
119
  return diff(aa, bb);
120
120
  };
121
121
  export const getSortingFunction = (schemaKey, schemaValue) => {
122
- const types = toArray(schemaValue.type);
122
+ const types = castArray(schemaValue.type);
123
123
  const refScheme = getPropertyScheme(schemaValue);
124
124
  const splitRefScheme = (refScheme === null || refScheme === void 0 ? void 0 : refScheme[0]) ? splitPath(refScheme[0]) : null;
125
125
  if (types.includes(JsonTypes.string)) {
@@ -1,5 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import * as React from 'react';
3
+ import find from 'lodash/find';
4
+ import startsWith from 'lodash/startsWith';
5
+ import isEmpty from 'lodash/isEmpty';
3
6
  import { Button, Stack, TextField, Typography } from '@mui/material';
4
7
  import { Callout } from '../Callout';
5
8
  import { useTranslation } from '../../hooks/useTranslations';
@@ -10,7 +13,7 @@ const RESERVED_NAMESPACES = ['io.resin.', 'io.balena.'];
10
13
  const newTagValidationRules = (t, key, existingTags) => {
11
14
  return [
12
15
  {
13
- test: () => !key,
16
+ test: () => !key || isEmpty(key),
14
17
  message: t('fields_errors.tag_name_cannot_be_empty'),
15
18
  },
16
19
  {
@@ -18,7 +21,7 @@ const newTagValidationRules = (t, key, existingTags) => {
18
21
  message: t('fields_errors.tag_names_cannot_contain_whitespace'),
19
22
  },
20
23
  {
21
- test: () => RESERVED_NAMESPACES.some((reserved) => key.startsWith(reserved)),
24
+ test: () => RESERVED_NAMESPACES.some((reserved) => startsWith(key, reserved)),
22
25
  message: t(`fields_errors.some_tag_keys_are_reserved`, {
23
26
  namespace: RESERVED_NAMESPACES.join(', '),
24
27
  }),
@@ -50,7 +53,9 @@ export const AddTagForm = ({ itemType, existingTags, overridableTags = [], addTa
50
53
  return hasErrors;
51
54
  };
52
55
  const checkTagOverwrites = async () => {
53
- const overridableTag = overridableTags.find((tag) => tag.tag_key === tagKey);
56
+ const overridableTag = find(overridableTags, {
57
+ tag_key: tagKey,
58
+ });
54
59
  if (!overridableTag) {
55
60
  return true;
56
61
  }
@@ -5,6 +5,7 @@ import { faUndo } from '@fortawesome/free-solid-svg-icons/faUndo';
5
5
  import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
6
6
  import { AddTagForm } from './AddTagForm';
7
7
  import sortBy from 'lodash/sortBy';
8
+ import toString from 'lodash/toString';
8
9
  import { faPencilAlt } from '@fortawesome/free-solid-svg-icons/faPencilAlt';
9
10
  import { getResourceTagSubmitInfo, groupResourcesByTags, } from './tag-management-service';
10
11
  import partition from 'lodash/partition';
@@ -185,10 +186,9 @@ export const TagManagementDialog = ({ items, itemType, titleField, tagField, can
185
186
  setTags(tags.slice());
186
187
  };
187
188
  const getItemTitle = (item) => {
188
- var _a;
189
189
  const title = typeof titleField === 'function'
190
190
  ? titleField(item)
191
- : `${(_a = item[titleField]) !== null && _a !== void 0 ? _a : ''}`;
191
+ : toString(item[titleField]);
192
192
  return title || `(${t('no_data.no_name_set')})`;
193
193
  };
194
194
  return (_jsxs(DialogWithCloseButton, { open: true, title: _jsxs(Stack, { children: [_jsxs(Typography, { variant: "h3", mt: 0, mb: 10, children: [items.length > 1 && _jsxs("span", { children: [t('labels.shared'), " "] }), t('labels.tags')] }), _jsx(CollectionSummary, { items: items.map(getItemTitle).sort(), itemsType: t('resource.' + itemType, { count: items.length }), maxVisibleItemCount: 10 })] }), children: [_jsxs(DialogContent, { children: [_jsx(AddTagForm, { itemType: itemType, existingTags: tags, overridableTags: partialTags, addTag: addTag, t: t }), _jsxs(Table, { children: [_jsxs(TableHead, { children: [_jsx(TableCell, {}), _jsx(TableCell, { children: t('labels.tag_name') }), _jsx(TableCell, { children: t('labels.value') }), _jsx(TableCell, {})] }), _jsx(TableBody, { children: !tags.length ? (_jsxs(TableRow, { children: [_jsx(TableCell, {}), _jsx(TableCell, { children: t(`errors.no_tags_for_selected_itemtype`, {
@@ -1,9 +1,12 @@
1
+ import keys from 'lodash/keys';
2
+ import flatMap from 'lodash/flatMap';
3
+ import map from 'lodash/map';
1
4
  import groupBy from 'lodash/groupBy';
2
5
  export const TAGS_COLUMN_KEY = 'Tags';
3
6
  export const getTagKeyValueComposite = (tagKey, value) => `${tagKey}: ${value}`;
4
7
  export const getResourceTags = (item, tagField) => { var _a; return ((_a = (tagField in item ? item[tagField] : null)) !== null && _a !== void 0 ? _a : []); };
5
8
  export const groupResourcesByTags = (items, tagField) => {
6
- const resourceTagInfos = items.flatMap((item) => {
9
+ const resourceTagInfos = flatMap(items, (item) => {
7
10
  const tags = getResourceTags(item, tagField);
8
11
  return tags.map((tag) => ({
9
12
  tag_key_value: getTagKeyValueComposite(tag.tag_key, tag.value),
@@ -13,15 +16,13 @@ export const groupResourcesByTags = (items, tagField) => {
13
16
  }));
14
17
  });
15
18
  const tagsByTagKeyValue = groupBy(resourceTagInfos, 'tag_key_value');
16
- const tagsWithItems = Object.keys(tagsByTagKeyValue)
17
- .sort()
18
- .map((tagKeyValue) => {
19
+ const tagsWithItems = map(keys(tagsByTagKeyValue).sort(), (tagKeyValue) => {
19
20
  const tags = tagsByTagKeyValue[tagKeyValue];
20
21
  const firstTag = tags[0];
21
22
  return {
22
23
  tag_key: firstTag.tag_key,
23
24
  value: firstTag.value,
24
- items: tags.map((tag) => tag.item),
25
+ items: map(tags, 'item'),
25
26
  };
26
27
  });
27
28
  return tagsWithItems;
package/dist/index.d.ts CHANGED
@@ -92,6 +92,5 @@ export * as MaterialDataGrid from '@mui/x-data-grid';
92
92
  export { enqueueSnackbar, closeSnackbar } from 'notistack';
93
93
  export { useRandomUUID } from './hooks/useRandomUUID';
94
94
  export { token } from './utils/token';
95
- export { uniq, toArray } from './utils/arrays';
96
95
  export * as designTokens from '@balena/design-tokens';
97
96
  export * as ReactQuery from '@tanstack/react-query';
package/dist/index.js CHANGED
@@ -53,6 +53,5 @@ export * as MaterialDataGrid from '@mui/x-data-grid';
53
53
  export { enqueueSnackbar, closeSnackbar } from 'notistack';
54
54
  export { useRandomUUID } from './hooks/useRandomUUID';
55
55
  export { token } from './utils/token';
56
- export { uniq, toArray } from './utils/arrays';
57
56
  export * as designTokens from '@balena/design-tokens';
58
57
  export * as ReactQuery from '@tanstack/react-query';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@balena/ui-shared-components",
3
- "version": "15.2.4-build-drop-some-lodash-for-native-alternatives-2e2165e6ae9420fd623789747910f4a6e6d463fb-1",
3
+ "version": "15.2.4-build-remove-column-management-experimental-code-79be8f7aaed914004e675a86a775e5a02eb4daa0-1",
4
4
  "main": "./dist/index.js",
5
5
  "sideEffects": false,
6
6
  "files": [
@@ -135,7 +135,7 @@
135
135
  },
136
136
  "homepage": "https://github.com/balena-io/ui-shared-components#readme",
137
137
  "versionist": {
138
- "publishedAt": "2025-11-14T13:41:36.403Z"
138
+ "publishedAt": "2025-11-17T09:20:04.396Z"
139
139
  },
140
140
  "overrides": {
141
141
  "storybook": "$storybook",
@@ -1,2 +0,0 @@
1
- export declare const uniq: <T>(arr: T[]) => T[];
2
- export declare const toArray: <T>(v: T | T[] | null | undefined) => T[];
@@ -1,6 +0,0 @@
1
- export const uniq = (arr) => {
2
- return Array.from(new Set(arr));
3
- };
4
- export const toArray = (v) => {
5
- return v == null ? [] : Array.isArray(v) ? v : [v];
6
- };
@@ -1 +0,0 @@
1
- export declare const isObjectEmpty: (obj: Record<string, unknown> | object) => boolean;
@@ -1,3 +0,0 @@
1
- export const isObjectEmpty = (obj) => {
2
- return Object.keys(obj).length === 0;
3
- };