@northern.tech/store 0.46.4 → 0.46.5
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/dist/deploymentsSlice/thunks.d.cts +9 -9
- package/dist/deploymentsSlice/thunks.d.ts +9 -9
- package/dist/devicesSlice/selectors.cjs +1 -1
- package/dist/devicesSlice/selectors.cjs.map +1 -1
- package/dist/devicesSlice/selectors.js +1 -1
- package/dist/devicesSlice/selectors.js.map +1 -1
- package/dist/releasesSlice/thunks.d.cts +1 -1
- package/dist/releasesSlice/thunks.d.ts +1 -1
- package/dist/utils.cjs +1 -4
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.js +1 -4
- package/dist/utils.js.map +1 -1
- package/package.json +1 -1
|
@@ -164,7 +164,14 @@ export declare const abortDeployment: import("@reduxjs/toolkit").AsyncThunk<[{
|
|
|
164
164
|
fulfilledMeta?: unknown;
|
|
165
165
|
rejectedMeta?: unknown;
|
|
166
166
|
}>;
|
|
167
|
-
export declare const updateDeploymentControlMap: import("@reduxjs/toolkit").AsyncThunk<import("@reduxjs/toolkit").PayloadAction<
|
|
167
|
+
export declare const updateDeploymentControlMap: import("@reduxjs/toolkit").AsyncThunk<import("@reduxjs/toolkit").PayloadAction<{
|
|
168
|
+
payload: Deployment;
|
|
169
|
+
type: "deployments/receivedDeployment";
|
|
170
|
+
}, string, {
|
|
171
|
+
arg: string;
|
|
172
|
+
requestId: string;
|
|
173
|
+
requestStatus: "fulfilled";
|
|
174
|
+
}, never> | import("@reduxjs/toolkit").PayloadAction<unknown, string, {
|
|
168
175
|
arg: string;
|
|
169
176
|
requestId: string;
|
|
170
177
|
requestStatus: "rejected";
|
|
@@ -174,14 +181,7 @@ export declare const updateDeploymentControlMap: import("@reduxjs/toolkit").Asyn
|
|
|
174
181
|
rejectedWithValue: true;
|
|
175
182
|
} | ({
|
|
176
183
|
rejectedWithValue: false;
|
|
177
|
-
} & {})), import("@reduxjs/toolkit").SerializedError
|
|
178
|
-
payload: Deployment;
|
|
179
|
-
type: "deployments/receivedDeployment";
|
|
180
|
-
}, string, {
|
|
181
|
-
arg: string;
|
|
182
|
-
requestId: string;
|
|
183
|
-
requestStatus: "fulfilled";
|
|
184
|
-
}, never>, {
|
|
184
|
+
} & {})), import("@reduxjs/toolkit").SerializedError>, {
|
|
185
185
|
deploymentId: string;
|
|
186
186
|
updateControlMap: DeploymentV1["update_control_map"];
|
|
187
187
|
}, {
|
|
@@ -164,7 +164,14 @@ export declare const abortDeployment: import("@reduxjs/toolkit").AsyncThunk<[{
|
|
|
164
164
|
fulfilledMeta?: unknown;
|
|
165
165
|
rejectedMeta?: unknown;
|
|
166
166
|
}>;
|
|
167
|
-
export declare const updateDeploymentControlMap: import("@reduxjs/toolkit").AsyncThunk<import("@reduxjs/toolkit").PayloadAction<
|
|
167
|
+
export declare const updateDeploymentControlMap: import("@reduxjs/toolkit").AsyncThunk<import("@reduxjs/toolkit").PayloadAction<{
|
|
168
|
+
payload: Deployment;
|
|
169
|
+
type: "deployments/receivedDeployment";
|
|
170
|
+
}, string, {
|
|
171
|
+
arg: string;
|
|
172
|
+
requestId: string;
|
|
173
|
+
requestStatus: "fulfilled";
|
|
174
|
+
}, never> | import("@reduxjs/toolkit").PayloadAction<unknown, string, {
|
|
168
175
|
arg: string;
|
|
169
176
|
requestId: string;
|
|
170
177
|
requestStatus: "rejected";
|
|
@@ -174,14 +181,7 @@ export declare const updateDeploymentControlMap: import("@reduxjs/toolkit").Asyn
|
|
|
174
181
|
rejectedWithValue: true;
|
|
175
182
|
} | ({
|
|
176
183
|
rejectedWithValue: false;
|
|
177
|
-
} & {})), import("@reduxjs/toolkit").SerializedError
|
|
178
|
-
payload: Deployment;
|
|
179
|
-
type: "deployments/receivedDeployment";
|
|
180
|
-
}, string, {
|
|
181
|
-
arg: string;
|
|
182
|
-
requestId: string;
|
|
183
|
-
requestStatus: "fulfilled";
|
|
184
|
-
}, never>, {
|
|
184
|
+
} & {})), import("@reduxjs/toolkit").SerializedError>, {
|
|
185
185
|
deploymentId: string;
|
|
186
186
|
updateControlMap: DeploymentV1["update_control_map"];
|
|
187
187
|
}, {
|
|
@@ -24,7 +24,7 @@ const getDeviceLimits = (state) => state.devices.limits;
|
|
|
24
24
|
const getTestDeviceCount = (state) => state.devices.testDeviceCount;
|
|
25
25
|
const getFilteringAttributesLimit = (state) => state.devices.filteringAttributesLimit;
|
|
26
26
|
const getDeviceIdentityAttributes = (0, _reduxjs_toolkit.createSelector)([getFilteringAttributes, getFilteringAttributesLimit], ({ identityAttributes }, filteringAttributesLimit) => {
|
|
27
|
-
return identityAttributes.slice(0, filteringAttributesLimit).reduce((accu, value) => {
|
|
27
|
+
return identityAttributes.filter((attribute) => attribute !== "status").slice(0, filteringAttributesLimit).reduce((accu, value) => {
|
|
28
28
|
accu.push({
|
|
29
29
|
value,
|
|
30
30
|
label: value,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selectors.cjs","names":["createSelector","DEVICE_STATES","UNGROUPED_GROUP","duplicateFilter"],"sources":["../../src/devicesSlice/selectors.ts"],"sourcesContent":["// Copyright 2023 Northern.tech AS\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\nimport { duplicateFilter } from '@northern.tech/utils/helpers';\nimport { createSelector } from '@reduxjs/toolkit';\n\nimport type { DeviceFilter, DeviceGroup } from '.';\nimport type { DeviceAuthState } from '../constants';\nimport { DEVICE_STATES, UNGROUPED_GROUP } from '../constants';\nimport type { RootState } from '../store';\n\nexport const getAcceptedDevices = (state: RootState) => state.devices.byStatus.accepted;\nexport const getDevicesByStatus = (state: RootState) => state.devices.byStatus;\nexport const getDevicesById = (state: RootState) => state.devices.byId;\nexport const getDeviceReports = (state: RootState) => state.devices.reports;\nexport const getGroupsById = (state: RootState) => state.devices.groups.byId;\nexport const getSelectedGroup = (state: RootState) => state.devices.groups.selectedGroup;\n\nexport const getDeviceListState = (state: RootState) => state.devices.deviceList;\nexport const getListedDevices = (state: RootState) => state.devices.deviceList.deviceIds;\nexport const getFilteringAttributes = (state: RootState) => state.devices.filteringAttributes;\nexport const getDeviceFilters = (state: RootState) => state.devices.filters || [];\nexport const getTestDeviceLimit = (state: RootState) => state.devices.testDeviceLimit;\nconst getFilteringAttributesFromConfig = (state: RootState) => state.devices.filteringAttributesConfig.attributes;\nexport const getSortedFilteringAttributes = createSelector([getFilteringAttributes], filteringAttributes => ({\n ...filteringAttributes,\n identityAttributes: [...filteringAttributes.identityAttributes, 'id']\n}));\nexport const getDeviceLimits = (state: RootState) => state.devices.limits;\nexport const getTestDeviceCount = (state: RootState) => state.devices.testDeviceCount;\nconst getFilteringAttributesLimit = (state: RootState) => state.devices.filteringAttributesLimit;\n\nexport const getDeviceIdentityAttributes = createSelector(\n [getFilteringAttributes, getFilteringAttributesLimit],\n ({ identityAttributes }, filteringAttributesLimit) => {\n // limit the selection of the available attribute to AVAILABLE_ATTRIBUTE_LIMIT\n const attributes = identityAttributes.slice(0, filteringAttributesLimit);\n return attributes.reduce(\n (accu, value) => {\n accu.push({ value, label: value, scope: 'identity' });\n return accu;\n },\n [\n { value: 'name', label: 'Name', scope: 'tags' },\n { value: 'id', label: 'Device ID', scope: 'identity' }\n ]\n );\n }\n);\n\nexport const getDeviceCountsByStatus = createSelector([getDevicesByStatus], byStatus =>\n Object.values(DEVICE_STATES).reduce<Record<DeviceAuthState, number>>(\n (accu, deviceState) => {\n const { counts } = byStatus[deviceState];\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { total, ...tieredCounts } = counts;\n const count = Object.values(tieredCounts).reduce((accu, countPerTier) => accu + countPerTier, 0);\n accu[deviceState] = count;\n accu.total = accu.total + count;\n return accu;\n },\n { total: 0 }\n )\n);\n\nexport const getDeviceById = createSelector([getDevicesById, (_, deviceId) => deviceId], (devicesById, deviceId = '') => devicesById[deviceId] ?? {});\n\nexport const getSelectedGroupInfo = createSelector(\n [getDeviceCountsByStatus, getGroupsById, getSelectedGroup],\n ({ accepted: acceptedDeviceTotal }, groupsById, selectedGroup) => {\n let groupCount = acceptedDeviceTotal;\n let groupFilters: DeviceFilter[] = [];\n if (selectedGroup && groupsById[selectedGroup]) {\n groupCount = groupsById[selectedGroup].total || 0;\n groupFilters = groupsById[selectedGroup].filters || [];\n }\n return { groupCount, selectedGroup, groupFilters };\n }\n);\n\nexport const getCombinedLimit = createSelector(\n [getDeviceLimits],\n deviceLimits => Object.values(deviceLimits).reduce((accu, limit) => accu + Math.max(limit ?? 0, 0), 0) // limit might be -1 for unlimited devices\n);\n\nexport const getLimitMaxed = createSelector(\n [getDeviceCountsByStatus, getCombinedLimit],\n ({ accepted: acceptedDevices }, combinedLimit) => !!combinedLimit && combinedLimit <= acceptedDevices\n);\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport const getGroupsByIdWithoutUngrouped = createSelector([getGroupsById], ({ [UNGROUPED_GROUP.id]: ungrouped, ...groups }) => groups);\n\nexport const getGroupData = createSelector([getGroupsByIdWithoutUngrouped], groups => {\n const createdGroup = Object.keys(groups).length ? Object.keys(groups)[0] : undefined;\n const hasDynamicGroups = Object.values(groups).some(group => !!group.id);\n return { createdGroup, hasDynamicGroups, groups };\n});\n\ntype SelectorGroup = DeviceGroup & { groupId: string };\ntype SelectorGroups = { dynamic: SelectorGroup[]; static: SelectorGroup[]; ungrouped: SelectorGroup[] };\n\nexport const getGroups = createSelector([getGroupsById], groupsById => {\n const groupNames = Object.keys(groupsById).sort();\n const groupedGroups = Object.entries(groupsById)\n .sort((a, b) => a[0].localeCompare(b[0]))\n .reduce<SelectorGroups>(\n (accu, [groupname, group]) => {\n const name = groupname === UNGROUPED_GROUP.id ? UNGROUPED_GROUP.name : groupname;\n const groupItem = { ...group, groupId: name, name: groupname };\n if ((group.filters ?? []).length > 0) {\n if (groupname !== UNGROUPED_GROUP.id) {\n accu.dynamic.push(groupItem);\n } else {\n accu.ungrouped.push(groupItem);\n }\n } else {\n accu.static.push(groupItem);\n }\n return accu;\n },\n { dynamic: [], static: [], ungrouped: [] }\n );\n return { groupNames, ...groupedGroups };\n});\nexport const getAttributesList = createSelector(\n [getFilteringAttributes, getFilteringAttributesFromConfig],\n ({ identityAttributes = [], inventoryAttributes = [] }, { identity = [], inventory = [] }) =>\n [...identityAttributes, ...inventoryAttributes, ...identity, ...inventory].filter(duplicateFilter)\n);\nconst getEnabledTierLimits = createSelector([getDeviceLimits], limits => Object.entries(limits).filter(([, limit]) => limit !== 0));\n\nexport const getEnabledTiers = createSelector([getEnabledTierLimits], enabledTierLimits => enabledTierLimits.map(([type]) => type));\n\nexport const getDeviceLimitStats = createSelector([getEnabledTierLimits, getAcceptedDevices], (enabledTierLimits, accepted) => {\n const { counts } = accepted;\n return enabledTierLimits.map(([type, limit]) => ({\n type,\n limit,\n total: counts[type] || 0\n }));\n});\n\nexport const getDeviceTypes = createSelector([getAcceptedDevices, getDevicesById], ({ deviceIds = [] }, devicesById) =>\n Object.keys(\n deviceIds.slice(0, 200).reduce((accu, item) => {\n const { device_type: deviceTypes = [] } = devicesById[item] ? devicesById[item].attributes : {};\n accu = deviceTypes.reduce((deviceTypeAccu, deviceType) => {\n if (deviceType.length > 1) {\n deviceTypeAccu[deviceType] = deviceTypeAccu[deviceType] ? deviceTypeAccu[deviceType] + 1 : 1;\n }\n return deviceTypeAccu;\n }, accu);\n return accu;\n }, {})\n )\n);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"selectors.cjs","names":["createSelector","DEVICE_STATES","UNGROUPED_GROUP","duplicateFilter"],"sources":["../../src/devicesSlice/selectors.ts"],"sourcesContent":["// Copyright 2023 Northern.tech AS\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\nimport { duplicateFilter } from '@northern.tech/utils/helpers';\nimport { createSelector } from '@reduxjs/toolkit';\n\nimport type { DeviceFilter, DeviceGroup } from '.';\nimport type { DeviceAuthState } from '../constants';\nimport { DEVICE_STATES, UNGROUPED_GROUP } from '../constants';\nimport type { RootState } from '../store';\n\nexport const getAcceptedDevices = (state: RootState) => state.devices.byStatus.accepted;\nexport const getDevicesByStatus = (state: RootState) => state.devices.byStatus;\nexport const getDevicesById = (state: RootState) => state.devices.byId;\nexport const getDeviceReports = (state: RootState) => state.devices.reports;\nexport const getGroupsById = (state: RootState) => state.devices.groups.byId;\nexport const getSelectedGroup = (state: RootState) => state.devices.groups.selectedGroup;\n\nexport const getDeviceListState = (state: RootState) => state.devices.deviceList;\nexport const getListedDevices = (state: RootState) => state.devices.deviceList.deviceIds;\nexport const getFilteringAttributes = (state: RootState) => state.devices.filteringAttributes;\nexport const getDeviceFilters = (state: RootState) => state.devices.filters || [];\nexport const getTestDeviceLimit = (state: RootState) => state.devices.testDeviceLimit;\nconst getFilteringAttributesFromConfig = (state: RootState) => state.devices.filteringAttributesConfig.attributes;\nexport const getSortedFilteringAttributes = createSelector([getFilteringAttributes], filteringAttributes => ({\n ...filteringAttributes,\n identityAttributes: [...filteringAttributes.identityAttributes, 'id']\n}));\nexport const getDeviceLimits = (state: RootState) => state.devices.limits;\nexport const getTestDeviceCount = (state: RootState) => state.devices.testDeviceCount;\nconst getFilteringAttributesLimit = (state: RootState) => state.devices.filteringAttributesLimit;\n\nexport const getDeviceIdentityAttributes = createSelector(\n [getFilteringAttributes, getFilteringAttributesLimit],\n ({ identityAttributes }, filteringAttributesLimit) => {\n // the device auth status is not a meaningful device identifier\n // limit the selection of the available attribute to AVAILABLE_ATTRIBUTE_LIMIT\n const attributes = identityAttributes.filter(attribute => attribute !== 'status').slice(0, filteringAttributesLimit);\n return attributes.reduce(\n (accu, value) => {\n accu.push({ value, label: value, scope: 'identity' });\n return accu;\n },\n [\n { value: 'name', label: 'Name', scope: 'tags' },\n { value: 'id', label: 'Device ID', scope: 'identity' }\n ]\n );\n }\n);\n\nexport const getDeviceCountsByStatus = createSelector([getDevicesByStatus], byStatus =>\n Object.values(DEVICE_STATES).reduce<Record<DeviceAuthState, number>>(\n (accu, deviceState) => {\n const { counts } = byStatus[deviceState];\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { total, ...tieredCounts } = counts;\n const count = Object.values(tieredCounts).reduce((accu, countPerTier) => accu + countPerTier, 0);\n accu[deviceState] = count;\n accu.total = accu.total + count;\n return accu;\n },\n { total: 0 }\n )\n);\n\nexport const getDeviceById = createSelector([getDevicesById, (_, deviceId) => deviceId], (devicesById, deviceId = '') => devicesById[deviceId] ?? {});\n\nexport const getSelectedGroupInfo = createSelector(\n [getDeviceCountsByStatus, getGroupsById, getSelectedGroup],\n ({ accepted: acceptedDeviceTotal }, groupsById, selectedGroup) => {\n let groupCount = acceptedDeviceTotal;\n let groupFilters: DeviceFilter[] = [];\n if (selectedGroup && groupsById[selectedGroup]) {\n groupCount = groupsById[selectedGroup].total || 0;\n groupFilters = groupsById[selectedGroup].filters || [];\n }\n return { groupCount, selectedGroup, groupFilters };\n }\n);\n\nexport const getCombinedLimit = createSelector(\n [getDeviceLimits],\n deviceLimits => Object.values(deviceLimits).reduce((accu, limit) => accu + Math.max(limit ?? 0, 0), 0) // limit might be -1 for unlimited devices\n);\n\nexport const getLimitMaxed = createSelector(\n [getDeviceCountsByStatus, getCombinedLimit],\n ({ accepted: acceptedDevices }, combinedLimit) => !!combinedLimit && combinedLimit <= acceptedDevices\n);\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport const getGroupsByIdWithoutUngrouped = createSelector([getGroupsById], ({ [UNGROUPED_GROUP.id]: ungrouped, ...groups }) => groups);\n\nexport const getGroupData = createSelector([getGroupsByIdWithoutUngrouped], groups => {\n const createdGroup = Object.keys(groups).length ? Object.keys(groups)[0] : undefined;\n const hasDynamicGroups = Object.values(groups).some(group => !!group.id);\n return { createdGroup, hasDynamicGroups, groups };\n});\n\ntype SelectorGroup = DeviceGroup & { groupId: string };\ntype SelectorGroups = { dynamic: SelectorGroup[]; static: SelectorGroup[]; ungrouped: SelectorGroup[] };\n\nexport const getGroups = createSelector([getGroupsById], groupsById => {\n const groupNames = Object.keys(groupsById).sort();\n const groupedGroups = Object.entries(groupsById)\n .sort((a, b) => a[0].localeCompare(b[0]))\n .reduce<SelectorGroups>(\n (accu, [groupname, group]) => {\n const name = groupname === UNGROUPED_GROUP.id ? UNGROUPED_GROUP.name : groupname;\n const groupItem = { ...group, groupId: name, name: groupname };\n if ((group.filters ?? []).length > 0) {\n if (groupname !== UNGROUPED_GROUP.id) {\n accu.dynamic.push(groupItem);\n } else {\n accu.ungrouped.push(groupItem);\n }\n } else {\n accu.static.push(groupItem);\n }\n return accu;\n },\n { dynamic: [], static: [], ungrouped: [] }\n );\n return { groupNames, ...groupedGroups };\n});\nexport const getAttributesList = createSelector(\n [getFilteringAttributes, getFilteringAttributesFromConfig],\n ({ identityAttributes = [], inventoryAttributes = [] }, { identity = [], inventory = [] }) =>\n [...identityAttributes, ...inventoryAttributes, ...identity, ...inventory].filter(duplicateFilter)\n);\nconst getEnabledTierLimits = createSelector([getDeviceLimits], limits => Object.entries(limits).filter(([, limit]) => limit !== 0));\n\nexport const getEnabledTiers = createSelector([getEnabledTierLimits], enabledTierLimits => enabledTierLimits.map(([type]) => type));\n\nexport const getDeviceLimitStats = createSelector([getEnabledTierLimits, getAcceptedDevices], (enabledTierLimits, accepted) => {\n const { counts } = accepted;\n return enabledTierLimits.map(([type, limit]) => ({\n type,\n limit,\n total: counts[type] || 0\n }));\n});\n\nexport const getDeviceTypes = createSelector([getAcceptedDevices, getDevicesById], ({ deviceIds = [] }, devicesById) =>\n Object.keys(\n deviceIds.slice(0, 200).reduce((accu, item) => {\n const { device_type: deviceTypes = [] } = devicesById[item] ? devicesById[item].attributes : {};\n accu = deviceTypes.reduce((deviceTypeAccu, deviceType) => {\n if (deviceType.length > 1) {\n deviceTypeAccu[deviceType] = deviceTypeAccu[deviceType] ? deviceTypeAccu[deviceType] + 1 : 1;\n }\n return deviceTypeAccu;\n }, accu);\n return accu;\n }, {})\n )\n);\n"],"mappings":"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"}
|
|
@@ -22,7 +22,7 @@ const getDeviceLimits = (state) => state.devices.limits;
|
|
|
22
22
|
const getTestDeviceCount = (state) => state.devices.testDeviceCount;
|
|
23
23
|
const getFilteringAttributesLimit = (state) => state.devices.filteringAttributesLimit;
|
|
24
24
|
const getDeviceIdentityAttributes = createSelector([getFilteringAttributes, getFilteringAttributesLimit], ({ identityAttributes }, filteringAttributesLimit) => {
|
|
25
|
-
return identityAttributes.slice(0, filteringAttributesLimit).reduce((accu, value) => {
|
|
25
|
+
return identityAttributes.filter((attribute) => attribute !== "status").slice(0, filteringAttributesLimit).reduce((accu, value) => {
|
|
26
26
|
accu.push({
|
|
27
27
|
value,
|
|
28
28
|
label: value,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selectors.js","names":[],"sources":["../../src/devicesSlice/selectors.ts"],"sourcesContent":["// Copyright 2023 Northern.tech AS\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\nimport { duplicateFilter } from '@northern.tech/utils/helpers';\nimport { createSelector } from '@reduxjs/toolkit';\n\nimport type { DeviceFilter, DeviceGroup } from '.';\nimport type { DeviceAuthState } from '../constants';\nimport { DEVICE_STATES, UNGROUPED_GROUP } from '../constants';\nimport type { RootState } from '../store';\n\nexport const getAcceptedDevices = (state: RootState) => state.devices.byStatus.accepted;\nexport const getDevicesByStatus = (state: RootState) => state.devices.byStatus;\nexport const getDevicesById = (state: RootState) => state.devices.byId;\nexport const getDeviceReports = (state: RootState) => state.devices.reports;\nexport const getGroupsById = (state: RootState) => state.devices.groups.byId;\nexport const getSelectedGroup = (state: RootState) => state.devices.groups.selectedGroup;\n\nexport const getDeviceListState = (state: RootState) => state.devices.deviceList;\nexport const getListedDevices = (state: RootState) => state.devices.deviceList.deviceIds;\nexport const getFilteringAttributes = (state: RootState) => state.devices.filteringAttributes;\nexport const getDeviceFilters = (state: RootState) => state.devices.filters || [];\nexport const getTestDeviceLimit = (state: RootState) => state.devices.testDeviceLimit;\nconst getFilteringAttributesFromConfig = (state: RootState) => state.devices.filteringAttributesConfig.attributes;\nexport const getSortedFilteringAttributes = createSelector([getFilteringAttributes], filteringAttributes => ({\n ...filteringAttributes,\n identityAttributes: [...filteringAttributes.identityAttributes, 'id']\n}));\nexport const getDeviceLimits = (state: RootState) => state.devices.limits;\nexport const getTestDeviceCount = (state: RootState) => state.devices.testDeviceCount;\nconst getFilteringAttributesLimit = (state: RootState) => state.devices.filteringAttributesLimit;\n\nexport const getDeviceIdentityAttributes = createSelector(\n [getFilteringAttributes, getFilteringAttributesLimit],\n ({ identityAttributes }, filteringAttributesLimit) => {\n // limit the selection of the available attribute to AVAILABLE_ATTRIBUTE_LIMIT\n const attributes = identityAttributes.slice(0, filteringAttributesLimit);\n return attributes.reduce(\n (accu, value) => {\n accu.push({ value, label: value, scope: 'identity' });\n return accu;\n },\n [\n { value: 'name', label: 'Name', scope: 'tags' },\n { value: 'id', label: 'Device ID', scope: 'identity' }\n ]\n );\n }\n);\n\nexport const getDeviceCountsByStatus = createSelector([getDevicesByStatus], byStatus =>\n Object.values(DEVICE_STATES).reduce<Record<DeviceAuthState, number>>(\n (accu, deviceState) => {\n const { counts } = byStatus[deviceState];\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { total, ...tieredCounts } = counts;\n const count = Object.values(tieredCounts).reduce((accu, countPerTier) => accu + countPerTier, 0);\n accu[deviceState] = count;\n accu.total = accu.total + count;\n return accu;\n },\n { total: 0 }\n )\n);\n\nexport const getDeviceById = createSelector([getDevicesById, (_, deviceId) => deviceId], (devicesById, deviceId = '') => devicesById[deviceId] ?? {});\n\nexport const getSelectedGroupInfo = createSelector(\n [getDeviceCountsByStatus, getGroupsById, getSelectedGroup],\n ({ accepted: acceptedDeviceTotal }, groupsById, selectedGroup) => {\n let groupCount = acceptedDeviceTotal;\n let groupFilters: DeviceFilter[] = [];\n if (selectedGroup && groupsById[selectedGroup]) {\n groupCount = groupsById[selectedGroup].total || 0;\n groupFilters = groupsById[selectedGroup].filters || [];\n }\n return { groupCount, selectedGroup, groupFilters };\n }\n);\n\nexport const getCombinedLimit = createSelector(\n [getDeviceLimits],\n deviceLimits => Object.values(deviceLimits).reduce((accu, limit) => accu + Math.max(limit ?? 0, 0), 0) // limit might be -1 for unlimited devices\n);\n\nexport const getLimitMaxed = createSelector(\n [getDeviceCountsByStatus, getCombinedLimit],\n ({ accepted: acceptedDevices }, combinedLimit) => !!combinedLimit && combinedLimit <= acceptedDevices\n);\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport const getGroupsByIdWithoutUngrouped = createSelector([getGroupsById], ({ [UNGROUPED_GROUP.id]: ungrouped, ...groups }) => groups);\n\nexport const getGroupData = createSelector([getGroupsByIdWithoutUngrouped], groups => {\n const createdGroup = Object.keys(groups).length ? Object.keys(groups)[0] : undefined;\n const hasDynamicGroups = Object.values(groups).some(group => !!group.id);\n return { createdGroup, hasDynamicGroups, groups };\n});\n\ntype SelectorGroup = DeviceGroup & { groupId: string };\ntype SelectorGroups = { dynamic: SelectorGroup[]; static: SelectorGroup[]; ungrouped: SelectorGroup[] };\n\nexport const getGroups = createSelector([getGroupsById], groupsById => {\n const groupNames = Object.keys(groupsById).sort();\n const groupedGroups = Object.entries(groupsById)\n .sort((a, b) => a[0].localeCompare(b[0]))\n .reduce<SelectorGroups>(\n (accu, [groupname, group]) => {\n const name = groupname === UNGROUPED_GROUP.id ? UNGROUPED_GROUP.name : groupname;\n const groupItem = { ...group, groupId: name, name: groupname };\n if ((group.filters ?? []).length > 0) {\n if (groupname !== UNGROUPED_GROUP.id) {\n accu.dynamic.push(groupItem);\n } else {\n accu.ungrouped.push(groupItem);\n }\n } else {\n accu.static.push(groupItem);\n }\n return accu;\n },\n { dynamic: [], static: [], ungrouped: [] }\n );\n return { groupNames, ...groupedGroups };\n});\nexport const getAttributesList = createSelector(\n [getFilteringAttributes, getFilteringAttributesFromConfig],\n ({ identityAttributes = [], inventoryAttributes = [] }, { identity = [], inventory = [] }) =>\n [...identityAttributes, ...inventoryAttributes, ...identity, ...inventory].filter(duplicateFilter)\n);\nconst getEnabledTierLimits = createSelector([getDeviceLimits], limits => Object.entries(limits).filter(([, limit]) => limit !== 0));\n\nexport const getEnabledTiers = createSelector([getEnabledTierLimits], enabledTierLimits => enabledTierLimits.map(([type]) => type));\n\nexport const getDeviceLimitStats = createSelector([getEnabledTierLimits, getAcceptedDevices], (enabledTierLimits, accepted) => {\n const { counts } = accepted;\n return enabledTierLimits.map(([type, limit]) => ({\n type,\n limit,\n total: counts[type] || 0\n }));\n});\n\nexport const getDeviceTypes = createSelector([getAcceptedDevices, getDevicesById], ({ deviceIds = [] }, devicesById) =>\n Object.keys(\n deviceIds.slice(0, 200).reduce((accu, item) => {\n const { device_type: deviceTypes = [] } = devicesById[item] ? devicesById[item].attributes : {};\n accu = deviceTypes.reduce((deviceTypeAccu, deviceType) => {\n if (deviceType.length > 1) {\n deviceTypeAccu[deviceType] = deviceTypeAccu[deviceType] ? deviceTypeAccu[deviceType] + 1 : 1;\n }\n return deviceTypeAccu;\n }, accu);\n return accu;\n }, {})\n )\n);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"selectors.js","names":[],"sources":["../../src/devicesSlice/selectors.ts"],"sourcesContent":["// Copyright 2023 Northern.tech AS\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\nimport { duplicateFilter } from '@northern.tech/utils/helpers';\nimport { createSelector } from '@reduxjs/toolkit';\n\nimport type { DeviceFilter, DeviceGroup } from '.';\nimport type { DeviceAuthState } from '../constants';\nimport { DEVICE_STATES, UNGROUPED_GROUP } from '../constants';\nimport type { RootState } from '../store';\n\nexport const getAcceptedDevices = (state: RootState) => state.devices.byStatus.accepted;\nexport const getDevicesByStatus = (state: RootState) => state.devices.byStatus;\nexport const getDevicesById = (state: RootState) => state.devices.byId;\nexport const getDeviceReports = (state: RootState) => state.devices.reports;\nexport const getGroupsById = (state: RootState) => state.devices.groups.byId;\nexport const getSelectedGroup = (state: RootState) => state.devices.groups.selectedGroup;\n\nexport const getDeviceListState = (state: RootState) => state.devices.deviceList;\nexport const getListedDevices = (state: RootState) => state.devices.deviceList.deviceIds;\nexport const getFilteringAttributes = (state: RootState) => state.devices.filteringAttributes;\nexport const getDeviceFilters = (state: RootState) => state.devices.filters || [];\nexport const getTestDeviceLimit = (state: RootState) => state.devices.testDeviceLimit;\nconst getFilteringAttributesFromConfig = (state: RootState) => state.devices.filteringAttributesConfig.attributes;\nexport const getSortedFilteringAttributes = createSelector([getFilteringAttributes], filteringAttributes => ({\n ...filteringAttributes,\n identityAttributes: [...filteringAttributes.identityAttributes, 'id']\n}));\nexport const getDeviceLimits = (state: RootState) => state.devices.limits;\nexport const getTestDeviceCount = (state: RootState) => state.devices.testDeviceCount;\nconst getFilteringAttributesLimit = (state: RootState) => state.devices.filteringAttributesLimit;\n\nexport const getDeviceIdentityAttributes = createSelector(\n [getFilteringAttributes, getFilteringAttributesLimit],\n ({ identityAttributes }, filteringAttributesLimit) => {\n // the device auth status is not a meaningful device identifier\n // limit the selection of the available attribute to AVAILABLE_ATTRIBUTE_LIMIT\n const attributes = identityAttributes.filter(attribute => attribute !== 'status').slice(0, filteringAttributesLimit);\n return attributes.reduce(\n (accu, value) => {\n accu.push({ value, label: value, scope: 'identity' });\n return accu;\n },\n [\n { value: 'name', label: 'Name', scope: 'tags' },\n { value: 'id', label: 'Device ID', scope: 'identity' }\n ]\n );\n }\n);\n\nexport const getDeviceCountsByStatus = createSelector([getDevicesByStatus], byStatus =>\n Object.values(DEVICE_STATES).reduce<Record<DeviceAuthState, number>>(\n (accu, deviceState) => {\n const { counts } = byStatus[deviceState];\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { total, ...tieredCounts } = counts;\n const count = Object.values(tieredCounts).reduce((accu, countPerTier) => accu + countPerTier, 0);\n accu[deviceState] = count;\n accu.total = accu.total + count;\n return accu;\n },\n { total: 0 }\n )\n);\n\nexport const getDeviceById = createSelector([getDevicesById, (_, deviceId) => deviceId], (devicesById, deviceId = '') => devicesById[deviceId] ?? {});\n\nexport const getSelectedGroupInfo = createSelector(\n [getDeviceCountsByStatus, getGroupsById, getSelectedGroup],\n ({ accepted: acceptedDeviceTotal }, groupsById, selectedGroup) => {\n let groupCount = acceptedDeviceTotal;\n let groupFilters: DeviceFilter[] = [];\n if (selectedGroup && groupsById[selectedGroup]) {\n groupCount = groupsById[selectedGroup].total || 0;\n groupFilters = groupsById[selectedGroup].filters || [];\n }\n return { groupCount, selectedGroup, groupFilters };\n }\n);\n\nexport const getCombinedLimit = createSelector(\n [getDeviceLimits],\n deviceLimits => Object.values(deviceLimits).reduce((accu, limit) => accu + Math.max(limit ?? 0, 0), 0) // limit might be -1 for unlimited devices\n);\n\nexport const getLimitMaxed = createSelector(\n [getDeviceCountsByStatus, getCombinedLimit],\n ({ accepted: acceptedDevices }, combinedLimit) => !!combinedLimit && combinedLimit <= acceptedDevices\n);\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport const getGroupsByIdWithoutUngrouped = createSelector([getGroupsById], ({ [UNGROUPED_GROUP.id]: ungrouped, ...groups }) => groups);\n\nexport const getGroupData = createSelector([getGroupsByIdWithoutUngrouped], groups => {\n const createdGroup = Object.keys(groups).length ? Object.keys(groups)[0] : undefined;\n const hasDynamicGroups = Object.values(groups).some(group => !!group.id);\n return { createdGroup, hasDynamicGroups, groups };\n});\n\ntype SelectorGroup = DeviceGroup & { groupId: string };\ntype SelectorGroups = { dynamic: SelectorGroup[]; static: SelectorGroup[]; ungrouped: SelectorGroup[] };\n\nexport const getGroups = createSelector([getGroupsById], groupsById => {\n const groupNames = Object.keys(groupsById).sort();\n const groupedGroups = Object.entries(groupsById)\n .sort((a, b) => a[0].localeCompare(b[0]))\n .reduce<SelectorGroups>(\n (accu, [groupname, group]) => {\n const name = groupname === UNGROUPED_GROUP.id ? UNGROUPED_GROUP.name : groupname;\n const groupItem = { ...group, groupId: name, name: groupname };\n if ((group.filters ?? []).length > 0) {\n if (groupname !== UNGROUPED_GROUP.id) {\n accu.dynamic.push(groupItem);\n } else {\n accu.ungrouped.push(groupItem);\n }\n } else {\n accu.static.push(groupItem);\n }\n return accu;\n },\n { dynamic: [], static: [], ungrouped: [] }\n );\n return { groupNames, ...groupedGroups };\n});\nexport const getAttributesList = createSelector(\n [getFilteringAttributes, getFilteringAttributesFromConfig],\n ({ identityAttributes = [], inventoryAttributes = [] }, { identity = [], inventory = [] }) =>\n [...identityAttributes, ...inventoryAttributes, ...identity, ...inventory].filter(duplicateFilter)\n);\nconst getEnabledTierLimits = createSelector([getDeviceLimits], limits => Object.entries(limits).filter(([, limit]) => limit !== 0));\n\nexport const getEnabledTiers = createSelector([getEnabledTierLimits], enabledTierLimits => enabledTierLimits.map(([type]) => type));\n\nexport const getDeviceLimitStats = createSelector([getEnabledTierLimits, getAcceptedDevices], (enabledTierLimits, accepted) => {\n const { counts } = accepted;\n return enabledTierLimits.map(([type, limit]) => ({\n type,\n limit,\n total: counts[type] || 0\n }));\n});\n\nexport const getDeviceTypes = createSelector([getAcceptedDevices, getDevicesById], ({ deviceIds = [] }, devicesById) =>\n Object.keys(\n deviceIds.slice(0, 200).reduce((accu, item) => {\n const { device_type: deviceTypes = [] } = devicesById[item] ? devicesById[item].attributes : {};\n accu = deviceTypes.reduce((deviceTypeAccu, deviceType) => {\n if (deviceType.length > 1) {\n deviceTypeAccu[deviceType] = deviceTypeAccu[deviceType] ? deviceTypeAccu[deviceType] + 1 : 1;\n }\n return deviceTypeAccu;\n }, accu);\n return accu;\n }, {})\n )\n);\n"],"mappings":"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"}
|
|
@@ -397,9 +397,9 @@ export declare const getManifest: import("@reduxjs/toolkit").AsyncThunk<{
|
|
|
397
397
|
modified?: string;
|
|
398
398
|
artifact: import("@northern.tech/types/types.gen").ArtifactV2 & Omit<import("@northern.tech/types/types.gen").ArtifactV2, "updates"> & {
|
|
399
399
|
updates?: Array<{
|
|
400
|
+
metadata?: import("@northern.tech/types/types.gen").MetadataAny | undefined;
|
|
400
401
|
type_info?: import("@northern.tech/types/types.gen").ArtifactTypeInfo | undefined;
|
|
401
402
|
files?: Array<import("@northern.tech/types/types.gen").UpdateFile> | undefined;
|
|
402
|
-
metadata?: import("@northern.tech/types/types.gen").MetadataAny | undefined;
|
|
403
403
|
}>;
|
|
404
404
|
url?: string;
|
|
405
405
|
};
|
|
@@ -397,9 +397,9 @@ export declare const getManifest: import("@reduxjs/toolkit").AsyncThunk<{
|
|
|
397
397
|
modified?: string;
|
|
398
398
|
artifact: import("@northern.tech/types/types.gen").ArtifactV2 & Omit<import("@northern.tech/types/types.gen").ArtifactV2, "updates"> & {
|
|
399
399
|
updates?: Array<{
|
|
400
|
+
metadata?: import("@northern.tech/types/types.gen").MetadataAny | undefined;
|
|
400
401
|
type_info?: import("@northern.tech/types/types.gen").ArtifactTypeInfo | undefined;
|
|
401
402
|
files?: Array<import("@northern.tech/types/types.gen").UpdateFile> | undefined;
|
|
402
|
-
metadata?: import("@northern.tech/types/types.gen").MetadataAny | undefined;
|
|
403
403
|
}>;
|
|
404
404
|
url?: string;
|
|
405
405
|
};
|
package/dist/utils.cjs
CHANGED
|
@@ -54,11 +54,8 @@ const convertDeviceListStateToFilters = ({ filters = [], group, groups = { byId:
|
|
|
54
54
|
operator: _northern_tech_utils_constants.DEVICE_FILTERING_OPTIONS.$eq.key,
|
|
55
55
|
scope: "system"
|
|
56
56
|
});
|
|
57
|
-
const nonMonitorFilters = applicableFilters.filter((filter) => !Object.values(_northern_tech_utils_constants.DEVICE_ISSUE_OPTIONS).some(({ filterRule }) => {
|
|
58
|
-
const { key = "", scope = "" } = filterRule;
|
|
59
|
-
return filter.scope !== "inventory" && scope === filter.scope && key === filter.key;
|
|
60
|
-
}));
|
|
61
57
|
const deviceIssueFilters = convertIssueOptionsToFilters(selectedIssues, { offlineThreshold });
|
|
58
|
+
const nonMonitorFilters = applicableFilters.filter((filter) => !deviceIssueFilters.some((issueFilter) => filterCompare(issueFilter, filter)));
|
|
62
59
|
applicableFilters = [...nonMonitorFilters, ...deviceIssueFilters];
|
|
63
60
|
const effectiveFilters = status ? [...applicableFilters, {
|
|
64
61
|
key: "status",
|
package/dist/utils.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.cjs","names":["DEVICE_FILTERING_OPTIONS","yes","DEVICE_ISSUE_OPTIONS","ATTRIBUTE_SCOPES","emptyFilter","ORCHESTRATOR_MANIFEST_ATTRIBUTE_PREFIX","ATTRIBUTE_SCOPE_LABELS","emptyUiPermissions","duplicateFilter","softwareIndicator","deploymentStatesToSubstates","defaultStats","deploymentStatesToSubstatesWithSkipped","DEPLOYMENT_STATES","deploymentDisplayStates","DARK_MODE","TIMEOUTS"],"sources":["../src/utils.ts"],"sourcesContent":["// Copyright 2024 Northern.tech AS\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\nimport type { AttributeFilterPredicate, AttributeResponse, DeviceWithImage, FilterV2, InvoiceLineItem, Scope } from '@northern.tech/types/MenderTypes';\nimport { duplicateFilter, yes } from '@northern.tech/utils/helpers';\nimport type { AxiosError } from 'axios';\n\nimport type { DeviceIssueOptionKey, FilterOperator, Role } from './constants';\nimport {\n ATTRIBUTE_SCOPES,\n ATTRIBUTE_SCOPE_LABELS,\n DARK_MODE,\n DEPLOYMENT_STATES,\n DEVICE_FILTERING_OPTIONS,\n DEVICE_ISSUE_OPTIONS,\n DEVICE_LIST_MAXIMUM_LENGTH,\n ORCHESTRATOR_MANIFEST_ATTRIBUTE_PREFIX,\n TIMEOUTS,\n defaultStats,\n deploymentDisplayStates,\n deploymentStatesToSubstates,\n deploymentStatesToSubstatesWithSkipped,\n emptyFilter,\n emptyUiPermissions,\n softwareIndicator\n} from './constants';\nimport type { Deployment } from './deploymentsSlice';\nimport type { DeviceFilter, DeviceGroup, InventoryAttributes } from './devicesSlice';\nimport type { PricePreview } from './organizationSlice/types';\nimport type { AppDispatch } from './store';\n\ntype FilterProcessorValue = string | string[] | number | boolean; // this aligns with a API compatible `FilterPredicate.value`\ntype FilterProcessor = (val: string) => FilterProcessorValue;\n\n// for some reason these functions can not be stored in the deviceConstants...\nconst filterProcessors: Record<string, FilterProcessor> = {\n [DEVICE_FILTERING_OPTIONS.$gt.key]: (val: string) => Number(val) || val,\n [DEVICE_FILTERING_OPTIONS.$gte.key]: (val: string) => Number(val) || val,\n [DEVICE_FILTERING_OPTIONS.$lt.key]: (val: string) => Number(val) || val,\n [DEVICE_FILTERING_OPTIONS.$lte.key]: (val: string) => Number(val) || val,\n [DEVICE_FILTERING_OPTIONS.$ltne.key]: (val: string) => Number(val) || val,\n [DEVICE_FILTERING_OPTIONS.$in.key]: (val: string) => ('' + val).split(',').map(i => i.trim()),\n [DEVICE_FILTERING_OPTIONS.$nin.key]: (val: string) => ('' + val).split(',').map(i => i.trim()),\n [DEVICE_FILTERING_OPTIONS.$exists.key]: yes,\n [DEVICE_FILTERING_OPTIONS.$nexists.key]: () => false\n};\n\ntype FilterAlias = { alias: FilterOperator; value: boolean };\nconst filterAliases: Record<string, FilterAlias> = {\n $nexists: { alias: DEVICE_FILTERING_OPTIONS.$exists.key, value: false }\n};\n\nexport type FilterTerm = {\n attribute: string;\n scope: Scope;\n type: FilterOperator;\n value: FilterProcessorValue;\n};\n\nexport const mapFiltersToTerms = (filters: DeviceFilter[]): FilterTerm[] =>\n filters.map(filter => ({\n scope: filter.scope,\n attribute: filter.key,\n type: filterAliases[filter.operator]?.alias || filter.operator,\n value: Object.hasOwn(filterProcessors, filter.operator) ? filterProcessors[filter.operator](filter.value as string) : filter.value\n }));\nexport const mapTermsToFilters = (terms: FilterTerm[]): DeviceFilter[] =>\n terms.map(term => {\n const aliasedFilter = Object.entries(filterAliases).find(\n aliasDefinition => aliasDefinition[1].alias === term.type && aliasDefinition[1].value === term.value\n );\n const operator = (aliasedFilter ? aliasedFilter[0] : term.type) as FilterOperator;\n return { scope: term.scope as Scope, key: term.attribute, operator, value: term.value } as DeviceFilter;\n });\n\ntype IssueFilterState = { offlineThreshold?: string };\n\ntype IssueFilterRule = {\n key: string;\n operator: FilterOperator;\n scope: Scope;\n value: string | string[] | ((state: IssueFilterState) => string);\n};\n\nconst convertIssueOptionsToFilters = (issuesSelection: DeviceIssueOptionKey[], filtersState: IssueFilterState = {}): DeviceFilter[] =>\n issuesSelection.map(item => {\n const filterRule = DEVICE_ISSUE_OPTIONS[item].filterRule as IssueFilterRule;\n const value = typeof filterRule.value === 'function' ? filterRule.value(filtersState) : filterRule.value;\n return { key: filterRule.key, operator: filterRule.operator, scope: filterRule.scope, value } as DeviceFilter;\n });\n\nexport const convertDeviceListStateToFilters = ({\n filters = [],\n group,\n groups = { byId: {} },\n offlineThreshold,\n selectedIssues = [],\n status\n}: {\n filters?: DeviceFilter[];\n group?: string;\n groups?: { byId: Record<string, DeviceGroup> };\n offlineThreshold?: string;\n selectedIssues?: DeviceIssueOptionKey[];\n status?: string;\n}) => {\n let applicableFilters = [...filters];\n if (typeof group === 'string' && !(groups.byId[group]?.filters || applicableFilters).length) {\n applicableFilters.push({ key: 'group', value: group, operator: DEVICE_FILTERING_OPTIONS.$eq.key, scope: 'system' });\n }\n const nonMonitorFilters = applicableFilters.filter(\n filter =>\n !Object.values(DEVICE_ISSUE_OPTIONS).some(({ filterRule }) => {\n const { key = '', scope = '' } = filterRule as IssueFilterRule;\n return filter.scope !== 'inventory' && scope === filter.scope && key === filter.key;\n })\n );\n const deviceIssueFilters = convertIssueOptionsToFilters(selectedIssues, { offlineThreshold });\n applicableFilters = [...nonMonitorFilters, ...deviceIssueFilters];\n const effectiveFilters = status\n ? [...applicableFilters, { key: 'status', value: status, operator: DEVICE_FILTERING_OPTIONS.$eq.key, scope: ATTRIBUTE_SCOPES.identity }]\n : applicableFilters;\n return { applicableFilters: nonMonitorFilters, filterTerms: mapFiltersToTerms(effectiveFilters) };\n};\n\nconst filterCompare = (filter: DeviceFilter, item: DeviceFilter): boolean =>\n Object.keys(emptyFilter).every(key => item[key as keyof DeviceFilter]?.toString() === filter[key as keyof DeviceFilter]?.toString());\n\nexport const filtersFilter = (item: DeviceFilter, index: number, array: DeviceFilter[]): boolean => {\n const firstIndex = array.findIndex(filter => filterCompare(filter, item));\n return firstIndex === index;\n};\n\nexport const stripOrchestratorManifestPrefix = (key: string) =>\n key.startsWith(ORCHESTRATOR_MANIFEST_ATTRIBUTE_PREFIX) ? key.substring(ORCHESTRATOR_MANIFEST_ATTRIBUTE_PREFIX.length) : key;\n\nexport const getAttributeScopeLabel = ({ key = '', scope }: { key?: string; scope?: string }) => {\n if (scope === ATTRIBUTE_SCOPES.system) {\n return ATTRIBUTE_SCOPE_LABELS.default;\n }\n if (scope === ATTRIBUTE_SCOPES.inventory && key.startsWith(ORCHESTRATOR_MANIFEST_ATTRIBUTE_PREFIX)) {\n return ATTRIBUTE_SCOPE_LABELS.system;\n }\n return scope ?? '';\n};\n\nexport const stripUndefined = <T extends Record<string, unknown>>(obj: T): Partial<T> =>\n Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined)) as Partial<T>;\n\nexport const listItemMapper = <T extends object>(\n byId: Record<string, T>,\n ids: string[],\n { cutOffSize = DEVICE_LIST_MAXIMUM_LENGTH, defaultObject = {} as Partial<T> }: { cutOffSize?: number; defaultObject?: Partial<T> }\n): T[] =>\n ids.slice(0, cutOffSize).reduce<T[]>((accu, id) => {\n if (id && byId[id]) {\n accu.push({ ...defaultObject, ...byId[id] });\n }\n return accu;\n }, []);\n\ntype UiPermissions = typeof emptyUiPermissions;\ntype PermissionValue = string[] | Record<string, string[]>; // this would ideally be `PermissionValue = string[] | Record<string, PermissionValue>`\n\nexport const mergePermissions = (existingPermissions: UiPermissions = { ...emptyUiPermissions }, addedPermissions: UiPermissions): UiPermissions =>\n Object.entries(existingPermissions).reduce<UiPermissions>(\n (accu, [key, value]) => {\n let values;\n if (!accu[key]) {\n accu[key] = value;\n return accu;\n }\n if (Array.isArray(value)) {\n values = [...value, ...(accu[key] as string[])].filter(duplicateFilter);\n } else {\n values = mergePermissions(accu[key], { ...value } as unknown as UiPermissions) as unknown as PermissionValue;\n }\n accu[key] = values;\n return accu;\n },\n { ...addedPermissions }\n );\n\nexport const mapUserRolesToUiPermissions = (userRoles: string[], roles: Record<string, Role>): UiPermissions =>\n userRoles.reduce(\n (accu, roleId) => {\n if (!(roleId && roles[roleId])) {\n return accu;\n }\n return mergePermissions(accu, roles[roleId].uiPermissions);\n },\n { ...emptyUiPermissions }\n );\n\nexport const progress = ({ loaded, total }: { loaded: number; total?: number }): number => {\n if (!total) return 0;\n const uploadProgress = (loaded / total) * 100;\n return uploadProgress < 50 ? Math.ceil(uploadProgress) : Math.round(uploadProgress);\n};\n\nexport type ErrorWithResponse = AxiosError<{ error?: { message?: string } | string }> & { error?: string };\n\nexport const extractErrorMessage = (err: ErrorWithResponse, fallback = ''): string =>\n (typeof err.response?.data?.error === 'object' ? err.response?.data?.error?.message : err.response?.data?.error) || err.error || err.message || fallback;\n\nexport const ensureVersionString = (software: string, fallback: string): string =>\n software.length && software !== 'artifact_name' ? (software.endsWith(softwareIndicator) ? software : `${software}${softwareIndicator}`) : fallback;\n\nexport const stringToBoolean = (content: string | number | undefined): boolean => {\n if (!content) {\n return false;\n }\n const string = content + '';\n switch (string.trim().toLowerCase()) {\n case 'true':\n case 'yes':\n case '1':\n return true;\n case 'false':\n case 'no':\n case '0':\n case null:\n return false;\n default:\n return Boolean(string);\n }\n};\n\nexport type DeploymentStats = {\n failures: number;\n inprogress: number;\n paused: number;\n pending: number;\n skipped?: number;\n successes: number;\n};\n\nexport const groupDeploymentDevicesStats = (deployment: Pick<Deployment, 'devices'>): DeploymentStats => {\n const deviceStatCollector = (deploymentStates: string[], devices: Record<string, DeviceWithImage>): number =>\n Object.values(devices).reduce<number>((accu, device) => (deploymentStates.includes(device.status ?? '') ? accu + 1 : accu), 0);\n\n const inprogress = deviceStatCollector(deploymentStatesToSubstates.inprogress, deployment.devices);\n const pending = deviceStatCollector(deploymentStatesToSubstates.pending, deployment.devices);\n const successes = deviceStatCollector(deploymentStatesToSubstates.successes, deployment.devices);\n const failures = deviceStatCollector(deploymentStatesToSubstates.failures, deployment.devices);\n const paused = deviceStatCollector(deploymentStatesToSubstates.paused, deployment.devices);\n return { inprogress, paused, pending, successes, failures };\n};\n\nexport const statCollector = (items: string[], statistics: Record<string, number>): number =>\n items.reduce((accu, property) => accu + Number(statistics[property] || 0), 0);\n\nexport const groupDeploymentStats = (deployment: Partial<Deployment>, withSkipped?: boolean): DeploymentStats => {\n const { statistics = {} } = deployment;\n const { status = {} } = statistics;\n const stats = { ...defaultStats, ...status };\n const groupStates = withSkipped ? deploymentStatesToSubstatesWithSkipped : deploymentStatesToSubstates;\n const result: DeploymentStats = {\n // don't include 'pending' as inprogress, as all remaining devices will be pending - we don't discriminate based on phase membership\n inprogress: statCollector(groupStates.inprogress, stats),\n pending: statCollector(groupStates.pending, stats),\n successes: statCollector(groupStates.successes, stats),\n failures: statCollector(groupStates.failures, stats),\n paused: statCollector(groupStates.paused, stats)\n };\n if (withSkipped) {\n result.skipped = statCollector(groupStates.skipped!, stats);\n }\n return result;\n};\n\nexport const getDeploymentState = (deployment: Partial<Deployment>): string => {\n const { status: deploymentStatus = DEPLOYMENT_STATES.pending } = deployment;\n const { inprogress: currentProgressCount, paused } = groupDeploymentStats(deployment);\n\n let status = deploymentDisplayStates[deploymentStatus];\n if (deploymentStatus === DEPLOYMENT_STATES.pending && currentProgressCount === 0) {\n status = 'queued';\n } else if (paused > 0) {\n status = deploymentDisplayStates.paused;\n }\n return status;\n};\n\ntype DeploymentFilter =\n | FilterV2\n | {\n terms?: Array<AttributeFilterPredicate | { key: string }>;\n };\n\nexport const generateDeploymentGroupDetails = (filter: DeploymentFilter | undefined, groupName: string): string =>\n filter && filter.terms?.length\n ? `${groupName} (${filter.terms\n .map(\n filter =>\n `${filter.attribute || filter.key} ${DEVICE_FILTERING_OPTIONS[filter.type || filter.operator || DEVICE_FILTERING_OPTIONS.$eq.key].shortform} ${filter.value}`\n )\n .join(', ')})`\n : groupName;\n\ntype DeviceAttributeMap = {\n identity: Record<string, string>;\n inventory: InventoryAttributes;\n monitor: Record<string, string>;\n system: Record<string, string>;\n tags: Record<string, string>;\n};\n\nexport const mapDeviceAttributes = (attributes: AttributeResponse[] = []): DeviceAttributeMap =>\n attributes.reduce<DeviceAttributeMap>(\n (accu, attribute) => {\n if (!(attribute.value && attribute.name) && attribute.scope === ATTRIBUTE_SCOPES.inventory) {\n return accu;\n }\n const scope = (attribute.scope || ATTRIBUTE_SCOPES.inventory) as keyof DeviceAttributeMap;\n (accu[scope] as Record<string, unknown>) = {\n ...accu[scope],\n [attribute.name]: attribute.value\n };\n if (attribute.name === 'device_type' && attribute.scope === ATTRIBUTE_SCOPES.inventory) {\n accu.inventory.device_type = ([] as string[]).concat(attribute.value as string | string[]);\n }\n return accu;\n },\n { inventory: { device_type: [] as string[], artifact_name: '' }, identity: {}, monitor: {}, system: {}, tags: {} }\n );\n\nexport const isDarkMode = (mode: string): boolean => mode === DARK_MODE;\n\ntype Line = InvoiceLineItem & { product: 'mender_standard' | 'mender_micro' };\nexport const parseSubscriptionPreview = (lines: Line[]): PricePreview['items'] =>\n lines.reduce((acc, { addon, amount, product }) => {\n const tier = product.replace('mender_', '');\n if (!acc[tier]) {\n acc[tier] = {\n amount: 0,\n addons: {}\n };\n }\n if (!addon) {\n acc[tier].amount += amount;\n } else {\n acc[tier].addons[addon] = (acc[tier].addons[addon] ?? 0) + amount;\n }\n return acc;\n }, {});\n\nexport const convertToBackendSPLimits = (\n limits: Record<string, number | string>,\n spLimits: Record<string, object>\n): Record<string, { Name: string; value: number }> =>\n Object.fromEntries(\n Object.entries(limits)\n .filter(([key]) => !!spLimits[key])\n .map(([key, limit]) => {\n const backendId = (spLimits[key] as { backendId: string }).backendId;\n return [backendId, { Name: backendId, value: Number(limit) || 0 }];\n })\n );\n\nexport const dispatchDelayed = ({ action, delay = TIMEOUTS.threeSeconds, dispatch }: { action: any; delay?: number; dispatch: AppDispatch }) =>\n setTimeout(() => dispatch(action), delay);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"utils.cjs","names":["DEVICE_FILTERING_OPTIONS","yes","DEVICE_ISSUE_OPTIONS","ATTRIBUTE_SCOPES","emptyFilter","ORCHESTRATOR_MANIFEST_ATTRIBUTE_PREFIX","ATTRIBUTE_SCOPE_LABELS","emptyUiPermissions","duplicateFilter","softwareIndicator","deploymentStatesToSubstates","defaultStats","deploymentStatesToSubstatesWithSkipped","DEPLOYMENT_STATES","deploymentDisplayStates","DARK_MODE","TIMEOUTS"],"sources":["../src/utils.ts"],"sourcesContent":["// Copyright 2024 Northern.tech AS\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\nimport type { AttributeFilterPredicate, AttributeResponse, DeviceWithImage, FilterV2, InvoiceLineItem, Scope } from '@northern.tech/types/MenderTypes';\nimport { duplicateFilter, yes } from '@northern.tech/utils/helpers';\nimport type { AxiosError } from 'axios';\n\nimport type { DeviceIssueOptionKey, FilterOperator, Role } from './constants';\nimport {\n ATTRIBUTE_SCOPES,\n ATTRIBUTE_SCOPE_LABELS,\n DARK_MODE,\n DEPLOYMENT_STATES,\n DEVICE_FILTERING_OPTIONS,\n DEVICE_ISSUE_OPTIONS,\n DEVICE_LIST_MAXIMUM_LENGTH,\n ORCHESTRATOR_MANIFEST_ATTRIBUTE_PREFIX,\n TIMEOUTS,\n defaultStats,\n deploymentDisplayStates,\n deploymentStatesToSubstates,\n deploymentStatesToSubstatesWithSkipped,\n emptyFilter,\n emptyUiPermissions,\n softwareIndicator\n} from './constants';\nimport type { Deployment } from './deploymentsSlice';\nimport type { DeviceFilter, DeviceGroup, InventoryAttributes } from './devicesSlice';\nimport type { PricePreview } from './organizationSlice/types';\nimport type { AppDispatch } from './store';\n\ntype FilterProcessorValue = string | string[] | number | boolean; // this aligns with a API compatible `FilterPredicate.value`\ntype FilterProcessor = (val: string) => FilterProcessorValue;\n\n// for some reason these functions can not be stored in the deviceConstants...\nconst filterProcessors: Record<string, FilterProcessor> = {\n [DEVICE_FILTERING_OPTIONS.$gt.key]: (val: string) => Number(val) || val,\n [DEVICE_FILTERING_OPTIONS.$gte.key]: (val: string) => Number(val) || val,\n [DEVICE_FILTERING_OPTIONS.$lt.key]: (val: string) => Number(val) || val,\n [DEVICE_FILTERING_OPTIONS.$lte.key]: (val: string) => Number(val) || val,\n [DEVICE_FILTERING_OPTIONS.$ltne.key]: (val: string) => Number(val) || val,\n [DEVICE_FILTERING_OPTIONS.$in.key]: (val: string) => ('' + val).split(',').map(i => i.trim()),\n [DEVICE_FILTERING_OPTIONS.$nin.key]: (val: string) => ('' + val).split(',').map(i => i.trim()),\n [DEVICE_FILTERING_OPTIONS.$exists.key]: yes,\n [DEVICE_FILTERING_OPTIONS.$nexists.key]: () => false\n};\n\ntype FilterAlias = { alias: FilterOperator; value: boolean };\nconst filterAliases: Record<string, FilterAlias> = {\n $nexists: { alias: DEVICE_FILTERING_OPTIONS.$exists.key, value: false }\n};\n\nexport type FilterTerm = {\n attribute: string;\n scope: Scope;\n type: FilterOperator;\n value: FilterProcessorValue;\n};\n\nexport const mapFiltersToTerms = (filters: DeviceFilter[]): FilterTerm[] =>\n filters.map(filter => ({\n scope: filter.scope,\n attribute: filter.key,\n type: filterAliases[filter.operator]?.alias || filter.operator,\n value: Object.hasOwn(filterProcessors, filter.operator) ? filterProcessors[filter.operator](filter.value as string) : filter.value\n }));\nexport const mapTermsToFilters = (terms: FilterTerm[]): DeviceFilter[] =>\n terms.map(term => {\n const aliasedFilter = Object.entries(filterAliases).find(\n aliasDefinition => aliasDefinition[1].alias === term.type && aliasDefinition[1].value === term.value\n );\n const operator = (aliasedFilter ? aliasedFilter[0] : term.type) as FilterOperator;\n return { scope: term.scope as Scope, key: term.attribute, operator, value: term.value } as DeviceFilter;\n });\n\ntype IssueFilterState = { offlineThreshold?: string };\n\ntype IssueFilterRule = {\n key: string;\n operator: FilterOperator;\n scope: Scope;\n value: string | string[] | ((state: IssueFilterState) => string);\n};\n\nconst convertIssueOptionsToFilters = (issuesSelection: DeviceIssueOptionKey[], filtersState: IssueFilterState = {}): DeviceFilter[] =>\n issuesSelection.map(item => {\n const filterRule = DEVICE_ISSUE_OPTIONS[item].filterRule as IssueFilterRule;\n const value = typeof filterRule.value === 'function' ? filterRule.value(filtersState) : filterRule.value;\n return { key: filterRule.key, operator: filterRule.operator, scope: filterRule.scope, value } as DeviceFilter;\n });\n\nexport const convertDeviceListStateToFilters = ({\n filters = [],\n group,\n groups = { byId: {} },\n offlineThreshold,\n selectedIssues = [],\n status\n}: {\n filters?: DeviceFilter[];\n group?: string;\n groups?: { byId: Record<string, DeviceGroup> };\n offlineThreshold?: string;\n selectedIssues?: DeviceIssueOptionKey[];\n status?: string;\n}) => {\n let applicableFilters = [...filters];\n if (typeof group === 'string' && !(groups.byId[group]?.filters || applicableFilters).length) {\n applicableFilters.push({ key: 'group', value: group, operator: DEVICE_FILTERING_OPTIONS.$eq.key, scope: 'system' });\n }\n const deviceIssueFilters = convertIssueOptionsToFilters(selectedIssues, { offlineThreshold });\n // only drop filters that exactly duplicate a DEVICE_ISSUE_OPTIONS rule - filters on the same attribute are kept\n const nonMonitorFilters = applicableFilters.filter(filter => !deviceIssueFilters.some(issueFilter => filterCompare(issueFilter, filter)));\n applicableFilters = [...nonMonitorFilters, ...deviceIssueFilters];\n const effectiveFilters = status\n ? [...applicableFilters, { key: 'status', value: status, operator: DEVICE_FILTERING_OPTIONS.$eq.key, scope: ATTRIBUTE_SCOPES.identity }]\n : applicableFilters;\n return { applicableFilters: nonMonitorFilters, filterTerms: mapFiltersToTerms(effectiveFilters) };\n};\n\nconst filterCompare = (filter: DeviceFilter, item: DeviceFilter): boolean =>\n Object.keys(emptyFilter).every(key => item[key as keyof DeviceFilter]?.toString() === filter[key as keyof DeviceFilter]?.toString());\n\nexport const filtersFilter = (item: DeviceFilter, index: number, array: DeviceFilter[]): boolean => {\n const firstIndex = array.findIndex(filter => filterCompare(filter, item));\n return firstIndex === index;\n};\n\nexport const stripOrchestratorManifestPrefix = (key: string) =>\n key.startsWith(ORCHESTRATOR_MANIFEST_ATTRIBUTE_PREFIX) ? key.substring(ORCHESTRATOR_MANIFEST_ATTRIBUTE_PREFIX.length) : key;\n\nexport const getAttributeScopeLabel = ({ key = '', scope }: { key?: string; scope?: string }) => {\n if (scope === ATTRIBUTE_SCOPES.system) {\n return ATTRIBUTE_SCOPE_LABELS.default;\n }\n if (scope === ATTRIBUTE_SCOPES.inventory && key.startsWith(ORCHESTRATOR_MANIFEST_ATTRIBUTE_PREFIX)) {\n return ATTRIBUTE_SCOPE_LABELS.system;\n }\n return scope ?? '';\n};\n\nexport const stripUndefined = <T extends Record<string, unknown>>(obj: T): Partial<T> =>\n Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined)) as Partial<T>;\n\nexport const listItemMapper = <T extends object>(\n byId: Record<string, T>,\n ids: string[],\n { cutOffSize = DEVICE_LIST_MAXIMUM_LENGTH, defaultObject = {} as Partial<T> }: { cutOffSize?: number; defaultObject?: Partial<T> }\n): T[] =>\n ids.slice(0, cutOffSize).reduce<T[]>((accu, id) => {\n if (id && byId[id]) {\n accu.push({ ...defaultObject, ...byId[id] });\n }\n return accu;\n }, []);\n\ntype UiPermissions = typeof emptyUiPermissions;\ntype PermissionValue = string[] | Record<string, string[]>; // this would ideally be `PermissionValue = string[] | Record<string, PermissionValue>`\n\nexport const mergePermissions = (existingPermissions: UiPermissions = { ...emptyUiPermissions }, addedPermissions: UiPermissions): UiPermissions =>\n Object.entries(existingPermissions).reduce<UiPermissions>(\n (accu, [key, value]) => {\n let values;\n if (!accu[key]) {\n accu[key] = value;\n return accu;\n }\n if (Array.isArray(value)) {\n values = [...value, ...(accu[key] as string[])].filter(duplicateFilter);\n } else {\n values = mergePermissions(accu[key], { ...value } as unknown as UiPermissions) as unknown as PermissionValue;\n }\n accu[key] = values;\n return accu;\n },\n { ...addedPermissions }\n );\n\nexport const mapUserRolesToUiPermissions = (userRoles: string[], roles: Record<string, Role>): UiPermissions =>\n userRoles.reduce(\n (accu, roleId) => {\n if (!(roleId && roles[roleId])) {\n return accu;\n }\n return mergePermissions(accu, roles[roleId].uiPermissions);\n },\n { ...emptyUiPermissions }\n );\n\nexport const progress = ({ loaded, total }: { loaded: number; total?: number }): number => {\n if (!total) return 0;\n const uploadProgress = (loaded / total) * 100;\n return uploadProgress < 50 ? Math.ceil(uploadProgress) : Math.round(uploadProgress);\n};\n\nexport type ErrorWithResponse = AxiosError<{ error?: { message?: string } | string }> & { error?: string };\n\nexport const extractErrorMessage = (err: ErrorWithResponse, fallback = ''): string =>\n (typeof err.response?.data?.error === 'object' ? err.response?.data?.error?.message : err.response?.data?.error) || err.error || err.message || fallback;\n\nexport const ensureVersionString = (software: string, fallback: string): string =>\n software.length && software !== 'artifact_name' ? (software.endsWith(softwareIndicator) ? software : `${software}${softwareIndicator}`) : fallback;\n\nexport const stringToBoolean = (content: string | number | undefined): boolean => {\n if (!content) {\n return false;\n }\n const string = content + '';\n switch (string.trim().toLowerCase()) {\n case 'true':\n case 'yes':\n case '1':\n return true;\n case 'false':\n case 'no':\n case '0':\n case null:\n return false;\n default:\n return Boolean(string);\n }\n};\n\nexport type DeploymentStats = {\n failures: number;\n inprogress: number;\n paused: number;\n pending: number;\n skipped?: number;\n successes: number;\n};\n\nexport const groupDeploymentDevicesStats = (deployment: Pick<Deployment, 'devices'>): DeploymentStats => {\n const deviceStatCollector = (deploymentStates: string[], devices: Record<string, DeviceWithImage>): number =>\n Object.values(devices).reduce<number>((accu, device) => (deploymentStates.includes(device.status ?? '') ? accu + 1 : accu), 0);\n\n const inprogress = deviceStatCollector(deploymentStatesToSubstates.inprogress, deployment.devices);\n const pending = deviceStatCollector(deploymentStatesToSubstates.pending, deployment.devices);\n const successes = deviceStatCollector(deploymentStatesToSubstates.successes, deployment.devices);\n const failures = deviceStatCollector(deploymentStatesToSubstates.failures, deployment.devices);\n const paused = deviceStatCollector(deploymentStatesToSubstates.paused, deployment.devices);\n return { inprogress, paused, pending, successes, failures };\n};\n\nexport const statCollector = (items: string[], statistics: Record<string, number>): number =>\n items.reduce((accu, property) => accu + Number(statistics[property] || 0), 0);\n\nexport const groupDeploymentStats = (deployment: Partial<Deployment>, withSkipped?: boolean): DeploymentStats => {\n const { statistics = {} } = deployment;\n const { status = {} } = statistics;\n const stats = { ...defaultStats, ...status };\n const groupStates = withSkipped ? deploymentStatesToSubstatesWithSkipped : deploymentStatesToSubstates;\n const result: DeploymentStats = {\n // don't include 'pending' as inprogress, as all remaining devices will be pending - we don't discriminate based on phase membership\n inprogress: statCollector(groupStates.inprogress, stats),\n pending: statCollector(groupStates.pending, stats),\n successes: statCollector(groupStates.successes, stats),\n failures: statCollector(groupStates.failures, stats),\n paused: statCollector(groupStates.paused, stats)\n };\n if (withSkipped) {\n result.skipped = statCollector(groupStates.skipped!, stats);\n }\n return result;\n};\n\nexport const getDeploymentState = (deployment: Partial<Deployment>): string => {\n const { status: deploymentStatus = DEPLOYMENT_STATES.pending } = deployment;\n const { inprogress: currentProgressCount, paused } = groupDeploymentStats(deployment);\n\n let status = deploymentDisplayStates[deploymentStatus];\n if (deploymentStatus === DEPLOYMENT_STATES.pending && currentProgressCount === 0) {\n status = 'queued';\n } else if (paused > 0) {\n status = deploymentDisplayStates.paused;\n }\n return status;\n};\n\ntype DeploymentFilter =\n | FilterV2\n | {\n terms?: Array<AttributeFilterPredicate | { key: string }>;\n };\n\nexport const generateDeploymentGroupDetails = (filter: DeploymentFilter | undefined, groupName: string): string =>\n filter && filter.terms?.length\n ? `${groupName} (${filter.terms\n .map(\n filter =>\n `${filter.attribute || filter.key} ${DEVICE_FILTERING_OPTIONS[filter.type || filter.operator || DEVICE_FILTERING_OPTIONS.$eq.key].shortform} ${filter.value}`\n )\n .join(', ')})`\n : groupName;\n\ntype DeviceAttributeMap = {\n identity: Record<string, string>;\n inventory: InventoryAttributes;\n monitor: Record<string, string>;\n system: Record<string, string>;\n tags: Record<string, string>;\n};\n\nexport const mapDeviceAttributes = (attributes: AttributeResponse[] = []): DeviceAttributeMap =>\n attributes.reduce<DeviceAttributeMap>(\n (accu, attribute) => {\n if (!(attribute.value && attribute.name) && attribute.scope === ATTRIBUTE_SCOPES.inventory) {\n return accu;\n }\n const scope = (attribute.scope || ATTRIBUTE_SCOPES.inventory) as keyof DeviceAttributeMap;\n (accu[scope] as Record<string, unknown>) = {\n ...accu[scope],\n [attribute.name]: attribute.value\n };\n if (attribute.name === 'device_type' && attribute.scope === ATTRIBUTE_SCOPES.inventory) {\n accu.inventory.device_type = ([] as string[]).concat(attribute.value as string | string[]);\n }\n return accu;\n },\n { inventory: { device_type: [] as string[], artifact_name: '' }, identity: {}, monitor: {}, system: {}, tags: {} }\n );\n\nexport const isDarkMode = (mode: string): boolean => mode === DARK_MODE;\n\ntype Line = InvoiceLineItem & { product: 'mender_standard' | 'mender_micro' };\nexport const parseSubscriptionPreview = (lines: Line[]): PricePreview['items'] =>\n lines.reduce((acc, { addon, amount, product }) => {\n const tier = product.replace('mender_', '');\n if (!acc[tier]) {\n acc[tier] = {\n amount: 0,\n addons: {}\n };\n }\n if (!addon) {\n acc[tier].amount += amount;\n } else {\n acc[tier].addons[addon] = (acc[tier].addons[addon] ?? 0) + amount;\n }\n return acc;\n }, {});\n\nexport const convertToBackendSPLimits = (\n limits: Record<string, number | string>,\n spLimits: Record<string, object>\n): Record<string, { Name: string; value: number }> =>\n Object.fromEntries(\n Object.entries(limits)\n .filter(([key]) => !!spLimits[key])\n .map(([key, limit]) => {\n const backendId = (spLimits[key] as { backendId: string }).backendId;\n return [backendId, { Name: backendId, value: Number(limit) || 0 }];\n })\n );\n\nexport const dispatchDelayed = ({ action, delay = TIMEOUTS.threeSeconds, dispatch }: { action: any; delay?: number; dispatch: AppDispatch }) =>\n setTimeout(() => dispatch(action), delay);\n"],"mappings":"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"}
|
package/dist/utils.js
CHANGED
|
@@ -52,11 +52,8 @@ const convertDeviceListStateToFilters = ({ filters = [], group, groups = { byId:
|
|
|
52
52
|
operator: DEVICE_FILTERING_OPTIONS.$eq.key,
|
|
53
53
|
scope: "system"
|
|
54
54
|
});
|
|
55
|
-
const nonMonitorFilters = applicableFilters.filter((filter) => !Object.values(DEVICE_ISSUE_OPTIONS).some(({ filterRule }) => {
|
|
56
|
-
const { key = "", scope = "" } = filterRule;
|
|
57
|
-
return filter.scope !== "inventory" && scope === filter.scope && key === filter.key;
|
|
58
|
-
}));
|
|
59
55
|
const deviceIssueFilters = convertIssueOptionsToFilters(selectedIssues, { offlineThreshold });
|
|
56
|
+
const nonMonitorFilters = applicableFilters.filter((filter) => !deviceIssueFilters.some((issueFilter) => filterCompare(issueFilter, filter)));
|
|
60
57
|
applicableFilters = [...nonMonitorFilters, ...deviceIssueFilters];
|
|
61
58
|
const effectiveFilters = status ? [...applicableFilters, {
|
|
62
59
|
key: "status",
|
package/dist/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","names":[],"sources":["../src/utils.ts"],"sourcesContent":["// Copyright 2024 Northern.tech AS\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\nimport type { AttributeFilterPredicate, AttributeResponse, DeviceWithImage, FilterV2, InvoiceLineItem, Scope } from '@northern.tech/types/MenderTypes';\nimport { duplicateFilter, yes } from '@northern.tech/utils/helpers';\nimport type { AxiosError } from 'axios';\n\nimport type { DeviceIssueOptionKey, FilterOperator, Role } from './constants';\nimport {\n ATTRIBUTE_SCOPES,\n ATTRIBUTE_SCOPE_LABELS,\n DARK_MODE,\n DEPLOYMENT_STATES,\n DEVICE_FILTERING_OPTIONS,\n DEVICE_ISSUE_OPTIONS,\n DEVICE_LIST_MAXIMUM_LENGTH,\n ORCHESTRATOR_MANIFEST_ATTRIBUTE_PREFIX,\n TIMEOUTS,\n defaultStats,\n deploymentDisplayStates,\n deploymentStatesToSubstates,\n deploymentStatesToSubstatesWithSkipped,\n emptyFilter,\n emptyUiPermissions,\n softwareIndicator\n} from './constants';\nimport type { Deployment } from './deploymentsSlice';\nimport type { DeviceFilter, DeviceGroup, InventoryAttributes } from './devicesSlice';\nimport type { PricePreview } from './organizationSlice/types';\nimport type { AppDispatch } from './store';\n\ntype FilterProcessorValue = string | string[] | number | boolean; // this aligns with a API compatible `FilterPredicate.value`\ntype FilterProcessor = (val: string) => FilterProcessorValue;\n\n// for some reason these functions can not be stored in the deviceConstants...\nconst filterProcessors: Record<string, FilterProcessor> = {\n [DEVICE_FILTERING_OPTIONS.$gt.key]: (val: string) => Number(val) || val,\n [DEVICE_FILTERING_OPTIONS.$gte.key]: (val: string) => Number(val) || val,\n [DEVICE_FILTERING_OPTIONS.$lt.key]: (val: string) => Number(val) || val,\n [DEVICE_FILTERING_OPTIONS.$lte.key]: (val: string) => Number(val) || val,\n [DEVICE_FILTERING_OPTIONS.$ltne.key]: (val: string) => Number(val) || val,\n [DEVICE_FILTERING_OPTIONS.$in.key]: (val: string) => ('' + val).split(',').map(i => i.trim()),\n [DEVICE_FILTERING_OPTIONS.$nin.key]: (val: string) => ('' + val).split(',').map(i => i.trim()),\n [DEVICE_FILTERING_OPTIONS.$exists.key]: yes,\n [DEVICE_FILTERING_OPTIONS.$nexists.key]: () => false\n};\n\ntype FilterAlias = { alias: FilterOperator; value: boolean };\nconst filterAliases: Record<string, FilterAlias> = {\n $nexists: { alias: DEVICE_FILTERING_OPTIONS.$exists.key, value: false }\n};\n\nexport type FilterTerm = {\n attribute: string;\n scope: Scope;\n type: FilterOperator;\n value: FilterProcessorValue;\n};\n\nexport const mapFiltersToTerms = (filters: DeviceFilter[]): FilterTerm[] =>\n filters.map(filter => ({\n scope: filter.scope,\n attribute: filter.key,\n type: filterAliases[filter.operator]?.alias || filter.operator,\n value: Object.hasOwn(filterProcessors, filter.operator) ? filterProcessors[filter.operator](filter.value as string) : filter.value\n }));\nexport const mapTermsToFilters = (terms: FilterTerm[]): DeviceFilter[] =>\n terms.map(term => {\n const aliasedFilter = Object.entries(filterAliases).find(\n aliasDefinition => aliasDefinition[1].alias === term.type && aliasDefinition[1].value === term.value\n );\n const operator = (aliasedFilter ? aliasedFilter[0] : term.type) as FilterOperator;\n return { scope: term.scope as Scope, key: term.attribute, operator, value: term.value } as DeviceFilter;\n });\n\ntype IssueFilterState = { offlineThreshold?: string };\n\ntype IssueFilterRule = {\n key: string;\n operator: FilterOperator;\n scope: Scope;\n value: string | string[] | ((state: IssueFilterState) => string);\n};\n\nconst convertIssueOptionsToFilters = (issuesSelection: DeviceIssueOptionKey[], filtersState: IssueFilterState = {}): DeviceFilter[] =>\n issuesSelection.map(item => {\n const filterRule = DEVICE_ISSUE_OPTIONS[item].filterRule as IssueFilterRule;\n const value = typeof filterRule.value === 'function' ? filterRule.value(filtersState) : filterRule.value;\n return { key: filterRule.key, operator: filterRule.operator, scope: filterRule.scope, value } as DeviceFilter;\n });\n\nexport const convertDeviceListStateToFilters = ({\n filters = [],\n group,\n groups = { byId: {} },\n offlineThreshold,\n selectedIssues = [],\n status\n}: {\n filters?: DeviceFilter[];\n group?: string;\n groups?: { byId: Record<string, DeviceGroup> };\n offlineThreshold?: string;\n selectedIssues?: DeviceIssueOptionKey[];\n status?: string;\n}) => {\n let applicableFilters = [...filters];\n if (typeof group === 'string' && !(groups.byId[group]?.filters || applicableFilters).length) {\n applicableFilters.push({ key: 'group', value: group, operator: DEVICE_FILTERING_OPTIONS.$eq.key, scope: 'system' });\n }\n const nonMonitorFilters = applicableFilters.filter(\n filter =>\n !Object.values(DEVICE_ISSUE_OPTIONS).some(({ filterRule }) => {\n const { key = '', scope = '' } = filterRule as IssueFilterRule;\n return filter.scope !== 'inventory' && scope === filter.scope && key === filter.key;\n })\n );\n const deviceIssueFilters = convertIssueOptionsToFilters(selectedIssues, { offlineThreshold });\n applicableFilters = [...nonMonitorFilters, ...deviceIssueFilters];\n const effectiveFilters = status\n ? [...applicableFilters, { key: 'status', value: status, operator: DEVICE_FILTERING_OPTIONS.$eq.key, scope: ATTRIBUTE_SCOPES.identity }]\n : applicableFilters;\n return { applicableFilters: nonMonitorFilters, filterTerms: mapFiltersToTerms(effectiveFilters) };\n};\n\nconst filterCompare = (filter: DeviceFilter, item: DeviceFilter): boolean =>\n Object.keys(emptyFilter).every(key => item[key as keyof DeviceFilter]?.toString() === filter[key as keyof DeviceFilter]?.toString());\n\nexport const filtersFilter = (item: DeviceFilter, index: number, array: DeviceFilter[]): boolean => {\n const firstIndex = array.findIndex(filter => filterCompare(filter, item));\n return firstIndex === index;\n};\n\nexport const stripOrchestratorManifestPrefix = (key: string) =>\n key.startsWith(ORCHESTRATOR_MANIFEST_ATTRIBUTE_PREFIX) ? key.substring(ORCHESTRATOR_MANIFEST_ATTRIBUTE_PREFIX.length) : key;\n\nexport const getAttributeScopeLabel = ({ key = '', scope }: { key?: string; scope?: string }) => {\n if (scope === ATTRIBUTE_SCOPES.system) {\n return ATTRIBUTE_SCOPE_LABELS.default;\n }\n if (scope === ATTRIBUTE_SCOPES.inventory && key.startsWith(ORCHESTRATOR_MANIFEST_ATTRIBUTE_PREFIX)) {\n return ATTRIBUTE_SCOPE_LABELS.system;\n }\n return scope ?? '';\n};\n\nexport const stripUndefined = <T extends Record<string, unknown>>(obj: T): Partial<T> =>\n Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined)) as Partial<T>;\n\nexport const listItemMapper = <T extends object>(\n byId: Record<string, T>,\n ids: string[],\n { cutOffSize = DEVICE_LIST_MAXIMUM_LENGTH, defaultObject = {} as Partial<T> }: { cutOffSize?: number; defaultObject?: Partial<T> }\n): T[] =>\n ids.slice(0, cutOffSize).reduce<T[]>((accu, id) => {\n if (id && byId[id]) {\n accu.push({ ...defaultObject, ...byId[id] });\n }\n return accu;\n }, []);\n\ntype UiPermissions = typeof emptyUiPermissions;\ntype PermissionValue = string[] | Record<string, string[]>; // this would ideally be `PermissionValue = string[] | Record<string, PermissionValue>`\n\nexport const mergePermissions = (existingPermissions: UiPermissions = { ...emptyUiPermissions }, addedPermissions: UiPermissions): UiPermissions =>\n Object.entries(existingPermissions).reduce<UiPermissions>(\n (accu, [key, value]) => {\n let values;\n if (!accu[key]) {\n accu[key] = value;\n return accu;\n }\n if (Array.isArray(value)) {\n values = [...value, ...(accu[key] as string[])].filter(duplicateFilter);\n } else {\n values = mergePermissions(accu[key], { ...value } as unknown as UiPermissions) as unknown as PermissionValue;\n }\n accu[key] = values;\n return accu;\n },\n { ...addedPermissions }\n );\n\nexport const mapUserRolesToUiPermissions = (userRoles: string[], roles: Record<string, Role>): UiPermissions =>\n userRoles.reduce(\n (accu, roleId) => {\n if (!(roleId && roles[roleId])) {\n return accu;\n }\n return mergePermissions(accu, roles[roleId].uiPermissions);\n },\n { ...emptyUiPermissions }\n );\n\nexport const progress = ({ loaded, total }: { loaded: number; total?: number }): number => {\n if (!total) return 0;\n const uploadProgress = (loaded / total) * 100;\n return uploadProgress < 50 ? Math.ceil(uploadProgress) : Math.round(uploadProgress);\n};\n\nexport type ErrorWithResponse = AxiosError<{ error?: { message?: string } | string }> & { error?: string };\n\nexport const extractErrorMessage = (err: ErrorWithResponse, fallback = ''): string =>\n (typeof err.response?.data?.error === 'object' ? err.response?.data?.error?.message : err.response?.data?.error) || err.error || err.message || fallback;\n\nexport const ensureVersionString = (software: string, fallback: string): string =>\n software.length && software !== 'artifact_name' ? (software.endsWith(softwareIndicator) ? software : `${software}${softwareIndicator}`) : fallback;\n\nexport const stringToBoolean = (content: string | number | undefined): boolean => {\n if (!content) {\n return false;\n }\n const string = content + '';\n switch (string.trim().toLowerCase()) {\n case 'true':\n case 'yes':\n case '1':\n return true;\n case 'false':\n case 'no':\n case '0':\n case null:\n return false;\n default:\n return Boolean(string);\n }\n};\n\nexport type DeploymentStats = {\n failures: number;\n inprogress: number;\n paused: number;\n pending: number;\n skipped?: number;\n successes: number;\n};\n\nexport const groupDeploymentDevicesStats = (deployment: Pick<Deployment, 'devices'>): DeploymentStats => {\n const deviceStatCollector = (deploymentStates: string[], devices: Record<string, DeviceWithImage>): number =>\n Object.values(devices).reduce<number>((accu, device) => (deploymentStates.includes(device.status ?? '') ? accu + 1 : accu), 0);\n\n const inprogress = deviceStatCollector(deploymentStatesToSubstates.inprogress, deployment.devices);\n const pending = deviceStatCollector(deploymentStatesToSubstates.pending, deployment.devices);\n const successes = deviceStatCollector(deploymentStatesToSubstates.successes, deployment.devices);\n const failures = deviceStatCollector(deploymentStatesToSubstates.failures, deployment.devices);\n const paused = deviceStatCollector(deploymentStatesToSubstates.paused, deployment.devices);\n return { inprogress, paused, pending, successes, failures };\n};\n\nexport const statCollector = (items: string[], statistics: Record<string, number>): number =>\n items.reduce((accu, property) => accu + Number(statistics[property] || 0), 0);\n\nexport const groupDeploymentStats = (deployment: Partial<Deployment>, withSkipped?: boolean): DeploymentStats => {\n const { statistics = {} } = deployment;\n const { status = {} } = statistics;\n const stats = { ...defaultStats, ...status };\n const groupStates = withSkipped ? deploymentStatesToSubstatesWithSkipped : deploymentStatesToSubstates;\n const result: DeploymentStats = {\n // don't include 'pending' as inprogress, as all remaining devices will be pending - we don't discriminate based on phase membership\n inprogress: statCollector(groupStates.inprogress, stats),\n pending: statCollector(groupStates.pending, stats),\n successes: statCollector(groupStates.successes, stats),\n failures: statCollector(groupStates.failures, stats),\n paused: statCollector(groupStates.paused, stats)\n };\n if (withSkipped) {\n result.skipped = statCollector(groupStates.skipped!, stats);\n }\n return result;\n};\n\nexport const getDeploymentState = (deployment: Partial<Deployment>): string => {\n const { status: deploymentStatus = DEPLOYMENT_STATES.pending } = deployment;\n const { inprogress: currentProgressCount, paused } = groupDeploymentStats(deployment);\n\n let status = deploymentDisplayStates[deploymentStatus];\n if (deploymentStatus === DEPLOYMENT_STATES.pending && currentProgressCount === 0) {\n status = 'queued';\n } else if (paused > 0) {\n status = deploymentDisplayStates.paused;\n }\n return status;\n};\n\ntype DeploymentFilter =\n | FilterV2\n | {\n terms?: Array<AttributeFilterPredicate | { key: string }>;\n };\n\nexport const generateDeploymentGroupDetails = (filter: DeploymentFilter | undefined, groupName: string): string =>\n filter && filter.terms?.length\n ? `${groupName} (${filter.terms\n .map(\n filter =>\n `${filter.attribute || filter.key} ${DEVICE_FILTERING_OPTIONS[filter.type || filter.operator || DEVICE_FILTERING_OPTIONS.$eq.key].shortform} ${filter.value}`\n )\n .join(', ')})`\n : groupName;\n\ntype DeviceAttributeMap = {\n identity: Record<string, string>;\n inventory: InventoryAttributes;\n monitor: Record<string, string>;\n system: Record<string, string>;\n tags: Record<string, string>;\n};\n\nexport const mapDeviceAttributes = (attributes: AttributeResponse[] = []): DeviceAttributeMap =>\n attributes.reduce<DeviceAttributeMap>(\n (accu, attribute) => {\n if (!(attribute.value && attribute.name) && attribute.scope === ATTRIBUTE_SCOPES.inventory) {\n return accu;\n }\n const scope = (attribute.scope || ATTRIBUTE_SCOPES.inventory) as keyof DeviceAttributeMap;\n (accu[scope] as Record<string, unknown>) = {\n ...accu[scope],\n [attribute.name]: attribute.value\n };\n if (attribute.name === 'device_type' && attribute.scope === ATTRIBUTE_SCOPES.inventory) {\n accu.inventory.device_type = ([] as string[]).concat(attribute.value as string | string[]);\n }\n return accu;\n },\n { inventory: { device_type: [] as string[], artifact_name: '' }, identity: {}, monitor: {}, system: {}, tags: {} }\n );\n\nexport const isDarkMode = (mode: string): boolean => mode === DARK_MODE;\n\ntype Line = InvoiceLineItem & { product: 'mender_standard' | 'mender_micro' };\nexport const parseSubscriptionPreview = (lines: Line[]): PricePreview['items'] =>\n lines.reduce((acc, { addon, amount, product }) => {\n const tier = product.replace('mender_', '');\n if (!acc[tier]) {\n acc[tier] = {\n amount: 0,\n addons: {}\n };\n }\n if (!addon) {\n acc[tier].amount += amount;\n } else {\n acc[tier].addons[addon] = (acc[tier].addons[addon] ?? 0) + amount;\n }\n return acc;\n }, {});\n\nexport const convertToBackendSPLimits = (\n limits: Record<string, number | string>,\n spLimits: Record<string, object>\n): Record<string, { Name: string; value: number }> =>\n Object.fromEntries(\n Object.entries(limits)\n .filter(([key]) => !!spLimits[key])\n .map(([key, limit]) => {\n const backendId = (spLimits[key] as { backendId: string }).backendId;\n return [backendId, { Name: backendId, value: Number(limit) || 0 }];\n })\n );\n\nexport const dispatchDelayed = ({ action, delay = TIMEOUTS.threeSeconds, dispatch }: { action: any; delay?: number; dispatch: AppDispatch }) =>\n setTimeout(() => dispatch(action), delay);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"utils.js","names":[],"sources":["../src/utils.ts"],"sourcesContent":["// Copyright 2024 Northern.tech AS\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\nimport type { AttributeFilterPredicate, AttributeResponse, DeviceWithImage, FilterV2, InvoiceLineItem, Scope } from '@northern.tech/types/MenderTypes';\nimport { duplicateFilter, yes } from '@northern.tech/utils/helpers';\nimport type { AxiosError } from 'axios';\n\nimport type { DeviceIssueOptionKey, FilterOperator, Role } from './constants';\nimport {\n ATTRIBUTE_SCOPES,\n ATTRIBUTE_SCOPE_LABELS,\n DARK_MODE,\n DEPLOYMENT_STATES,\n DEVICE_FILTERING_OPTIONS,\n DEVICE_ISSUE_OPTIONS,\n DEVICE_LIST_MAXIMUM_LENGTH,\n ORCHESTRATOR_MANIFEST_ATTRIBUTE_PREFIX,\n TIMEOUTS,\n defaultStats,\n deploymentDisplayStates,\n deploymentStatesToSubstates,\n deploymentStatesToSubstatesWithSkipped,\n emptyFilter,\n emptyUiPermissions,\n softwareIndicator\n} from './constants';\nimport type { Deployment } from './deploymentsSlice';\nimport type { DeviceFilter, DeviceGroup, InventoryAttributes } from './devicesSlice';\nimport type { PricePreview } from './organizationSlice/types';\nimport type { AppDispatch } from './store';\n\ntype FilterProcessorValue = string | string[] | number | boolean; // this aligns with a API compatible `FilterPredicate.value`\ntype FilterProcessor = (val: string) => FilterProcessorValue;\n\n// for some reason these functions can not be stored in the deviceConstants...\nconst filterProcessors: Record<string, FilterProcessor> = {\n [DEVICE_FILTERING_OPTIONS.$gt.key]: (val: string) => Number(val) || val,\n [DEVICE_FILTERING_OPTIONS.$gte.key]: (val: string) => Number(val) || val,\n [DEVICE_FILTERING_OPTIONS.$lt.key]: (val: string) => Number(val) || val,\n [DEVICE_FILTERING_OPTIONS.$lte.key]: (val: string) => Number(val) || val,\n [DEVICE_FILTERING_OPTIONS.$ltne.key]: (val: string) => Number(val) || val,\n [DEVICE_FILTERING_OPTIONS.$in.key]: (val: string) => ('' + val).split(',').map(i => i.trim()),\n [DEVICE_FILTERING_OPTIONS.$nin.key]: (val: string) => ('' + val).split(',').map(i => i.trim()),\n [DEVICE_FILTERING_OPTIONS.$exists.key]: yes,\n [DEVICE_FILTERING_OPTIONS.$nexists.key]: () => false\n};\n\ntype FilterAlias = { alias: FilterOperator; value: boolean };\nconst filterAliases: Record<string, FilterAlias> = {\n $nexists: { alias: DEVICE_FILTERING_OPTIONS.$exists.key, value: false }\n};\n\nexport type FilterTerm = {\n attribute: string;\n scope: Scope;\n type: FilterOperator;\n value: FilterProcessorValue;\n};\n\nexport const mapFiltersToTerms = (filters: DeviceFilter[]): FilterTerm[] =>\n filters.map(filter => ({\n scope: filter.scope,\n attribute: filter.key,\n type: filterAliases[filter.operator]?.alias || filter.operator,\n value: Object.hasOwn(filterProcessors, filter.operator) ? filterProcessors[filter.operator](filter.value as string) : filter.value\n }));\nexport const mapTermsToFilters = (terms: FilterTerm[]): DeviceFilter[] =>\n terms.map(term => {\n const aliasedFilter = Object.entries(filterAliases).find(\n aliasDefinition => aliasDefinition[1].alias === term.type && aliasDefinition[1].value === term.value\n );\n const operator = (aliasedFilter ? aliasedFilter[0] : term.type) as FilterOperator;\n return { scope: term.scope as Scope, key: term.attribute, operator, value: term.value } as DeviceFilter;\n });\n\ntype IssueFilterState = { offlineThreshold?: string };\n\ntype IssueFilterRule = {\n key: string;\n operator: FilterOperator;\n scope: Scope;\n value: string | string[] | ((state: IssueFilterState) => string);\n};\n\nconst convertIssueOptionsToFilters = (issuesSelection: DeviceIssueOptionKey[], filtersState: IssueFilterState = {}): DeviceFilter[] =>\n issuesSelection.map(item => {\n const filterRule = DEVICE_ISSUE_OPTIONS[item].filterRule as IssueFilterRule;\n const value = typeof filterRule.value === 'function' ? filterRule.value(filtersState) : filterRule.value;\n return { key: filterRule.key, operator: filterRule.operator, scope: filterRule.scope, value } as DeviceFilter;\n });\n\nexport const convertDeviceListStateToFilters = ({\n filters = [],\n group,\n groups = { byId: {} },\n offlineThreshold,\n selectedIssues = [],\n status\n}: {\n filters?: DeviceFilter[];\n group?: string;\n groups?: { byId: Record<string, DeviceGroup> };\n offlineThreshold?: string;\n selectedIssues?: DeviceIssueOptionKey[];\n status?: string;\n}) => {\n let applicableFilters = [...filters];\n if (typeof group === 'string' && !(groups.byId[group]?.filters || applicableFilters).length) {\n applicableFilters.push({ key: 'group', value: group, operator: DEVICE_FILTERING_OPTIONS.$eq.key, scope: 'system' });\n }\n const deviceIssueFilters = convertIssueOptionsToFilters(selectedIssues, { offlineThreshold });\n // only drop filters that exactly duplicate a DEVICE_ISSUE_OPTIONS rule - filters on the same attribute are kept\n const nonMonitorFilters = applicableFilters.filter(filter => !deviceIssueFilters.some(issueFilter => filterCompare(issueFilter, filter)));\n applicableFilters = [...nonMonitorFilters, ...deviceIssueFilters];\n const effectiveFilters = status\n ? [...applicableFilters, { key: 'status', value: status, operator: DEVICE_FILTERING_OPTIONS.$eq.key, scope: ATTRIBUTE_SCOPES.identity }]\n : applicableFilters;\n return { applicableFilters: nonMonitorFilters, filterTerms: mapFiltersToTerms(effectiveFilters) };\n};\n\nconst filterCompare = (filter: DeviceFilter, item: DeviceFilter): boolean =>\n Object.keys(emptyFilter).every(key => item[key as keyof DeviceFilter]?.toString() === filter[key as keyof DeviceFilter]?.toString());\n\nexport const filtersFilter = (item: DeviceFilter, index: number, array: DeviceFilter[]): boolean => {\n const firstIndex = array.findIndex(filter => filterCompare(filter, item));\n return firstIndex === index;\n};\n\nexport const stripOrchestratorManifestPrefix = (key: string) =>\n key.startsWith(ORCHESTRATOR_MANIFEST_ATTRIBUTE_PREFIX) ? key.substring(ORCHESTRATOR_MANIFEST_ATTRIBUTE_PREFIX.length) : key;\n\nexport const getAttributeScopeLabel = ({ key = '', scope }: { key?: string; scope?: string }) => {\n if (scope === ATTRIBUTE_SCOPES.system) {\n return ATTRIBUTE_SCOPE_LABELS.default;\n }\n if (scope === ATTRIBUTE_SCOPES.inventory && key.startsWith(ORCHESTRATOR_MANIFEST_ATTRIBUTE_PREFIX)) {\n return ATTRIBUTE_SCOPE_LABELS.system;\n }\n return scope ?? '';\n};\n\nexport const stripUndefined = <T extends Record<string, unknown>>(obj: T): Partial<T> =>\n Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined)) as Partial<T>;\n\nexport const listItemMapper = <T extends object>(\n byId: Record<string, T>,\n ids: string[],\n { cutOffSize = DEVICE_LIST_MAXIMUM_LENGTH, defaultObject = {} as Partial<T> }: { cutOffSize?: number; defaultObject?: Partial<T> }\n): T[] =>\n ids.slice(0, cutOffSize).reduce<T[]>((accu, id) => {\n if (id && byId[id]) {\n accu.push({ ...defaultObject, ...byId[id] });\n }\n return accu;\n }, []);\n\ntype UiPermissions = typeof emptyUiPermissions;\ntype PermissionValue = string[] | Record<string, string[]>; // this would ideally be `PermissionValue = string[] | Record<string, PermissionValue>`\n\nexport const mergePermissions = (existingPermissions: UiPermissions = { ...emptyUiPermissions }, addedPermissions: UiPermissions): UiPermissions =>\n Object.entries(existingPermissions).reduce<UiPermissions>(\n (accu, [key, value]) => {\n let values;\n if (!accu[key]) {\n accu[key] = value;\n return accu;\n }\n if (Array.isArray(value)) {\n values = [...value, ...(accu[key] as string[])].filter(duplicateFilter);\n } else {\n values = mergePermissions(accu[key], { ...value } as unknown as UiPermissions) as unknown as PermissionValue;\n }\n accu[key] = values;\n return accu;\n },\n { ...addedPermissions }\n );\n\nexport const mapUserRolesToUiPermissions = (userRoles: string[], roles: Record<string, Role>): UiPermissions =>\n userRoles.reduce(\n (accu, roleId) => {\n if (!(roleId && roles[roleId])) {\n return accu;\n }\n return mergePermissions(accu, roles[roleId].uiPermissions);\n },\n { ...emptyUiPermissions }\n );\n\nexport const progress = ({ loaded, total }: { loaded: number; total?: number }): number => {\n if (!total) return 0;\n const uploadProgress = (loaded / total) * 100;\n return uploadProgress < 50 ? Math.ceil(uploadProgress) : Math.round(uploadProgress);\n};\n\nexport type ErrorWithResponse = AxiosError<{ error?: { message?: string } | string }> & { error?: string };\n\nexport const extractErrorMessage = (err: ErrorWithResponse, fallback = ''): string =>\n (typeof err.response?.data?.error === 'object' ? err.response?.data?.error?.message : err.response?.data?.error) || err.error || err.message || fallback;\n\nexport const ensureVersionString = (software: string, fallback: string): string =>\n software.length && software !== 'artifact_name' ? (software.endsWith(softwareIndicator) ? software : `${software}${softwareIndicator}`) : fallback;\n\nexport const stringToBoolean = (content: string | number | undefined): boolean => {\n if (!content) {\n return false;\n }\n const string = content + '';\n switch (string.trim().toLowerCase()) {\n case 'true':\n case 'yes':\n case '1':\n return true;\n case 'false':\n case 'no':\n case '0':\n case null:\n return false;\n default:\n return Boolean(string);\n }\n};\n\nexport type DeploymentStats = {\n failures: number;\n inprogress: number;\n paused: number;\n pending: number;\n skipped?: number;\n successes: number;\n};\n\nexport const groupDeploymentDevicesStats = (deployment: Pick<Deployment, 'devices'>): DeploymentStats => {\n const deviceStatCollector = (deploymentStates: string[], devices: Record<string, DeviceWithImage>): number =>\n Object.values(devices).reduce<number>((accu, device) => (deploymentStates.includes(device.status ?? '') ? accu + 1 : accu), 0);\n\n const inprogress = deviceStatCollector(deploymentStatesToSubstates.inprogress, deployment.devices);\n const pending = deviceStatCollector(deploymentStatesToSubstates.pending, deployment.devices);\n const successes = deviceStatCollector(deploymentStatesToSubstates.successes, deployment.devices);\n const failures = deviceStatCollector(deploymentStatesToSubstates.failures, deployment.devices);\n const paused = deviceStatCollector(deploymentStatesToSubstates.paused, deployment.devices);\n return { inprogress, paused, pending, successes, failures };\n};\n\nexport const statCollector = (items: string[], statistics: Record<string, number>): number =>\n items.reduce((accu, property) => accu + Number(statistics[property] || 0), 0);\n\nexport const groupDeploymentStats = (deployment: Partial<Deployment>, withSkipped?: boolean): DeploymentStats => {\n const { statistics = {} } = deployment;\n const { status = {} } = statistics;\n const stats = { ...defaultStats, ...status };\n const groupStates = withSkipped ? deploymentStatesToSubstatesWithSkipped : deploymentStatesToSubstates;\n const result: DeploymentStats = {\n // don't include 'pending' as inprogress, as all remaining devices will be pending - we don't discriminate based on phase membership\n inprogress: statCollector(groupStates.inprogress, stats),\n pending: statCollector(groupStates.pending, stats),\n successes: statCollector(groupStates.successes, stats),\n failures: statCollector(groupStates.failures, stats),\n paused: statCollector(groupStates.paused, stats)\n };\n if (withSkipped) {\n result.skipped = statCollector(groupStates.skipped!, stats);\n }\n return result;\n};\n\nexport const getDeploymentState = (deployment: Partial<Deployment>): string => {\n const { status: deploymentStatus = DEPLOYMENT_STATES.pending } = deployment;\n const { inprogress: currentProgressCount, paused } = groupDeploymentStats(deployment);\n\n let status = deploymentDisplayStates[deploymentStatus];\n if (deploymentStatus === DEPLOYMENT_STATES.pending && currentProgressCount === 0) {\n status = 'queued';\n } else if (paused > 0) {\n status = deploymentDisplayStates.paused;\n }\n return status;\n};\n\ntype DeploymentFilter =\n | FilterV2\n | {\n terms?: Array<AttributeFilterPredicate | { key: string }>;\n };\n\nexport const generateDeploymentGroupDetails = (filter: DeploymentFilter | undefined, groupName: string): string =>\n filter && filter.terms?.length\n ? `${groupName} (${filter.terms\n .map(\n filter =>\n `${filter.attribute || filter.key} ${DEVICE_FILTERING_OPTIONS[filter.type || filter.operator || DEVICE_FILTERING_OPTIONS.$eq.key].shortform} ${filter.value}`\n )\n .join(', ')})`\n : groupName;\n\ntype DeviceAttributeMap = {\n identity: Record<string, string>;\n inventory: InventoryAttributes;\n monitor: Record<string, string>;\n system: Record<string, string>;\n tags: Record<string, string>;\n};\n\nexport const mapDeviceAttributes = (attributes: AttributeResponse[] = []): DeviceAttributeMap =>\n attributes.reduce<DeviceAttributeMap>(\n (accu, attribute) => {\n if (!(attribute.value && attribute.name) && attribute.scope === ATTRIBUTE_SCOPES.inventory) {\n return accu;\n }\n const scope = (attribute.scope || ATTRIBUTE_SCOPES.inventory) as keyof DeviceAttributeMap;\n (accu[scope] as Record<string, unknown>) = {\n ...accu[scope],\n [attribute.name]: attribute.value\n };\n if (attribute.name === 'device_type' && attribute.scope === ATTRIBUTE_SCOPES.inventory) {\n accu.inventory.device_type = ([] as string[]).concat(attribute.value as string | string[]);\n }\n return accu;\n },\n { inventory: { device_type: [] as string[], artifact_name: '' }, identity: {}, monitor: {}, system: {}, tags: {} }\n );\n\nexport const isDarkMode = (mode: string): boolean => mode === DARK_MODE;\n\ntype Line = InvoiceLineItem & { product: 'mender_standard' | 'mender_micro' };\nexport const parseSubscriptionPreview = (lines: Line[]): PricePreview['items'] =>\n lines.reduce((acc, { addon, amount, product }) => {\n const tier = product.replace('mender_', '');\n if (!acc[tier]) {\n acc[tier] = {\n amount: 0,\n addons: {}\n };\n }\n if (!addon) {\n acc[tier].amount += amount;\n } else {\n acc[tier].addons[addon] = (acc[tier].addons[addon] ?? 0) + amount;\n }\n return acc;\n }, {});\n\nexport const convertToBackendSPLimits = (\n limits: Record<string, number | string>,\n spLimits: Record<string, object>\n): Record<string, { Name: string; value: number }> =>\n Object.fromEntries(\n Object.entries(limits)\n .filter(([key]) => !!spLimits[key])\n .map(([key, limit]) => {\n const backendId = (spLimits[key] as { backendId: string }).backendId;\n return [backendId, { Name: backendId, value: Number(limit) || 0 }];\n })\n );\n\nexport const dispatchDelayed = ({ action, delay = TIMEOUTS.threeSeconds, dispatch }: { action: any; delay?: number; dispatch: AppDispatch }) =>\n setTimeout(() => dispatch(action), delay);\n"],"mappings":"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"}
|