@odigos/ui-kit 0.0.48 → 0.0.49
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/CHANGELOG.md +8 -0
- package/eslint.config.mjs +16 -2
- package/lib/components/data-card/data-card-fields/index.d.ts +2 -1
- package/lib/components/error-boundary/error-boundary.stories.d.ts +3 -1
- package/lib/components/error-boundary/index.d.ts +1 -2
- package/lib/components/field-error/field-error.stories.d.ts +3 -1
- package/lib/components/field-error/index.d.ts +1 -2
- package/lib/components/segment/index.d.ts +8 -7
- package/lib/components/styled.d.ts +5 -1
- package/lib/components.js +6 -6
- package/lib/containers/await-pipeline/await-pipeline.stories.d.ts +1 -1
- package/lib/containers/await-pipeline/index.d.ts +1 -2
- package/lib/containers/data-flow-actions-menu/add-entity/index.d.ts +2 -3
- package/lib/containers/data-flow-actions-menu/filters/index.d.ts +2 -3
- package/lib/containers/data-flow-actions-menu/search/index.d.ts +2 -3
- package/lib/containers/data-stream-modal/data-stream-modal.stories.d.ts +2 -2
- package/lib/containers/data-stream-modal/index.d.ts +1 -2
- package/lib/containers/index.d.ts +1 -0
- package/lib/containers/notification-manager/index.d.ts +1 -2
- package/lib/containers/notification-manager/notification-manager.stories.d.ts +1 -1
- package/lib/containers/service-map/helpers/build-edges.d.ts +10 -0
- package/lib/containers/service-map/helpers/build-map-nodes.d.ts +11 -0
- package/lib/containers/service-map/index.d.ts +8 -0
- package/lib/containers/service-map/service-map.stories.d.ts +9 -0
- package/lib/containers/slack-invite/index.d.ts +1 -2
- package/lib/containers/slack-invite/slack-invite.stories.d.ts +1 -1
- package/lib/containers/toast-list/index.d.ts +1 -2
- package/lib/containers/toast-list/toast-list.stories.d.ts +1 -1
- package/lib/containers/toggle-dark-mode/index.d.ts +1 -2
- package/lib/containers/toggle-dark-mode/toggle-dark-mode.stories.d.ts +1 -1
- package/lib/containers.js +381 -12479
- package/lib/functions/clean-object-empty-strings-values/index.d.ts +2 -1
- package/lib/functions/compare-condition/index.d.ts +1 -1
- package/lib/functions/flatten-object-keys/index.d.ts +2 -1
- package/lib/functions/get-entity-id/index.d.ts +2 -2
- package/lib/functions/get-entity-label/index.d.ts +2 -2
- package/lib/functions/index.d.ts +1 -0
- package/lib/functions/map-destination-fields-for-display/index.d.ts +1 -1
- package/lib/functions/remove-empty-values-from-object/index.d.ts +2 -1
- package/lib/functions/safe-json-parse/index.d.ts +2 -1
- package/lib/functions/safe-json-stringify/index.d.ts +2 -1
- package/lib/functions/stringify-non-string-values/index.d.ts +2 -1
- package/lib/functions.js +32 -6
- package/lib/hooks/useGenericForm.d.ts +2 -1
- package/lib/hooks/useInstrumentationRuleFormData.d.ts +1 -4
- package/lib/hooks/useSessionStorage.d.ts +2 -2
- package/lib/hooks/useSourceFormData.d.ts +1 -4
- package/lib/hooks.js +3 -3
- package/lib/icons/common/index.d.ts +1 -0
- package/lib/icons/common/user-icon/index.d.ts +2 -0
- package/lib/icons/common/user-icon/user-icon.stories.d.ts +8 -0
- package/lib/icons.js +1 -1
- package/lib/{index-BV85P9UP.js → index-BnvrwbRB.js} +4 -0
- package/lib/{index-DXBePB-r.js → index-C1V7D2ey.js} +12724 -359
- package/lib/{index-BWIOWlkS.js → index-CeBxw8J4.js} +1 -1
- package/lib/{index-BIYXaOIt.js → index-CeDmxXUE.js} +9 -1
- package/lib/{index-DHHUJe_a.js → index-DOU0EdZP.js} +1 -1
- package/lib/{index-CrXEzEGw.js → index-DsEoqSQn.js} +1 -1
- package/lib/{index-D_SG1Qp0.js → index-w9lkC6fb.js} +7 -5
- package/lib/mock-data/index.d.ts +1 -0
- package/lib/mock-data/service-map/index.d.ts +2 -0
- package/lib/snippets/index.d.ts +1 -0
- package/lib/{containers/data-flow → snippets/react-flow}/edges/labeled-edge.d.ts +4 -4
- package/lib/{containers/data-flow → snippets/react-flow}/flow.d.ts +2 -0
- package/lib/snippets/react-flow/index.d.ts +13 -0
- package/lib/{containers/data-flow → snippets/react-flow}/nodes/add-node.d.ts +4 -4
- package/lib/{containers/data-flow → snippets/react-flow}/nodes/base-node.d.ts +4 -4
- package/lib/{containers/data-flow → snippets/react-flow}/nodes/edged-node.d.ts +4 -4
- package/lib/{containers/data-flow → snippets/react-flow}/nodes/frame-node.d.ts +4 -4
- package/lib/{containers/data-flow → snippets/react-flow}/nodes/header-node.d.ts +4 -4
- package/lib/snippets/react-flow/nodes/map-item-node.d.ts +12 -0
- package/lib/snippets/react-flow/nodes/no-data-node.d.ts +9 -0
- package/lib/{containers/data-flow → snippets/react-flow}/nodes/scroll-node.d.ts +4 -4
- package/lib/snippets/react-flow/nodes/skeleton-node.d.ts +8 -0
- package/lib/snippets.js +5 -5
- package/lib/types/common/index.d.ts +1 -0
- package/lib/types/data-flow/index.d.ts +3 -1
- package/lib/types/describe/index.d.ts +1 -1
- package/lib/types/index.d.ts +1 -0
- package/lib/types/service-map/index.d.ts +10 -0
- package/lib/types.js +2 -0
- package/lib/{useSourceSelectionFormData-BP-O55O3.js → useSourceSelectionFormData-C5VMfWEf.js} +13 -48
- package/lib/{useTransition-DanOnTji.js → useTransition-mupXsbop.js} +43 -9
- package/package.json +3 -2
- package/lib/containers/data-flow/nodes/skeleton-node.d.ts +0 -8
- /package/lib/{containers/data-flow/helpers/get-main-container-language.d.ts → functions/get-main-container-language/index.d.ts} +0 -0
- /package/lib/{containers/data-flow/helpers → snippets/react-flow}/node-config.d.ts +0 -0
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import type { AnyObj } from '@/types';
|
|
2
|
+
export declare const cleanObjectEmptyStringsValues: (obj: AnyObj) => AnyObj;
|
|
@@ -29,4 +29,5 @@
|
|
|
29
29
|
* 'name.explain': '...',
|
|
30
30
|
* }
|
|
31
31
|
*/
|
|
32
|
-
|
|
32
|
+
import type { AnyObj } from '@/types';
|
|
33
|
+
export declare const flattenObjectKeys: (obj: AnyObj, prefix?: string, result?: AnyObj) => AnyObj;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { WorkloadId } from '@/types';
|
|
2
|
-
export declare const getEntityId: (item:
|
|
1
|
+
import type { AnyObj, WorkloadId } from '@/types';
|
|
2
|
+
export declare const getEntityId: (item: AnyObj) => string | WorkloadId | undefined;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { EntityTypes } from '@/types';
|
|
2
|
-
export declare const getEntityLabel: (entity:
|
|
1
|
+
import { type AnyObj, EntityTypes } from '@/types';
|
|
2
|
+
export declare const getEntityLabel: (entity: AnyObj, entityType: EntityTypes, options?: {
|
|
3
3
|
extended?: boolean;
|
|
4
4
|
prioritizeDisplayName?: boolean;
|
|
5
5
|
}) => string;
|
package/lib/functions/index.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export * from './get-entity-id';
|
|
|
19
19
|
export * from './get-entity-label';
|
|
20
20
|
export * from './get-id-from-sse-target';
|
|
21
21
|
export * from './get-instrumentation-rule-icon';
|
|
22
|
+
export * from './get-main-container-language';
|
|
22
23
|
export * from './get-metric-for-entity';
|
|
23
24
|
export * from './get-monitor-icon';
|
|
24
25
|
export * from './get-platform-icon';
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import type { AnyObj } from '@/types';
|
|
2
|
+
export declare const removeEmptyValuesFromObject: (obj: AnyObj) => AnyObj;
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import type { AnyObj } from '@/types';
|
|
2
|
+
export declare function safeJsonParse<T = AnyObj>(val: T | string | undefined, fallback: T): T;
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import type { AnyObj } from '@/types';
|
|
2
|
+
export declare const safeJsonStringify: (obj?: AnyObj, indent?: number) => string;
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import type { AnyObj } from '@/types';
|
|
2
|
+
export declare const stringifyNonStringValues: (obj: AnyObj) => Record<string, string>;
|
package/lib/functions.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
export { c as capitalizeFirstLetter, f as flattenObjectKeys, g as getConditionsBooleans, a as getMonitorIcon, b as getStatusIcon, i as isValidVersion, m as mapConditions, n as numbersOnly, p as parseBooleanFromString, d as parseJsonStringToPrettyString, r as removeEmptyValuesFromObject, s as safeJsonStringify, e as splitCamelString } from './index-
|
|
2
|
-
export { c as compareCondition, d as deepClone, f as filterActions, a as filterDestinations, b as filterDestinationsByStream, e as filterSources, g as filterSourcesByStream, h as formatBytes, j as getContainersIcons, i as getContainersInstrumentedCount, k as getDestinationIcon, l as getEntityIcon, m as getEntityLabel, n as getMetricForEntity, o as getPlatformIcon, p as getPlatformLabel, q as getValueForRange, r as getWorkloadId, s as getYamlFieldsForDestination, t as isOverTime, u as mapDestinationFieldsForDisplay, v as sleep } from './index-
|
|
1
|
+
export { c as capitalizeFirstLetter, f as flattenObjectKeys, g as getConditionsBooleans, a as getMonitorIcon, b as getStatusIcon, i as isValidVersion, m as mapConditions, n as numbersOnly, p as parseBooleanFromString, d as parseJsonStringToPrettyString, r as removeEmptyValuesFromObject, s as safeJsonStringify, e as splitCamelString } from './index-DsEoqSQn.js';
|
|
2
|
+
export { c as compareCondition, d as deepClone, f as filterActions, a as filterDestinations, b as filterDestinationsByStream, e as filterSources, g as filterSourcesByStream, h as formatBytes, j as getContainersIcons, i as getContainersInstrumentedCount, k as getDestinationIcon, l as getEntityIcon, m as getEntityLabel, n as getMetricForEntity, o as getPlatformIcon, p as getPlatformLabel, q as getValueForRange, r as getWorkloadId, s as getYamlFieldsForDestination, t as isOverTime, u as mapDestinationFieldsForDisplay, v as sleep } from './index-w9lkC6fb.js';
|
|
3
3
|
export { m as getActionIcon, n as getEntityId, o as getInstrumentationRuleIcon, p as getProgrammingLanguageIcon } from './index-Bw7RE2T2.js';
|
|
4
4
|
export { g as getIdFromSseTarget, i as isLegalK8sLabel, m as mapExportedSignals } from './index-BlZKWuxe.js';
|
|
5
|
-
import { EntityTypes } from './types.js';
|
|
6
|
-
export { i as isEmpty, s as safeJsonParse } from './index-
|
|
5
|
+
import { ProgrammingLanguages, EntityTypes } from './types.js';
|
|
6
|
+
export { i as isEmpty, s as safeJsonParse } from './index-BnvrwbRB.js';
|
|
7
7
|
import 'react';
|
|
8
8
|
import 'styled-components';
|
|
9
9
|
import './index-DxR7e2Cq.js';
|
|
10
10
|
import './index-ZTzxu5fz.js';
|
|
11
11
|
|
|
12
12
|
const cleanObjectEmptyStringsValues = (obj) => {
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
13
14
|
const cleanArray = (arr) => arr.filter((item) => {
|
|
14
15
|
if (typeof item === 'object' && item !== null) {
|
|
15
16
|
return item.key !== '' && item.value !== '';
|
|
@@ -38,7 +39,7 @@ const cleanObjectEmptyStringsValues = (obj) => {
|
|
|
38
39
|
acc[key] = value;
|
|
39
40
|
}
|
|
40
41
|
}
|
|
41
|
-
catch (
|
|
42
|
+
catch (_) {
|
|
42
43
|
// Handle non-stringified objects or arrays directly
|
|
43
44
|
if (typeof value === 'object' && value !== null) {
|
|
44
45
|
if (Array.isArray(value))
|
|
@@ -55,6 +56,31 @@ const cleanObjectEmptyStringsValues = (obj) => {
|
|
|
55
56
|
}, {});
|
|
56
57
|
};
|
|
57
58
|
|
|
59
|
+
// while odigos lists language per container, we want to aggregate one single language for the workload.
|
|
60
|
+
// the process is mostly heuristic, we iterate over the containers and return the first valid language we find.
|
|
61
|
+
// there are additional cases for when the workload programming language is not available.
|
|
62
|
+
const getMainContainerLanguage = (source) => {
|
|
63
|
+
const { numberOfInstances, containers } = source;
|
|
64
|
+
if (!containers) {
|
|
65
|
+
if (!!numberOfInstances && numberOfInstances > 0) {
|
|
66
|
+
return ProgrammingLanguages.Processing;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
return ProgrammingLanguages.NoRunningPods;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// we will filter out the ignored languages as we don't want to account them in the main language
|
|
73
|
+
const noneIgnoredLanguages = containers?.filter((container) => container.language !== ProgrammingLanguages.Ignored);
|
|
74
|
+
if (!noneIgnoredLanguages.length)
|
|
75
|
+
return ProgrammingLanguages.NoContainers;
|
|
76
|
+
// find the first container with valid language
|
|
77
|
+
const mainContainer = noneIgnoredLanguages.find((container) => container.language !== ProgrammingLanguages.Unknown);
|
|
78
|
+
// no valid language found, return the first one
|
|
79
|
+
if (!mainContainer)
|
|
80
|
+
return ProgrammingLanguages.Unknown;
|
|
81
|
+
return mainContainer.language;
|
|
82
|
+
};
|
|
83
|
+
|
|
58
84
|
const getSseTargetFromId = (id, type) => {
|
|
59
85
|
switch (type) {
|
|
60
86
|
case EntityTypes.Source: {
|
|
@@ -90,4 +116,4 @@ const stringifyNonStringValues = (obj) => {
|
|
|
90
116
|
}, {});
|
|
91
117
|
};
|
|
92
118
|
|
|
93
|
-
export { cleanObjectEmptyStringsValues, getSseTargetFromId, isTimeElapsed, stringifyNonStringValues };
|
|
119
|
+
export { cleanObjectEmptyStringsValues, getMainContainerLanguage, getSseTargetFromId, isTimeElapsed, stringifyNonStringValues };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import type { AnyObj } from '@/types';
|
|
2
|
+
export declare const useGenericForm: <Form extends AnyObj>(initialFormData: Form) => {
|
|
2
3
|
formData: Form;
|
|
3
4
|
formErrors: Partial<Record<keyof Form, string>>;
|
|
4
5
|
handleFormChange: (key?: keyof Form | string, val?: any, obj?: Form) => void;
|
|
@@ -4,9 +4,6 @@ export declare const useInstrumentationRuleFormData: () => {
|
|
|
4
4
|
formErrors: Partial<Record<"ruleName" | "notes" | "disabled" | "workloads" | "instrumentationLibraries" | "codeAttributes" | "headersCollection" | "payloadCollection" | "customInstrumentations", string>>;
|
|
5
5
|
handleFormChange: (key?: string | undefined, val?: any, obj?: InstrumentationRuleFormData | undefined) => void;
|
|
6
6
|
resetFormData: () => void;
|
|
7
|
-
validateForm: (
|
|
8
|
-
withAlert?: boolean;
|
|
9
|
-
alertTitle?: string;
|
|
10
|
-
}) => boolean;
|
|
7
|
+
validateForm: () => boolean;
|
|
11
8
|
loadFormWithDrawerItem: ({ ruleName, notes, disabled, payloadCollection, codeAttributes, headersCollection, customInstrumentations }: InstrumentationRule) => void;
|
|
12
9
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare const useSessionStorage: () => {
|
|
2
|
-
getItemSS: (key: string, defaultValue:
|
|
3
|
-
setItemSS: (key: string, value:
|
|
2
|
+
getItemSS: <T>(key: string, defaultValue: T) => T;
|
|
3
|
+
setItemSS: <T>(key: string, value: T) => void;
|
|
4
4
|
removeItemSS: (key: string) => void;
|
|
5
5
|
};
|
|
@@ -4,9 +4,6 @@ export declare const useSourceFormData: () => {
|
|
|
4
4
|
formErrors: Partial<Record<keyof SourceFormData, string>>;
|
|
5
5
|
handleFormChange: (key?: string | undefined, val?: any, obj?: SourceFormData | undefined) => void;
|
|
6
6
|
resetFormData: () => void;
|
|
7
|
-
validateForm: (
|
|
8
|
-
withAlert?: boolean;
|
|
9
|
-
alertTitle?: string;
|
|
10
|
-
}) => boolean;
|
|
7
|
+
validateForm: () => boolean;
|
|
11
8
|
loadFormWithDrawerItem: ({ otelServiceName, name }: Source) => void;
|
|
12
9
|
};
|
package/lib/hooks.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export { u as useActionFormData, a as
|
|
2
|
-
export { u as
|
|
1
|
+
export { u as useActionFormData, a as useClickNotification, b as useDataStreamFormData, c as useDestinationFormData, d as useSessionStorage, e as useSourceFormData, f as useSourceSelectionFormData } from './useSourceSelectionFormData-C5VMfWEf.js';
|
|
2
|
+
export { u as useClickNode, a as useContainerSize, b as useCopy, c as useGenericForm, d as useInstrumentationRuleFormData, e as useKeyDown, f as useOnClickOutside, g as useTimeAgo, h as useTransition } from './useTransition-mupXsbop.js';
|
|
3
3
|
import './types.js';
|
|
4
4
|
import './index-Bw7RE2T2.js';
|
|
5
5
|
import 'react';
|
|
6
6
|
import 'styled-components';
|
|
7
|
-
import './index-
|
|
7
|
+
import './index-BnvrwbRB.js';
|
|
8
8
|
import './index-BlZKWuxe.js';
|
package/lib/icons.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { T as Theme } from './index-Bw7RE2T2.js';
|
|
2
2
|
export { q as AddClusterInfoIcon, y as CPlusPlusLogo, z as CSharpLogo, C as CodeAttributesIcon, w as CustomInstrumentationIcon, r as DeleteAttributeIcon, E as DotnetLogo, G as ElixirLogo, J as GoLogo, H as HeadersCollectionIcon, t as ImageErrorIcon, N as JavaLogo, K as K8sLogo, v as KafkaLogo, O as MysqlLogo, Q as NginxLogo, U as NodejsLogo, x as PayloadCollectionIcon, V as PhpLogo, P as PiiMaskingIcon, W as PostgresLogo, X as PythonLogo, Y as RedisLogo, R as RenameAttributeIcon, Z as RubyLogo, _ as RustLogo, s as SamplerIcon, $ as SwiftLogo } from './index-Bw7RE2T2.js';
|
|
3
3
|
export { C as CheckCircledIcon, E as ErrorTriangleIcon, I as InfoIcon, L as LogsIcon, M as MetricsIcon, O as OdigosLogo, T as TracesIcon, W as WarningTriangleIcon } from './index-DxR7e2Cq.js';
|
|
4
|
-
export { C as CrossCircledIcon, D as DataStreamsIcon, F as FilterIcon, K as KeyIcon, N as NotificationIcon, O as OdigosLogoText, a as OverviewIcon, R as RetryIcon, S as SlackLogo, T as TerminalIcon } from './index-
|
|
4
|
+
export { C as CrossCircledIcon, D as DataStreamsIcon, F as FilterIcon, K as KeyIcon, N as NotificationIcon, O as OdigosLogoText, a as OverviewIcon, R as RetryIcon, S as SlackLogo, T as TerminalIcon, U as UserIcon } from './index-CeDmxXUE.js';
|
|
5
5
|
export { A as ArrowIcon, h as CheckIcon, C as CodeIcon, a as CopyIcon, i as CrossIcon, E as EditIcon, b as EditedIcon, c as ExtendArrowIcon, f as EyeClosedIcon, g as EyeOpenIcon, L as ListIcon, M as MinusIcon, N as NoDataIcon, d as NotebookIcon, P as PlusIcon, S as SearchIcon, e as SortArrowsIcon, T as TrashIcon, X as XIcon } from './index-CkTdd3MS.js';
|
|
6
6
|
import React from 'react';
|
|
7
7
|
export { a3 as ActionsIcon, A as AlaudaLogo, a as AlibabaCloudLogo, b as AppDynamicsLogo, c as AwsCloudwatchLogo, d as AwsS3Logo, e as AwsXrayLogo, f as AxiomLogo, B as BetterStackLogo, g as BlobStorageLogo, h as BonreeLogo, C as CauselyLogo, i as ChecklyLogo, j as ChronosphereLogo, k as ClickhouseLogo, l as CoralogixLogo, D as Dash0Logo, m as DatadogLogo, a4 as DestinationsIcon, n as DynatraceLogo, E as ElasticApmLogo, o as ElasticSearchLogo, G as GigapipeLogo, p as GoogleCloudPlatformLogo, q as GrafanaLogo, r as GreptimeLogo, s as GroundcoverLogo, H as HoneycombLogo, t as HyperDxLogo, I as InstanaLogo, J as JaegerLogo, K as KloudmateLogo, L as Last9Logo, u as LightstepLogo, v as LogzioLogo, w as LokiLogo, x as LumigoLogo, M as MiddlewareLogo, a5 as NamespacesIcon, N as NewRelicLogo, O as ObserveLogo, y as OneUptimeLogo, z as OpenObserveLogo, F as OpenTelemetryLogo, P as OpsVerseLogo, Q as OracleLogo, R as PrometheusLogo, S as QrynLogo, T as QuickwitLogo, a6 as RulesIcon, U as SeqLogo, W as SignozLogo, a7 as SourcesIcon, X as SplunkLogo, Y as SumoLogicLogo, Z as TelemetryHubLogo, _ as TempoLogo, $ as TingyunLogo, a0 as TraceloopLogo, a1 as UptraceLogo, a2 as VictoriaMetricsLogo, V as VmLogo } from './index-ZTzxu5fz.js';
|
|
@@ -15,14 +15,18 @@ function safeJsonParse(val, fallback) {
|
|
|
15
15
|
|
|
16
16
|
// Sometimes we need to allow "zero" values, and a simple "!val" check would result in false positives.
|
|
17
17
|
// This function is a strict check for empty values, permitting values like "0" and "false".
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
18
19
|
const isEmpty = (val) => {
|
|
19
20
|
if (Array.isArray(val)) {
|
|
21
|
+
// empty
|
|
20
22
|
return !val?.length;
|
|
21
23
|
}
|
|
22
24
|
else if (typeof val === 'object') {
|
|
25
|
+
// empty
|
|
23
26
|
return !Object.keys(val || {}).length;
|
|
24
27
|
}
|
|
25
28
|
else {
|
|
29
|
+
// empty if included
|
|
26
30
|
return [undefined, null, ''].includes(val);
|
|
27
31
|
}
|
|
28
32
|
};
|