This repository has been archived by the owner on Jan 16, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 11
/
useWidgetOperations.ts
113 lines (107 loc) · 4.53 KB
/
useWidgetOperations.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import { useMemo } from 'react'
import { Operation, OperationGroup, isOperationGroup, OperationInclusionDescriptor } from '../interfaces/operation'
import { WidgetMeta, WidgetOperations } from '../interfaces/widget'
const emptyArray: Array<Operation | OperationGroup> = []
/**
* Returns a memoized array of operations with respect to include/exclude list in widget meta configuration
*
* @param operations List of operations
* @param widgetMeta Widget meta configuration
* @param bcName BC name in case of hierarchy usage
* @category Hooks
*/
export function useWidgetOperations(operations: Array<Operation | OperationGroup>, widgetMeta: WidgetMeta, bcName?: string) {
return useMemo(() => {
const isHierarchy = widgetMeta.options?.hierarchy?.length > 0
const actionGroup: WidgetOperations =
widgetMeta.options?.actionGroups &&
(isHierarchy ? (widgetMeta.options.actionGroups as Record<string, WidgetOperations>)[bcName] : widgetMeta.options.actionGroups)
if (!actionGroup) {
return operations || emptyArray
}
const { include, exclude } = actionGroup
return getIncludedOperations(operations || emptyArray, include, exclude)
}, [operations, widgetMeta, bcName])
}
/**
* Returns an array of operations with respect to include/exclude lists.
*
* If element is an operation group than its nested operations also checked against inclusion/exclusion lists;
* noth inclusion/exclusion lists from arguments and from group declarations are checked against.
*
* @param operations List of operations
* @param include List of operations to include
* @param exclude List of operations to exclude
* @category Utils
*/
export function getIncludedOperations(
operations: Array<Operation | OperationGroup>,
include: OperationInclusionDescriptor[],
exclude: OperationInclusionDescriptor[]
) {
const result: Array<Operation | OperationGroup> = []
operations.forEach(item => {
if (shouldPickOperation(item, include, exclude)) {
if (isOperationGroup(item)) {
const filtered = item.actions.filter(operation => {
if (!include) {
return shouldPickOperation(operation, null, exclude)
}
const nestedDescriptor = include.find(descriptor => getDescriptorValue(descriptor) === item.type)
const excludeAll =
nestedDescriptor && typeof nestedDescriptor === 'string'
? [nestedDescriptor, ...(exclude || [])]
: [...((nestedDescriptor as any).exclude || []), ...(exclude || [])]
return (
nestedDescriptor &&
shouldPickOperation(operation, typeof nestedDescriptor !== 'string' && nestedDescriptor.include, excludeAll)
)
})
result.push({ ...item, actions: filtered })
} else {
result.push(item)
}
}
})
return result
}
/**
* Checks operation or operation group against inclusion/exclusion lists:
* - if inclusion list is specified then operation should be present there and shouldn't be present in exlusion list
* - if inlusion list is not specified then operation should be absent from exclusion list
*
* @param item Operation or operation group to check
* @param include List of operations to include
* @param exclude List of operations to exclude
* @category Utils
*/
export function shouldPickOperation(
item: Operation | OperationGroup,
include: OperationInclusionDescriptor[],
exclude: OperationInclusionDescriptor[]
) {
if (!include && exclude) {
return exclude.every(descriptor => getDescriptorValue(descriptor) !== item.type)
}
if (include && !exclude) {
return include.some(descriptor => getDescriptorValue(descriptor) === item.type)
}
if (include && exclude) {
return (
include.some(descriptor => getDescriptorValue(descriptor) === item.type) &&
exclude.every(descriptor => getDescriptorValue(descriptor) !== item.type)
)
}
return true
}
/**
* Получает тип операции из элемента списка включения/исключения
*
* @param descriptor Строка или объект с этой строкой
*/
function getDescriptorValue(descriptor: OperationInclusionDescriptor) {
if (typeof descriptor === 'string') {
return descriptor
}
return descriptor.type
}