Skip to content

Commit

Permalink
Feat: multi option select when picker.multi is true #24
Browse files Browse the repository at this point in the history
  • Loading branch information
luckylooky2 committed May 31, 2024
1 parent 25cbc01 commit 63cee62
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 15 deletions.
126 changes: 126 additions & 0 deletions public/app/features/dashboard/containers/MultiOptionDropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import { css, cx } from '@emotion/css';
import React, { useEffect, useState } from 'react';

import { GrafanaTheme2 } from '@grafana/data';
import { VariableOption } from '@grafana/data/src/types/templateVars';
import { reportInteraction } from '@grafana/runtime';
import { Menu, Dropdown, useStyles2, ToolbarButton, Icon } from '@grafana/ui';
import { useDashboardList } from 'app/features/browse-dashboards/state';

import { GitHubButtonStyles } from '../../../../style/GitHubButtonStyles';

interface Props {
values: VariableOption[];
selectedValues: VariableOption[];
onToggle: (option: VariableOption, clearOthers: boolean) => void;
showOptions: () => void;
}

const OptionDropdown = ({ values, onToggle, selectedValues, showOptions }: Props) => {
const [isOpen, setIsOpen] = useState(false);
const gitHubButtonStyles = useStyles2(GitHubButtonStyles);
const styles = useStyles2(getStyles);
const dashboardList = useDashboardList();
const isValid = dashboardList !== undefined;
const subCaterogyName = function (title: string | null) {
switch (title) {
default:
return 'namespace';
}
};

const handleOnToggle = (option: VariableOption) => (event: React.MouseEvent<HTMLButtonElement>) => {
const clearOthers = event.shiftKey || event.ctrlKey || event.metaKey;
event.preventDefault();
event.stopPropagation();
onToggle(option, clearOthers);
};

// 1. 현재 대시보드 uid 가져오기
const currDashboard =
isValid && dashboardList.length
? dashboardList.filter((v) => v.uid === window.location.pathname.split('/')[2])[0]
: { kind: '', uid: '', title: '', url: '' };

const createActions = values.map((value, index) => ({
id: index,
text: value.text as string, // can't be string[] due to disabled multi-select
icon: 'plus',
url: `/d/${currDashboard.uid}/${currDashboard.title}?var-${subCaterogyName(currDashboard.title)}=${value.text}`,
hideFromTabs: true,
isCreateAction: true,
option: value,
}));

// 2. 현재 체크된 것 가져오기
const check = (selectedValues: VariableOption[], title: string) => {
for (const value of selectedValues) {
if (value.text === title) {
return true;
}
}
return false;
};

useEffect(() => {
showOptions();
}, [showOptions]);

const MenuActions = () => {
return (
<Menu>
{createActions.map((createAction, index) => (
<Menu.Item
key={index}
label={createAction.text}
checkType={true}
isChecked={check(selectedValues, createAction.text)}
onClick={handleOnToggle(createAction.option)}
/>
))}
</Menu>
);
};

return (
<Dropdown overlay={MenuActions} placement="bottom-start" onVisibleChange={setIsOpen}>
<ToolbarButton
isOpen={isOpen}
className={cx(gitHubButtonStyles.button, gitHubButtonStyles.greenButton, styles.button)}
aria-label="New"
>
<div className={styles.ellipsis}>
<div>
<Icon name="filter" />
</div>
<div className={styles.text}>multi-select</div>
</div>
</ToolbarButton>
</Dropdown>
);
};

const getStyles = (theme: GrafanaTheme2) => ({
buttonContent: css({
alignItems: 'center',
display: 'flex',
}),
buttonText: css({
[theme.breakpoints.down('md')]: {
display: 'none',
},
}),
ellipsis: css({
display: 'flex',
maxWidth: '200px',
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis',
}),
button: css({ maxWidth: '200px' }),
text: css({
paddingLeft: '10px',
}),
});

export default OptionDropdown;
13 changes: 6 additions & 7 deletions public/app/features/dashboard/containers/OptionDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@ import { useDashboardList } from 'app/features/browse-dashboards/state';
import { GitHubButtonStyles } from '../../../../style/GitHubButtonStyles';

interface Props {
// picker: OptionsPickerState;
options: VariableOption[];
values: VariableOption[];
}

const OptionDropdown = ({ options }: Props) => {
const OptionDropdown = ({ values }: Props) => {
const [isOpen, setIsOpen] = useState(false);
const gitHubButtonStyles = useStyles2(GitHubButtonStyles);
const styles = useStyles2(getStyles);
Expand All @@ -34,16 +33,16 @@ const OptionDropdown = ({ options }: Props) => {
? dashboardList.filter((v) => v.uid === window.location.pathname.split('/')[2])[0]
: { kind: '', uid: '', title: '', url: '' };

const createActions = options.map((option, index) => ({
const createActions = values.map((value, index) => ({
id: index,
text: option.text as string, // can't be string[] due to disabled multi-select
text: value.text as string, // can't be string[] due to disabled multi-select
icon: 'plus',
url: `/d/${currDashboard.uid}/${currDashboard.title}?var-${subCaterogyName(currDashboard.title)}=${option.text}`,
url: `/d/${currDashboard.uid}/${currDashboard.title}?var-${subCaterogyName(currDashboard.title)}=${value.text}`,
hideFromTabs: true,
isCreateAction: true,
}));
// 2. 현재 체크된 것 가져오기
const currSubCategory = options.filter((v) => v.selected === true)[0].text;
const currSubCategory = values.filter((v) => v.selected === true)[0].text;

const MenuActions = () => {
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { bindActionCreators } from 'redux';

import { LoadingState } from '@grafana/data';
import { ClickOutsideWrapper } from '@grafana/ui';
import MultiOptionDropdown from 'app/features/dashboard/containers/MultiOptionDropdown';
import OptionDropdown from 'app/features/dashboard/containers/OptionDropdown';
import { StoreState, ThunkDispatch } from 'app/types';

Expand Down Expand Up @@ -111,16 +112,30 @@ export const optionPickerFactory = <Model extends VariableWithOptions | Variable
};

render() {
const { variable } = this.props;

// const { variable, picker } = this.props;
// const showOptions = picker.id === variable.id; // true: dropdown 열림(picker), false: dropdown 닫힘(variable)
const { variable, picker } = this.props;
const showOptions = picker.id === variable.id; // true: dropdown 열림(picker), false: dropdown 닫힘(variable)

return (
<div className="variable-link-wrapper">
<OptionDropdown options={variable.options} />
{/* {showOptions ? this.renderOptions(picker) : this.renderLink(variable)} */}
</div>
<>
<div className="variable-link-wrapper">
{picker.multi ? (
<MultiOptionDropdown
values={variable.options}
onToggle={this.onToggleOption}
selectedValues={picker.selectedValues}
showOptions={this.onShowOptions}
/>
) : (
<OptionDropdown values={variable.options} />
)}
{/* {showOptions ? this.renderOptions(picker) : this.renderLink(variable)} */}
</div>
<div>
{picker.selectedValues.map((v, i) => (
<div key={`${v.text} ${i}`}>{v.text}</div>
))}
</div>
</>
);
}

Expand Down

0 comments on commit 63cee62

Please sign in to comment.