Mirror of https://github.com/roostorg/osprey
github.com/roostorg/osprey
1import * as React from 'react';
2import { ExclamationCircleOutlined } from '@ant-design/icons';
3import { Drawer, notification, Modal } from 'antd';
4import shallow from 'zustand/shallow';
5
6import { getGroupByApproximateCountResults, postTopBulkLabelTask } from '../../actions/EventActions';
7import useLabelStore from '../../stores/LabelStore';
8import useQueryStore from '../../stores/QueryStore';
9import { LabelMutation } from '../../types/LabelTypes';
10import LabelForm from '../common/LabelForm';
11import EntityDrawer from '../entities/LabelDrawer';
12
13import styles from './BulkLabelDrawer.module.css';
14
15interface BulkLabelDrawerContentProps {
16 onCancel: (supressConfirmationModal: boolean) => void;
17 onEntityUnchecked: (entityUnchecked: boolean) => void;
18}
19
20const BulkLabelDrawerContent = ({ onCancel, onEntityUnchecked }: BulkLabelDrawerContentProps) => {
21 const [bulkLabelEntityType, bulkLabelFeatureName] = useLabelStore(
22 (state) => [state.bulkLabelEntityType, state.bulkLabelFeatureName],
23 shallow
24 );
25 const executedQuery = useQueryStore((state) => state.executedQuery);
26 const entityFeatureFilters = useQueryStore((state) => state.entityFeatureFilters);
27 const [entityCount, setEntityCount] = React.useState(0);
28 const [entityCountString, setEntityCountString] = React.useState('[CALCULATING...]');
29 const calculateApproximateCount = () => {
30 getGroupByApproximateCountResults({ ...executedQuery, entityFeatureFilters }, bulkLabelFeatureName)
31 .then((value) => {
32 if (!value) {
33 setEntityCountString('[COULD NOT CALCULATE]');
34 } else {
35 setEntityCountString(value.toLocaleString());
36 setEntityCount(value);
37 }
38 })
39 .catch((err) => {
40 console.error(err);
41 setEntityCountString('[COULD NOT CALCULATE]');
42 });
43 };
44 React.useEffect(calculateApproximateCount, []);
45
46 const [showChildDrawer, setShowChildDrawer] = React.useState(false);
47
48 const handleChildDrawerClose = () => {
49 setShowChildDrawer(false);
50 };
51
52 const handleSubmit = async (labelMutation: LabelMutation, noLimit: boolean) => {
53 if (bulkLabelFeatureName == null) return;
54
55 noLimit = noLimit ?? false;
56 const taskId = await postTopBulkLabelTask(
57 { ...executedQuery, entityFeatureFilters },
58 bulkLabelFeatureName,
59 new Set(), // excluded entities; removing for optimization purposes
60 entityCount,
61 noLimit,
62 labelMutation
63 );
64
65 if (taskId === null) {
66 notification.error({
67 message: 'Bulk Label Task Failed to Start',
68 description: `Task Failed`,
69 });
70 } else {
71 notification.success({
72 message: 'Bulk Label Task Started',
73 description: `A bulk label task with id ${taskId} has been started.`,
74 });
75 onCancel(true);
76 }
77 };
78
79 return (
80 <>
81 <>
82 <div className={styles.__invalid_headerLeft}>
83 <ExclamationCircleOutlined className={styles.exclamationIcon} />
84 <span>This contains approximately {entityCountString} unique entities.</span>
85 </div>
86 <LabelForm
87 entityType={bulkLabelEntityType}
88 onCancel={() => onCancel(false)}
89 onSubmit={(labelMutation, no_limit) => handleSubmit(labelMutation, no_limit)}
90 isBulkLabel={true}
91 />
92 </>
93 <EntityDrawer childDrawerProps={{ isVisible: showChildDrawer, onDrawerClose: handleChildDrawerClose }} />
94 </>
95 );
96};
97
98const BulkLabelDrawer: React.FC = () => {
99 const [showBulkLabelDrawer, updateShowBulkLabelDrawer] = useLabelStore(
100 (state) => [state.showBulkLabelDrawer, state.updateShowBulkLabelDrawer],
101 shallow
102 );
103
104 const [showConfirmModal, setShowConfirmModal] = React.useState(false);
105 const [entitiesHaveBeenUnchecked, setEntitiesHaveBeenUnchecked] = React.useState(false);
106
107 const handleDrawerClose = (supressConfirmationModal: boolean) => {
108 if (!entitiesHaveBeenUnchecked || supressConfirmationModal) {
109 updateShowBulkLabelDrawer(false, null, null);
110 } else {
111 setShowConfirmModal(true);
112 }
113 };
114
115 const handleConfirmationOk = () => {
116 setShowConfirmModal(false);
117 updateShowBulkLabelDrawer(false, null, null);
118 };
119
120 const handleConfirmationCancel = () => {
121 setShowConfirmModal(false);
122 };
123
124 return (
125 <Drawer
126 width={450}
127 title="Bulk Edit Labels"
128 visible={showBulkLabelDrawer}
129 onClose={() => {
130 handleDrawerClose(true);
131 }}
132 destroyOnClose
133 >
134 <BulkLabelDrawerContent onCancel={handleDrawerClose} onEntityUnchecked={setEntitiesHaveBeenUnchecked} />
135 <Modal
136 title="Are you sure you want to close?"
137 visible={showConfirmModal}
138 onOk={handleConfirmationOk}
139 onCancel={handleConfirmationCancel}
140 >
141 <p>You have some entities deselected and you'll lose the state if you close!</p>
142 </Modal>
143 </Drawer>
144 );
145};
146
147export default BulkLabelDrawer;