forked from elastic/kibana
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.tsx
107 lines (98 loc) · 3.52 KB
/
index.tsx
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
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { EuiAccordion, EuiFlexGroup, EuiFlexItem, EuiTitle } from '@elastic/eui';
import type { Filter } from '@kbn/es-query';
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
import { firstNonNullValue } from '../../helpers';
import type { RawBucket } from '../types';
import { createGroupFilter } from './helpers';
interface GroupPanelProps<T> {
customAccordionButtonClassName?: string;
customAccordionClassName?: string;
extraAction?: React.ReactNode;
forceState?: 'open' | 'closed';
groupBucket: RawBucket<T>;
groupPanelRenderer?: JSX.Element;
groupingLevel?: number;
isLoading: boolean;
onGroupClose: () => void;
onToggleGroup?: (isOpen: boolean, groupBucket: RawBucket<T>) => void;
renderChildComponent: (groupFilter: Filter[]) => React.ReactElement;
selectedGroup: string;
}
const DefaultGroupPanelRenderer = ({ title }: { title: string }) => (
<div>
<EuiFlexGroup gutterSize="s" alignItems="center" responsive={false}>
<EuiFlexItem>
<EuiTitle size="xs" className="euiAccordionForm__title">
<h4 className="eui-textTruncate">{title}</h4>
</EuiTitle>
</EuiFlexItem>
</EuiFlexGroup>
</div>
);
const GroupPanelComponent = <T,>({
customAccordionButtonClassName,
customAccordionClassName = 'groupingAccordionForm',
extraAction,
forceState,
groupBucket,
groupPanelRenderer,
groupingLevel = 0,
isLoading,
onGroupClose,
onToggleGroup,
renderChildComponent,
selectedGroup,
}: GroupPanelProps<T>) => {
const lastForceState = useRef(forceState);
useEffect(() => {
if (lastForceState.current === 'open' && forceState === 'closed') {
// when parent group closes, reset pagination of any child groups
onGroupClose();
lastForceState.current = 'closed';
} else if (lastForceState.current === 'closed' && forceState === 'open') {
lastForceState.current = 'open';
}
}, [onGroupClose, forceState, selectedGroup]);
const groupFieldValue = useMemo(() => firstNonNullValue(groupBucket.key), [groupBucket.key]);
const groupFilters = useMemo(
() => createGroupFilter(selectedGroup, groupFieldValue),
[groupFieldValue, selectedGroup]
);
const onToggle = useCallback(
(isOpen) => {
if (onToggleGroup) {
onToggleGroup(isOpen, groupBucket);
}
},
[groupBucket, onToggleGroup]
);
return !groupFieldValue ? null : (
<EuiAccordion
buttonClassName={customAccordionButtonClassName}
buttonContent={
<div data-test-subj="group-panel-toggle" className="groupingPanelRenderer">
{groupPanelRenderer ?? <DefaultGroupPanelRenderer title={groupFieldValue} />}
</div>
}
buttonElement="div"
className={groupingLevel > 0 ? 'groupingAccordionFormLevel' : customAccordionClassName}
data-test-subj="grouping-accordion"
extraAction={extraAction}
forceState={forceState}
isLoading={isLoading}
id={`group${groupingLevel}-${groupFieldValue}`}
onToggle={onToggle}
paddingSize="m"
>
<span data-test-subj="grouping-accordion-content">{renderChildComponent(groupFilters)}</span>
</EuiAccordion>
);
};
export const GroupPanel = React.memo(GroupPanelComponent);