-
Notifications
You must be signed in to change notification settings - Fork 114
Expand file tree
/
Copy pathColumnsEditor.tsx
More file actions
104 lines (91 loc) · 3.78 KB
/
ColumnsEditor.tsx
File metadata and controls
104 lines (91 loc) · 3.78 KB
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
import React, { useState, useEffect } from 'react';
import { InlineFormLabel, MultiSelect } from '@grafana/ui';
import { SelectableValue } from '@grafana/data';
import { TableColumn, SelectedColumn } from 'types/queryBuilder';
import labels from 'labels';
import { selectors } from 'selectors';
import { styles } from 'styles';
interface ColumnsEditorProps {
allColumns: readonly TableColumn[];
selectedColumns: SelectedColumn[];
onSelectedColumnsChange: (selectedColumns: SelectedColumn[]) => void;
disabled?: boolean;
showAllOption?: boolean;
}
function getCustomColumns(columnNames: string[], allColumns: readonly TableColumn[]): Array<SelectableValue<string>> {
const columnNamesSet = new Set(columnNames);
return allColumns.filter((c) => columnNamesSet.has(c.name)).map((c) => ({ label: c.label || c.name, value: c.name }));
}
const allColumnName = '*';
export const ColumnsEditor = (props: ColumnsEditorProps) => {
const { allColumns, selectedColumns, onSelectedColumnsChange, disabled, showAllOption } = props;
const [customColumns, setCustomColumns] = useState<Array<SelectableValue<string>>>([]);
const [isOpen, setIsOpen] = useState(false);
const allColumnNames = allColumns.map((c) => ({ label: c.label || c.name, value: c.name }));
if (showAllOption) {
allColumnNames.push({ label: allColumnName, value: allColumnName });
}
const selectedColumnNames = (selectedColumns || []).map((c) => ({ label: c.alias || c.name, value: c.name }));
const { label, tooltip } = labels.components.ColumnsEditor;
const options = [...allColumnNames, ...customColumns];
useEffect(() => {
if (allColumns.length === 0) {
return;
}
const columnNames = selectedColumns.map((c) => c.name);
const customColumns = getCustomColumns(columnNames, allColumns);
setCustomColumns(customColumns);
}, [allColumns, selectedColumns]);
const onChange = (selected: Array<SelectableValue<string>>): void => {
setIsOpen(false);
const selectedColumnNames = new Set<string>(selected.map((s) => s.value!));
const customColumnNames = new Set<string>(customColumns.map((c) => c.value!));
const columnMap = new Map<string, TableColumn>();
const currentColumnMap = new Map<string, SelectedColumn>();
allColumns.forEach((c) => columnMap.set(c.name, c));
selectedColumns.forEach((c) => currentColumnMap.set(c.name, c));
const excludeAllColumn = selectedColumnNames.size > 1;
const nextSelectedColumns: SelectedColumn[] = [];
for (let columnName of selectedColumnNames) {
if (excludeAllColumn && columnName === allColumnName) {
continue;
}
const tableColumn = columnMap.get(columnName);
const existingColumn = currentColumnMap.get(columnName);
if (existingColumn) {
nextSelectedColumns.push(existingColumn);
} else {
nextSelectedColumns.push({
name: columnName,
type: tableColumn?.type || 'String',
custom: customColumnNames.has(columnName),
alias: tableColumn?.label || columnName,
});
}
}
onSelectedColumnsChange(nextSelectedColumns);
};
return (
<div className={styles.Common.flexContainer}>
<InlineFormLabel width={8} className="query-keyword" tooltip={tooltip}>
{label}
</InlineFormLabel>
<div
data-testid={selectors.components.QueryBuilder.ColumnsEditor.multiSelectWrapper}
className={styles.Common.selectWrapper}
>
<MultiSelect<string>
disabled={disabled}
options={options}
value={selectedColumnNames}
isOpen={isOpen}
onOpenMenu={() => setIsOpen(true)}
onCloseMenu={() => setIsOpen(false)}
onChange={onChange}
allowCustomValue={true}
menuPlacement={'bottom'}
/>
</div>
</div>
);
};