add user groups user selector
This commit is contained in:
parent
2ce1ff2e65
commit
a195e09689
5 changed files with 110 additions and 30 deletions
|
|
@ -1,12 +1,14 @@
|
|||
import React, { FC } from 'react';
|
||||
|
||||
import { IconButton, VerticalGroup, HorizontalGroup } from '@grafana/ui';
|
||||
import { IconButton, VerticalGroup, HorizontalGroup, Field, Input, Button } from '@grafana/ui';
|
||||
import cn from 'classnames/bind';
|
||||
import dayjs from 'dayjs';
|
||||
import Draggable from 'react-draggable';
|
||||
|
||||
import Modal from 'components/Modal/Modal';
|
||||
import Text from 'components/Text/Text';
|
||||
import UserGroups from 'components/UserGroups/UserGroups';
|
||||
import { getTzOffsetString } from 'models/timezone/timezone.helpers';
|
||||
|
||||
import styles from './RotationForm.module.css';
|
||||
|
||||
|
|
@ -21,6 +23,8 @@ const cx = cn.bind(styles);
|
|||
const RotationForm: FC<RotationFormProps> = (props) => {
|
||||
const { onHide } = props;
|
||||
|
||||
const moment = dayjs();
|
||||
|
||||
return (
|
||||
<Modal
|
||||
width="400px"
|
||||
|
|
@ -33,16 +37,50 @@ const RotationForm: FC<RotationFormProps> = (props) => {
|
|||
)}
|
||||
>
|
||||
<VerticalGroup>
|
||||
<div className={cx('header')}>
|
||||
<HorizontalGroup justify="space-between">
|
||||
<Text size="medium">Rotation 1</Text>
|
||||
<div className={cx('header-buttons')}>
|
||||
<IconButton className={cx('handle', 'drag-handler')} name="draggabledots" />
|
||||
</div>
|
||||
</div>
|
||||
<HorizontalGroup>
|
||||
<IconButton variant="secondary" tooltip="Copy" name="copy" />
|
||||
<IconButton variant="secondary" tooltip="Code" name="brackets-curly" />
|
||||
<IconButton variant="secondary" tooltip="Delete" name="trash-alt" />
|
||||
<IconButton variant="secondary" className={cx('drag-handler')} name="draggabledots" />
|
||||
</HorizontalGroup>
|
||||
</HorizontalGroup>
|
||||
<UserGroups />
|
||||
{/*<HorizontalGroup justify="end">
|
||||
<Button variant="primary">Create</Button>
|
||||
</HorizontalGroup>*/}
|
||||
<hr />
|
||||
<VerticalGroup>
|
||||
<HorizontalGroup>
|
||||
<Field label="Repeat shifts every">
|
||||
<Input value="1" />
|
||||
</Field>
|
||||
<Field label="">
|
||||
<Input value="days" />
|
||||
</Field>
|
||||
</HorizontalGroup>
|
||||
<HorizontalGroup>
|
||||
<Field label="Shift start">
|
||||
<Input value="12 May, 22 10:00" />
|
||||
</Field>
|
||||
<Field label="Shift end">
|
||||
<Input value="12 May, 22 10:00" />
|
||||
</Field>
|
||||
</HorizontalGroup>
|
||||
<HorizontalGroup>
|
||||
<Field label="Rotation start">
|
||||
<Input value="12 May, 22 10:00" />
|
||||
</Field>
|
||||
<Field label="Rotation end">
|
||||
<Input value="endless" />
|
||||
</Field>
|
||||
</HorizontalGroup>
|
||||
</VerticalGroup>
|
||||
<HorizontalGroup justify="space-between">
|
||||
<Text type="secondary">Timezone: {getTzOffsetString(moment)}</Text>
|
||||
<HorizontalGroup>
|
||||
<Button variant="secondary">+ Override</Button>
|
||||
<Button variant="primary">Create</Button>
|
||||
</HorizontalGroup>
|
||||
</HorizontalGroup>
|
||||
</VerticalGroup>
|
||||
</Modal>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { getRandomTimezone } from '../UsersTimezones/UsersTimezones.helpers';
|
||||
import { getRandomTimezone } from 'components/UsersTimezones/UsersTimezones.helpers';
|
||||
|
||||
export const getRandomGroups = () => {
|
||||
return [
|
||||
|
|
@ -44,21 +44,14 @@ export const toPlainArray = (groups) => {
|
|||
return items;
|
||||
};
|
||||
|
||||
export const fromPlainArray = (
|
||||
items,
|
||||
createNewGroup = false,
|
||||
deleteEmptyGroups = true,
|
||||
) => {
|
||||
export const fromPlainArray = (items, createNewGroup = false, deleteEmptyGroups = true) => {
|
||||
const groups = [];
|
||||
|
||||
return items
|
||||
.reduce((memo, item, currentIndex) => {
|
||||
if (item.type === 'item') {
|
||||
let lastGroup = memo[memo.length - 1];
|
||||
if (
|
||||
!lastGroup ||
|
||||
(createNewGroup && currentIndex === items.length - 1)
|
||||
) {
|
||||
if (!lastGroup || (createNewGroup && currentIndex === items.length - 1)) {
|
||||
lastGroup = [];
|
||||
memo.push(lastGroup);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,3 +82,7 @@
|
|||
cursor: pointer;
|
||||
|
||||
}
|
||||
|
||||
.select{
|
||||
width: 100%;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,16 @@
|
|||
import React, { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import { VerticalGroup, HorizontalGroup, IconButton } from '@grafana/ui';
|
||||
import { SelectableValue } from '@grafana/data';
|
||||
import { VerticalGroup, HorizontalGroup, IconButton, Field, Input } from '@grafana/ui';
|
||||
import { arrayMoveImmutable } from 'array-move';
|
||||
import cn from 'classnames/bind';
|
||||
import { SortableContainer, SortableElement, SortableHandle } from 'react-sortable-hoc';
|
||||
|
||||
import Text from 'components/Text/Text';
|
||||
import GSelect from 'containers/GSelect/GSelect';
|
||||
import UserTooltip from 'containers/UserTooltip/UserTooltip';
|
||||
import { User } from 'models/user/user.types';
|
||||
import { getRandomTimezone } from 'pages/schedule/Schedule.helpers';
|
||||
|
||||
import { fromPlainArray, getRandomGroups, toPlainArray } from './UserGroups.helpers';
|
||||
|
||||
|
|
@ -54,12 +59,38 @@ const SortableList = SortableContainer(({ items, onAddUserGroup }) => {
|
|||
});
|
||||
|
||||
const UserGroups = () => {
|
||||
const [groups, setGroups] = useState(getRandomGroups());
|
||||
const [groups, setGroups] = useState([[]]);
|
||||
|
||||
const handleAddUserGroup = useCallback(() => {
|
||||
setGroups((oldGroups) => [...oldGroups, []]);
|
||||
}, [groups]);
|
||||
|
||||
const handleUserAdd = useCallback((pk: User['pk'], user: User) => {
|
||||
if (!pk) {
|
||||
return;
|
||||
}
|
||||
|
||||
setGroups((groups) => {
|
||||
const newGroups = [...groups];
|
||||
const lastGroup = newGroups[groups.length - 1];
|
||||
|
||||
lastGroup.push({ pk, name: user.username, tz: getRandomTimezone() });
|
||||
|
||||
return newGroups;
|
||||
});
|
||||
}, []);
|
||||
|
||||
const filterUsers = useCallback(
|
||||
({ value }) => {
|
||||
const userAlreadyExist = groups.some((group) => group.some((user) => user.pk === value));
|
||||
|
||||
console.log('userAlreadyExist', userAlreadyExist);
|
||||
|
||||
return !userAlreadyExist;
|
||||
},
|
||||
[groups]
|
||||
);
|
||||
|
||||
const items = useMemo(() => toPlainArray(groups), [groups]);
|
||||
|
||||
const onSortEnd = useCallback(
|
||||
|
|
@ -83,9 +114,19 @@ const UserGroups = () => {
|
|||
onAddUserGroup={handleAddUserGroup}
|
||||
//useDragHandle
|
||||
/>
|
||||
{/* <div className={cx('add-user-group')} onClick={handleAddUserGroup}>
|
||||
Add user group +
|
||||
</div>*/}
|
||||
<GSelect
|
||||
showSearch
|
||||
allowClear
|
||||
modelName="userStore"
|
||||
displayField="username"
|
||||
valueField="pk"
|
||||
placeholder="Add user"
|
||||
className={cx('select')}
|
||||
value={null}
|
||||
onChange={handleUserAdd}
|
||||
getOptionLabel={({ label, value }: SelectableValue) => <UserTooltip id={value} />}
|
||||
filterOptions={filterUsers}
|
||||
/>
|
||||
</VerticalGroup>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ interface GSelectProps {
|
|||
dropdownRender?: (menu: ReactElement) => ReactElement;
|
||||
getOptionLabel?: <T>(item: SelectableValue<T>) => React.ReactNode;
|
||||
getDescription?: (item: any) => React.ReactNode;
|
||||
filterOptions?: () => boolean;
|
||||
}
|
||||
|
||||
const GSelect = observer((props: GSelectProps) => {
|
||||
|
|
@ -59,6 +60,7 @@ const GSelect = observer((props: GSelectProps) => {
|
|||
getOptionLabel,
|
||||
showWarningIfEmptyValue = false,
|
||||
getDescription,
|
||||
filterOptions = () => true,
|
||||
} = props;
|
||||
|
||||
const store = useStore();
|
||||
|
|
@ -91,12 +93,14 @@ const GSelect = observer((props: GSelectProps) => {
|
|||
const searchResult = model.getSearchResult(query);
|
||||
const items = Array.isArray(searchResult.results) ? searchResult.results : searchResult;
|
||||
|
||||
const options = items.map((item: any) => ({
|
||||
value: item[valueField],
|
||||
label: get(item, displayField),
|
||||
imgUrl: item.avatar_url,
|
||||
description: getDescription && getDescription(item),
|
||||
}));
|
||||
const options = items
|
||||
.map((item: any) => ({
|
||||
value: item[valueField],
|
||||
label: get(item, displayField),
|
||||
imgUrl: item.avatar_url,
|
||||
description: getDescription && getDescription(item),
|
||||
}))
|
||||
.filter(filterOptions);
|
||||
return options;
|
||||
});
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue