support setting mode and stickiness in new project form (#6972)
This PR is a combination of two PRs:
This PR adds a functioning environment selection button to the new project creation form. Selected environments are added to the payload and to the API preview.
The implementation is mostly lifted from the existing FilterItem component we have for search filters. However, our need here is less complex, so I've removed some of the things we don't need. There is still more cleanup to be done, however, but I'd like to implement the rest of the submenus first, to see what we really do need in the end.
---
This PR adds support for stickiness and project mode in the new project
creation form.
Achieve this, it does a few things:
1. Moves `resolveStickinessOptions` from
`frontend/src/component/feature/StrategyTypes/FlexibleStrategy/StickinessSelect/StickinessSelect.tsx`
and into a separate hook. This component was used by the old project
creation form. Because the new form has a different input, but needs the
same option, moved that code into a reusable hook.
2. It adds functioning buttons for project stickiness and mode.
3. It adds labels to the search inputs for the dropdowns. Inputs *must*
have labels to meet a11y requirements. However, the designs don't have
labels, so we can hide them visually. Though that leads to another issue
(refer to the screen shot below).
4. It updates the `SelectionButton` component to handle both single- and
multiselect cases. It instead exports these two subcomponents. These are
currently in one file, but I'll split them out into their separate files
in a later PR.
As a side effect of working with the selection buttons, it also improves
how we handle keyboard interaction for these buttons.
Here's what it looks like for single-select lists. Notice the missing
part of the input's border around the top (where the label *would* be if
we showed it). We should figure out how best to handle it. I've done
like this for now, but we can sort it out later.
![image](https://github.com/Unleash/unleash/assets/17786332/5af979c2-6635-481e-8d3e-5aad1c0ab46f)
2024-05-03 07:27:13 +02:00
|
|
|
import Search from '@mui/icons-material/Search';
|
|
|
|
import { Box, Button, InputAdornment, List, ListItemText } from '@mui/material';
|
feat: configure CRs when creating projects (#6979)
This PR adds the ability to configure CRs when creating a project.
The design is unfinished, and the code certainly needs cleanup, but I'd
like to get this into sandbox so we can look at it.
Things that still need to be done:
1. What do we do about this button when the user has no environments
selected? As a rough draft, I've disabled it. However, we should make it
possible to navigate to and give you an explanation why it was disabled,
e.g. "You have no project environments selected. Please select at least
one project environment.".
2. The form design is not done: the width should be constant and not
jumpy the way it is now. Also, the search field is too wide.
3. I've made the desicion that if you deselect a project env, we also
remove that env from your CR config it it's in there.
4. Potential improvement: if you enable and then disable CRs for an env,
we *could* probably store the data in between, so that if you set
required approvers 5 and then disabled it, it'd still be 5 when you
re-enabled it. That sounds like a good user experience. We should also
be able to extend that to adding/removing environments from project
envs.
2024-05-07 08:14:28 +02:00
|
|
|
import { type FC, type ReactNode, useRef, useState, useMemo } from 'react';
|
support setting mode and stickiness in new project form (#6972)
This PR is a combination of two PRs:
This PR adds a functioning environment selection button to the new project creation form. Selected environments are added to the payload and to the API preview.
The implementation is mostly lifted from the existing FilterItem component we have for search filters. However, our need here is less complex, so I've removed some of the things we don't need. There is still more cleanup to be done, however, but I'd like to implement the rest of the submenus first, to see what we really do need in the end.
---
This PR adds support for stickiness and project mode in the new project
creation form.
Achieve this, it does a few things:
1. Moves `resolveStickinessOptions` from
`frontend/src/component/feature/StrategyTypes/FlexibleStrategy/StickinessSelect/StickinessSelect.tsx`
and into a separate hook. This component was used by the old project
creation form. Because the new form has a different input, but needs the
same option, moved that code into a reusable hook.
2. It adds functioning buttons for project stickiness and mode.
3. It adds labels to the search inputs for the dropdowns. Inputs *must*
have labels to meet a11y requirements. However, the designs don't have
labels, so we can hide them visually. Though that leads to another issue
(refer to the screen shot below).
4. It updates the `SelectionButton` component to handle both single- and
multiselect cases. It instead exports these two subcomponents. These are
currently in one file, but I'll split them out into their separate files
in a later PR.
As a side effect of working with the selection buttons, it also improves
how we handle keyboard interaction for these buttons.
Here's what it looks like for single-select lists. Notice the missing
part of the input's border around the top (where the label *would* be if
we showed it). We should figure out how best to handle it. I've done
like this for now, but we can sort it out later.
![image](https://github.com/Unleash/unleash/assets/17786332/5af979c2-6635-481e-8d3e-5aad1c0ab46f)
2024-05-03 07:27:13 +02:00
|
|
|
import {
|
|
|
|
StyledCheckbox,
|
|
|
|
StyledDropdown,
|
|
|
|
StyledListItem,
|
|
|
|
StyledPopover,
|
|
|
|
StyledTextField,
|
feat: configure CRs when creating projects (#6979)
This PR adds the ability to configure CRs when creating a project.
The design is unfinished, and the code certainly needs cleanup, but I'd
like to get this into sandbox so we can look at it.
Things that still need to be done:
1. What do we do about this button when the user has no environments
selected? As a rough draft, I've disabled it. However, we should make it
possible to navigate to and give you an explanation why it was disabled,
e.g. "You have no project environments selected. Please select at least
one project environment.".
2. The form design is not done: the width should be constant and not
jumpy the way it is now. Also, the search field is too wide.
3. I've made the desicion that if you deselect a project env, we also
remove that env from your CR config it it's in there.
4. Potential improvement: if you enable and then disable CRs for an env,
we *could* probably store the data in between, so that if you set
required approvers 5 and then disabled it, it'd still be 5 when you
re-enabled it. That sounds like a good user experience. We should also
be able to extend that to adding/removing environments from project
envs.
2024-05-07 08:14:28 +02:00
|
|
|
TableSearchInput,
|
support setting mode and stickiness in new project form (#6972)
This PR is a combination of two PRs:
This PR adds a functioning environment selection button to the new project creation form. Selected environments are added to the payload and to the API preview.
The implementation is mostly lifted from the existing FilterItem component we have for search filters. However, our need here is less complex, so I've removed some of the things we don't need. There is still more cleanup to be done, however, but I'd like to implement the rest of the submenus first, to see what we really do need in the end.
---
This PR adds support for stickiness and project mode in the new project
creation form.
Achieve this, it does a few things:
1. Moves `resolveStickinessOptions` from
`frontend/src/component/feature/StrategyTypes/FlexibleStrategy/StickinessSelect/StickinessSelect.tsx`
and into a separate hook. This component was used by the old project
creation form. Because the new form has a different input, but needs the
same option, moved that code into a reusable hook.
2. It adds functioning buttons for project stickiness and mode.
3. It adds labels to the search inputs for the dropdowns. Inputs *must*
have labels to meet a11y requirements. However, the designs don't have
labels, so we can hide them visually. Though that leads to another issue
(refer to the screen shot below).
4. It updates the `SelectionButton` component to handle both single- and
multiselect cases. It instead exports these two subcomponents. These are
currently in one file, but I'll split them out into their separate files
in a later PR.
As a side effect of working with the selection buttons, it also improves
how we handle keyboard interaction for these buttons.
Here's what it looks like for single-select lists. Notice the missing
part of the input's border around the top (where the label *would* be if
we showed it). We should figure out how best to handle it. I've done
like this for now, but we can sort it out later.
![image](https://github.com/Unleash/unleash/assets/17786332/5af979c2-6635-481e-8d3e-5aad1c0ab46f)
2024-05-03 07:27:13 +02:00
|
|
|
} from './SelectionButton.styles';
|
feat: configure CRs when creating projects (#6979)
This PR adds the ability to configure CRs when creating a project.
The design is unfinished, and the code certainly needs cleanup, but I'd
like to get this into sandbox so we can look at it.
Things that still need to be done:
1. What do we do about this button when the user has no environments
selected? As a rough draft, I've disabled it. However, we should make it
possible to navigate to and give you an explanation why it was disabled,
e.g. "You have no project environments selected. Please select at least
one project environment.".
2. The form design is not done: the width should be constant and not
jumpy the way it is now. Also, the search field is too wide.
3. I've made the desicion that if you deselect a project env, we also
remove that env from your CR config it it's in there.
4. Potential improvement: if you enable and then disable CRs for an env,
we *could* probably store the data in between, so that if you set
required approvers 5 and then disabled it, it'd still be 5 when you
re-enabled it. That sounds like a good user experience. We should also
be able to extend that to adding/removing environments from project
envs.
2024-05-07 08:14:28 +02:00
|
|
|
import { ChangeRequestTable } from './ChangeRequestTable';
|
support setting mode and stickiness in new project form (#6972)
This PR is a combination of two PRs:
This PR adds a functioning environment selection button to the new project creation form. Selected environments are added to the payload and to the API preview.
The implementation is mostly lifted from the existing FilterItem component we have for search filters. However, our need here is less complex, so I've removed some of the things we don't need. There is still more cleanup to be done, however, but I'd like to implement the rest of the submenus first, to see what we really do need in the end.
---
This PR adds support for stickiness and project mode in the new project
creation form.
Achieve this, it does a few things:
1. Moves `resolveStickinessOptions` from
`frontend/src/component/feature/StrategyTypes/FlexibleStrategy/StickinessSelect/StickinessSelect.tsx`
and into a separate hook. This component was used by the old project
creation form. Because the new form has a different input, but needs the
same option, moved that code into a reusable hook.
2. It adds functioning buttons for project stickiness and mode.
3. It adds labels to the search inputs for the dropdowns. Inputs *must*
have labels to meet a11y requirements. However, the designs don't have
labels, so we can hide them visually. Though that leads to another issue
(refer to the screen shot below).
4. It updates the `SelectionButton` component to handle both single- and
multiselect cases. It instead exports these two subcomponents. These are
currently in one file, but I'll split them out into their separate files
in a later PR.
As a side effect of working with the selection buttons, it also improves
how we handle keyboard interaction for these buttons.
Here's what it looks like for single-select lists. Notice the missing
part of the input's border around the top (where the label *would* be if
we showed it). We should figure out how best to handle it. I've done
like this for now, but we can sort it out later.
![image](https://github.com/Unleash/unleash/assets/17786332/5af979c2-6635-481e-8d3e-5aad1c0ab46f)
2024-05-03 07:27:13 +02:00
|
|
|
|
|
|
|
export interface IFilterItemProps {
|
|
|
|
label: ReactNode;
|
|
|
|
options: Array<{ label: string; value: string }>;
|
|
|
|
selectedOptions: Set<string>;
|
|
|
|
onChange: (values: Set<string>) => void;
|
|
|
|
}
|
|
|
|
|
|
|
|
export type FilterItemParams = {
|
|
|
|
operator: string;
|
|
|
|
values: string[];
|
|
|
|
};
|
|
|
|
|
|
|
|
interface UseSelectionManagementProps {
|
|
|
|
handleToggle: (value: string) => () => void;
|
|
|
|
}
|
|
|
|
|
|
|
|
const useSelectionManagement = ({
|
|
|
|
handleToggle,
|
|
|
|
}: UseSelectionManagementProps) => {
|
|
|
|
const listRefs = useRef<Array<HTMLInputElement | HTMLLIElement | null>>([]);
|
|
|
|
|
|
|
|
const handleSelection = (
|
|
|
|
event: React.KeyboardEvent,
|
|
|
|
index: number,
|
|
|
|
filteredOptions: { label: string; value: string }[],
|
|
|
|
) => {
|
|
|
|
// we have to be careful not to prevent other keys e.g tab
|
|
|
|
if (event.key === 'ArrowDown' && index < listRefs.current.length - 1) {
|
|
|
|
event.preventDefault();
|
|
|
|
listRefs.current[index + 1]?.focus();
|
|
|
|
} else if (event.key === 'ArrowUp' && index > 0) {
|
|
|
|
event.preventDefault();
|
|
|
|
listRefs.current[index - 1]?.focus();
|
|
|
|
} else if (
|
|
|
|
event.key === 'Enter' &&
|
|
|
|
index === 0 &&
|
|
|
|
listRefs.current[0]?.value &&
|
|
|
|
filteredOptions.length > 0
|
|
|
|
) {
|
|
|
|
// if the search field is not empty and the user presses
|
|
|
|
// enter from the search field, toggle the topmost item in
|
|
|
|
// the filtered list event.preventDefault();
|
|
|
|
handleToggle(filteredOptions[0].value)();
|
|
|
|
} else if (
|
|
|
|
event.key === 'Enter' ||
|
|
|
|
// allow selection with space when not in the search field
|
|
|
|
(index !== 0 && event.key === ' ')
|
|
|
|
) {
|
|
|
|
event.preventDefault();
|
|
|
|
if (index > 0) {
|
|
|
|
const listItemIndex = index - 1;
|
|
|
|
handleToggle(filteredOptions[listItemIndex].value)();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
return { listRefs, handleSelection };
|
|
|
|
};
|
|
|
|
|
|
|
|
type CombinedSelectProps = {
|
|
|
|
options: Array<{ label: string; value: string }>;
|
|
|
|
onChange: (value: string) => void;
|
|
|
|
button: { label: string; icon: ReactNode };
|
|
|
|
search: {
|
|
|
|
label: string;
|
|
|
|
placeholder: string;
|
|
|
|
};
|
|
|
|
multiselect?: { selectedOptions: Set<string> };
|
2024-05-07 08:56:53 +02:00
|
|
|
onOpen?: () => void;
|
|
|
|
onClose?: () => void;
|
support setting mode and stickiness in new project form (#6972)
This PR is a combination of two PRs:
This PR adds a functioning environment selection button to the new project creation form. Selected environments are added to the payload and to the API preview.
The implementation is mostly lifted from the existing FilterItem component we have for search filters. However, our need here is less complex, so I've removed some of the things we don't need. There is still more cleanup to be done, however, but I'd like to implement the rest of the submenus first, to see what we really do need in the end.
---
This PR adds support for stickiness and project mode in the new project
creation form.
Achieve this, it does a few things:
1. Moves `resolveStickinessOptions` from
`frontend/src/component/feature/StrategyTypes/FlexibleStrategy/StickinessSelect/StickinessSelect.tsx`
and into a separate hook. This component was used by the old project
creation form. Because the new form has a different input, but needs the
same option, moved that code into a reusable hook.
2. It adds functioning buttons for project stickiness and mode.
3. It adds labels to the search inputs for the dropdowns. Inputs *must*
have labels to meet a11y requirements. However, the designs don't have
labels, so we can hide them visually. Though that leads to another issue
(refer to the screen shot below).
4. It updates the `SelectionButton` component to handle both single- and
multiselect cases. It instead exports these two subcomponents. These are
currently in one file, but I'll split them out into their separate files
in a later PR.
As a side effect of working with the selection buttons, it also improves
how we handle keyboard interaction for these buttons.
Here's what it looks like for single-select lists. Notice the missing
part of the input's border around the top (where the label *would* be if
we showed it). We should figure out how best to handle it. I've done
like this for now, but we can sort it out later.
![image](https://github.com/Unleash/unleash/assets/17786332/5af979c2-6635-481e-8d3e-5aad1c0ab46f)
2024-05-03 07:27:13 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
const CombinedSelect: FC<CombinedSelectProps> = ({
|
|
|
|
options,
|
|
|
|
onChange,
|
|
|
|
button,
|
|
|
|
search,
|
|
|
|
multiselect,
|
2024-05-07 08:56:53 +02:00
|
|
|
onOpen = () => {},
|
|
|
|
onClose = () => {},
|
support setting mode and stickiness in new project form (#6972)
This PR is a combination of two PRs:
This PR adds a functioning environment selection button to the new project creation form. Selected environments are added to the payload and to the API preview.
The implementation is mostly lifted from the existing FilterItem component we have for search filters. However, our need here is less complex, so I've removed some of the things we don't need. There is still more cleanup to be done, however, but I'd like to implement the rest of the submenus first, to see what we really do need in the end.
---
This PR adds support for stickiness and project mode in the new project
creation form.
Achieve this, it does a few things:
1. Moves `resolveStickinessOptions` from
`frontend/src/component/feature/StrategyTypes/FlexibleStrategy/StickinessSelect/StickinessSelect.tsx`
and into a separate hook. This component was used by the old project
creation form. Because the new form has a different input, but needs the
same option, moved that code into a reusable hook.
2. It adds functioning buttons for project stickiness and mode.
3. It adds labels to the search inputs for the dropdowns. Inputs *must*
have labels to meet a11y requirements. However, the designs don't have
labels, so we can hide them visually. Though that leads to another issue
(refer to the screen shot below).
4. It updates the `SelectionButton` component to handle both single- and
multiselect cases. It instead exports these two subcomponents. These are
currently in one file, but I'll split them out into their separate files
in a later PR.
As a side effect of working with the selection buttons, it also improves
how we handle keyboard interaction for these buttons.
Here's what it looks like for single-select lists. Notice the missing
part of the input's border around the top (where the label *would* be if
we showed it). We should figure out how best to handle it. I've done
like this for now, but we can sort it out later.
![image](https://github.com/Unleash/unleash/assets/17786332/5af979c2-6635-481e-8d3e-5aad1c0ab46f)
2024-05-03 07:27:13 +02:00
|
|
|
}) => {
|
|
|
|
const ref = useRef<HTMLDivElement>(null);
|
|
|
|
const [anchorEl, setAnchorEl] = useState<HTMLDivElement | null>();
|
|
|
|
const [searchText, setSearchText] = useState('');
|
|
|
|
|
|
|
|
const open = () => {
|
|
|
|
setSearchText('');
|
|
|
|
setAnchorEl(ref.current);
|
2024-05-07 08:56:53 +02:00
|
|
|
onOpen();
|
support setting mode and stickiness in new project form (#6972)
This PR is a combination of two PRs:
This PR adds a functioning environment selection button to the new project creation form. Selected environments are added to the payload and to the API preview.
The implementation is mostly lifted from the existing FilterItem component we have for search filters. However, our need here is less complex, so I've removed some of the things we don't need. There is still more cleanup to be done, however, but I'd like to implement the rest of the submenus first, to see what we really do need in the end.
---
This PR adds support for stickiness and project mode in the new project
creation form.
Achieve this, it does a few things:
1. Moves `resolveStickinessOptions` from
`frontend/src/component/feature/StrategyTypes/FlexibleStrategy/StickinessSelect/StickinessSelect.tsx`
and into a separate hook. This component was used by the old project
creation form. Because the new form has a different input, but needs the
same option, moved that code into a reusable hook.
2. It adds functioning buttons for project stickiness and mode.
3. It adds labels to the search inputs for the dropdowns. Inputs *must*
have labels to meet a11y requirements. However, the designs don't have
labels, so we can hide them visually. Though that leads to another issue
(refer to the screen shot below).
4. It updates the `SelectionButton` component to handle both single- and
multiselect cases. It instead exports these two subcomponents. These are
currently in one file, but I'll split them out into their separate files
in a later PR.
As a side effect of working with the selection buttons, it also improves
how we handle keyboard interaction for these buttons.
Here's what it looks like for single-select lists. Notice the missing
part of the input's border around the top (where the label *would* be if
we showed it). We should figure out how best to handle it. I've done
like this for now, but we can sort it out later.
![image](https://github.com/Unleash/unleash/assets/17786332/5af979c2-6635-481e-8d3e-5aad1c0ab46f)
2024-05-03 07:27:13 +02:00
|
|
|
};
|
|
|
|
|
2024-05-07 08:56:53 +02:00
|
|
|
const handleClose = () => {
|
support setting mode and stickiness in new project form (#6972)
This PR is a combination of two PRs:
This PR adds a functioning environment selection button to the new project creation form. Selected environments are added to the payload and to the API preview.
The implementation is mostly lifted from the existing FilterItem component we have for search filters. However, our need here is less complex, so I've removed some of the things we don't need. There is still more cleanup to be done, however, but I'd like to implement the rest of the submenus first, to see what we really do need in the end.
---
This PR adds support for stickiness and project mode in the new project
creation form.
Achieve this, it does a few things:
1. Moves `resolveStickinessOptions` from
`frontend/src/component/feature/StrategyTypes/FlexibleStrategy/StickinessSelect/StickinessSelect.tsx`
and into a separate hook. This component was used by the old project
creation form. Because the new form has a different input, but needs the
same option, moved that code into a reusable hook.
2. It adds functioning buttons for project stickiness and mode.
3. It adds labels to the search inputs for the dropdowns. Inputs *must*
have labels to meet a11y requirements. However, the designs don't have
labels, so we can hide them visually. Though that leads to another issue
(refer to the screen shot below).
4. It updates the `SelectionButton` component to handle both single- and
multiselect cases. It instead exports these two subcomponents. These are
currently in one file, but I'll split them out into their separate files
in a later PR.
As a side effect of working with the selection buttons, it also improves
how we handle keyboard interaction for these buttons.
Here's what it looks like for single-select lists. Notice the missing
part of the input's border around the top (where the label *would* be if
we showed it). We should figure out how best to handle it. I've done
like this for now, but we can sort it out later.
![image](https://github.com/Unleash/unleash/assets/17786332/5af979c2-6635-481e-8d3e-5aad1c0ab46f)
2024-05-03 07:27:13 +02:00
|
|
|
setAnchorEl(null);
|
2024-05-07 08:56:53 +02:00
|
|
|
onClose();
|
support setting mode and stickiness in new project form (#6972)
This PR is a combination of two PRs:
This PR adds a functioning environment selection button to the new project creation form. Selected environments are added to the payload and to the API preview.
The implementation is mostly lifted from the existing FilterItem component we have for search filters. However, our need here is less complex, so I've removed some of the things we don't need. There is still more cleanup to be done, however, but I'd like to implement the rest of the submenus first, to see what we really do need in the end.
---
This PR adds support for stickiness and project mode in the new project
creation form.
Achieve this, it does a few things:
1. Moves `resolveStickinessOptions` from
`frontend/src/component/feature/StrategyTypes/FlexibleStrategy/StickinessSelect/StickinessSelect.tsx`
and into a separate hook. This component was used by the old project
creation form. Because the new form has a different input, but needs the
same option, moved that code into a reusable hook.
2. It adds functioning buttons for project stickiness and mode.
3. It adds labels to the search inputs for the dropdowns. Inputs *must*
have labels to meet a11y requirements. However, the designs don't have
labels, so we can hide them visually. Though that leads to another issue
(refer to the screen shot below).
4. It updates the `SelectionButton` component to handle both single- and
multiselect cases. It instead exports these two subcomponents. These are
currently in one file, but I'll split them out into their separate files
in a later PR.
As a side effect of working with the selection buttons, it also improves
how we handle keyboard interaction for these buttons.
Here's what it looks like for single-select lists. Notice the missing
part of the input's border around the top (where the label *would* be if
we showed it). We should figure out how best to handle it. I've done
like this for now, but we can sort it out later.
![image](https://github.com/Unleash/unleash/assets/17786332/5af979c2-6635-481e-8d3e-5aad1c0ab46f)
2024-05-03 07:27:13 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
const onSelection = (selected: string) => {
|
|
|
|
onChange(selected);
|
|
|
|
if (!multiselect) {
|
2024-05-07 08:56:53 +02:00
|
|
|
handleClose();
|
support setting mode and stickiness in new project form (#6972)
This PR is a combination of two PRs:
This PR adds a functioning environment selection button to the new project creation form. Selected environments are added to the payload and to the API preview.
The implementation is mostly lifted from the existing FilterItem component we have for search filters. However, our need here is less complex, so I've removed some of the things we don't need. There is still more cleanup to be done, however, but I'd like to implement the rest of the submenus first, to see what we really do need in the end.
---
This PR adds support for stickiness and project mode in the new project
creation form.
Achieve this, it does a few things:
1. Moves `resolveStickinessOptions` from
`frontend/src/component/feature/StrategyTypes/FlexibleStrategy/StickinessSelect/StickinessSelect.tsx`
and into a separate hook. This component was used by the old project
creation form. Because the new form has a different input, but needs the
same option, moved that code into a reusable hook.
2. It adds functioning buttons for project stickiness and mode.
3. It adds labels to the search inputs for the dropdowns. Inputs *must*
have labels to meet a11y requirements. However, the designs don't have
labels, so we can hide them visually. Though that leads to another issue
(refer to the screen shot below).
4. It updates the `SelectionButton` component to handle both single- and
multiselect cases. It instead exports these two subcomponents. These are
currently in one file, but I'll split them out into their separate files
in a later PR.
As a side effect of working with the selection buttons, it also improves
how we handle keyboard interaction for these buttons.
Here's what it looks like for single-select lists. Notice the missing
part of the input's border around the top (where the label *would* be if
we showed it). We should figure out how best to handle it. I've done
like this for now, but we can sort it out later.
![image](https://github.com/Unleash/unleash/assets/17786332/5af979c2-6635-481e-8d3e-5aad1c0ab46f)
2024-05-03 07:27:13 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const { listRefs, handleSelection } = useSelectionManagement({
|
|
|
|
handleToggle: (selected: string) => () => onSelection(selected),
|
|
|
|
});
|
|
|
|
|
|
|
|
const filteredOptions = options?.filter((option) =>
|
|
|
|
option.label.toLowerCase().includes(searchText.toLowerCase()),
|
|
|
|
);
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<Box ref={ref}>
|
|
|
|
<Button
|
|
|
|
variant='outlined'
|
|
|
|
color='primary'
|
|
|
|
startIcon={button.icon}
|
|
|
|
onClick={() => {
|
|
|
|
// todo: find out why this is clicked when you
|
|
|
|
// press enter in the search bar (only in
|
|
|
|
// single-select mode)
|
|
|
|
open();
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
{button.label}
|
|
|
|
</Button>
|
|
|
|
</Box>
|
|
|
|
<StyledPopover
|
|
|
|
open={Boolean(anchorEl)}
|
|
|
|
anchorEl={anchorEl}
|
2024-05-07 08:56:53 +02:00
|
|
|
onClose={handleClose}
|
support setting mode and stickiness in new project form (#6972)
This PR is a combination of two PRs:
This PR adds a functioning environment selection button to the new project creation form. Selected environments are added to the payload and to the API preview.
The implementation is mostly lifted from the existing FilterItem component we have for search filters. However, our need here is less complex, so I've removed some of the things we don't need. There is still more cleanup to be done, however, but I'd like to implement the rest of the submenus first, to see what we really do need in the end.
---
This PR adds support for stickiness and project mode in the new project
creation form.
Achieve this, it does a few things:
1. Moves `resolveStickinessOptions` from
`frontend/src/component/feature/StrategyTypes/FlexibleStrategy/StickinessSelect/StickinessSelect.tsx`
and into a separate hook. This component was used by the old project
creation form. Because the new form has a different input, but needs the
same option, moved that code into a reusable hook.
2. It adds functioning buttons for project stickiness and mode.
3. It adds labels to the search inputs for the dropdowns. Inputs *must*
have labels to meet a11y requirements. However, the designs don't have
labels, so we can hide them visually. Though that leads to another issue
(refer to the screen shot below).
4. It updates the `SelectionButton` component to handle both single- and
multiselect cases. It instead exports these two subcomponents. These are
currently in one file, but I'll split them out into their separate files
in a later PR.
As a side effect of working with the selection buttons, it also improves
how we handle keyboard interaction for these buttons.
Here's what it looks like for single-select lists. Notice the missing
part of the input's border around the top (where the label *would* be if
we showed it). We should figure out how best to handle it. I've done
like this for now, but we can sort it out later.
![image](https://github.com/Unleash/unleash/assets/17786332/5af979c2-6635-481e-8d3e-5aad1c0ab46f)
2024-05-03 07:27:13 +02:00
|
|
|
anchorOrigin={{
|
|
|
|
vertical: 'bottom',
|
|
|
|
horizontal: 'left',
|
|
|
|
}}
|
|
|
|
transformOrigin={{
|
|
|
|
vertical: 'top',
|
|
|
|
horizontal: 'left',
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<StyledDropdown>
|
|
|
|
<StyledTextField
|
|
|
|
variant='outlined'
|
|
|
|
size='small'
|
|
|
|
value={searchText}
|
|
|
|
onChange={(event) => setSearchText(event.target.value)}
|
|
|
|
label={search.label}
|
|
|
|
placeholder={search.placeholder}
|
|
|
|
autoFocus
|
|
|
|
InputProps={{
|
|
|
|
startAdornment: (
|
|
|
|
<InputAdornment position='start'>
|
|
|
|
<Search fontSize='small' />
|
|
|
|
</InputAdornment>
|
|
|
|
),
|
|
|
|
}}
|
|
|
|
inputRef={(el) => {
|
|
|
|
listRefs.current[0] = el;
|
|
|
|
}}
|
|
|
|
onKeyDown={(event) =>
|
|
|
|
handleSelection(event, 0, filteredOptions)
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
<List sx={{ overflowY: 'auto' }} disablePadding>
|
|
|
|
{filteredOptions.map((option, index) => {
|
|
|
|
const labelId = `checkbox-list-label-${option.value}`;
|
|
|
|
|
|
|
|
return (
|
|
|
|
<StyledListItem
|
|
|
|
key={option.value}
|
|
|
|
dense
|
|
|
|
disablePadding
|
|
|
|
tabIndex={0}
|
|
|
|
onClick={() => {
|
|
|
|
onSelection(option.value);
|
|
|
|
}}
|
|
|
|
ref={(el) => {
|
|
|
|
listRefs.current[index + 1] = el;
|
|
|
|
}}
|
|
|
|
onKeyDown={(event) =>
|
|
|
|
handleSelection(
|
|
|
|
event,
|
|
|
|
index + 1,
|
|
|
|
filteredOptions,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
>
|
|
|
|
{multiselect ? (
|
|
|
|
<StyledCheckbox
|
|
|
|
edge='start'
|
|
|
|
checked={multiselect.selectedOptions.has(
|
|
|
|
option.value,
|
|
|
|
)}
|
|
|
|
tabIndex={-1}
|
|
|
|
inputProps={{
|
|
|
|
'aria-labelledby': labelId,
|
|
|
|
}}
|
|
|
|
size='small'
|
|
|
|
disableRipple
|
|
|
|
/>
|
|
|
|
) : null}
|
|
|
|
<ListItemText
|
|
|
|
id={labelId}
|
|
|
|
primary={option.label}
|
|
|
|
/>
|
|
|
|
</StyledListItem>
|
|
|
|
);
|
|
|
|
})}
|
|
|
|
</List>
|
|
|
|
</StyledDropdown>
|
|
|
|
</StyledPopover>
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
type MultiselectListProps = Pick<
|
|
|
|
CombinedSelectProps,
|
2024-05-07 08:56:53 +02:00
|
|
|
'options' | 'button' | 'search' | 'onOpen' | 'onClose'
|
support setting mode and stickiness in new project form (#6972)
This PR is a combination of two PRs:
This PR adds a functioning environment selection button to the new project creation form. Selected environments are added to the payload and to the API preview.
The implementation is mostly lifted from the existing FilterItem component we have for search filters. However, our need here is less complex, so I've removed some of the things we don't need. There is still more cleanup to be done, however, but I'd like to implement the rest of the submenus first, to see what we really do need in the end.
---
This PR adds support for stickiness and project mode in the new project
creation form.
Achieve this, it does a few things:
1. Moves `resolveStickinessOptions` from
`frontend/src/component/feature/StrategyTypes/FlexibleStrategy/StickinessSelect/StickinessSelect.tsx`
and into a separate hook. This component was used by the old project
creation form. Because the new form has a different input, but needs the
same option, moved that code into a reusable hook.
2. It adds functioning buttons for project stickiness and mode.
3. It adds labels to the search inputs for the dropdowns. Inputs *must*
have labels to meet a11y requirements. However, the designs don't have
labels, so we can hide them visually. Though that leads to another issue
(refer to the screen shot below).
4. It updates the `SelectionButton` component to handle both single- and
multiselect cases. It instead exports these two subcomponents. These are
currently in one file, but I'll split them out into their separate files
in a later PR.
As a side effect of working with the selection buttons, it also improves
how we handle keyboard interaction for these buttons.
Here's what it looks like for single-select lists. Notice the missing
part of the input's border around the top (where the label *would* be if
we showed it). We should figure out how best to handle it. I've done
like this for now, but we can sort it out later.
![image](https://github.com/Unleash/unleash/assets/17786332/5af979c2-6635-481e-8d3e-5aad1c0ab46f)
2024-05-03 07:27:13 +02:00
|
|
|
> & {
|
|
|
|
selectedOptions: Set<string>;
|
|
|
|
onChange: (values: Set<string>) => void;
|
|
|
|
};
|
|
|
|
|
|
|
|
export const MultiselectList: FC<MultiselectListProps> = ({
|
|
|
|
selectedOptions,
|
|
|
|
onChange,
|
|
|
|
...rest
|
|
|
|
}) => {
|
|
|
|
// todo: add "select all" and "deselect all"
|
|
|
|
|
|
|
|
const handleToggle = (value: string) => {
|
|
|
|
if (selectedOptions.has(value)) {
|
|
|
|
selectedOptions.delete(value);
|
|
|
|
} else {
|
|
|
|
selectedOptions.add(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
onChange(new Set(selectedOptions));
|
|
|
|
};
|
|
|
|
|
|
|
|
return (
|
|
|
|
<CombinedSelect
|
|
|
|
{...rest}
|
|
|
|
onChange={handleToggle}
|
|
|
|
multiselect={{
|
|
|
|
selectedOptions,
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
type SingleSelectListProps = Pick<
|
|
|
|
CombinedSelectProps,
|
2024-05-07 08:56:53 +02:00
|
|
|
'options' | 'button' | 'search' | 'onChange' | 'onOpen' | 'onClose'
|
support setting mode and stickiness in new project form (#6972)
This PR is a combination of two PRs:
This PR adds a functioning environment selection button to the new project creation form. Selected environments are added to the payload and to the API preview.
The implementation is mostly lifted from the existing FilterItem component we have for search filters. However, our need here is less complex, so I've removed some of the things we don't need. There is still more cleanup to be done, however, but I'd like to implement the rest of the submenus first, to see what we really do need in the end.
---
This PR adds support for stickiness and project mode in the new project
creation form.
Achieve this, it does a few things:
1. Moves `resolveStickinessOptions` from
`frontend/src/component/feature/StrategyTypes/FlexibleStrategy/StickinessSelect/StickinessSelect.tsx`
and into a separate hook. This component was used by the old project
creation form. Because the new form has a different input, but needs the
same option, moved that code into a reusable hook.
2. It adds functioning buttons for project stickiness and mode.
3. It adds labels to the search inputs for the dropdowns. Inputs *must*
have labels to meet a11y requirements. However, the designs don't have
labels, so we can hide them visually. Though that leads to another issue
(refer to the screen shot below).
4. It updates the `SelectionButton` component to handle both single- and
multiselect cases. It instead exports these two subcomponents. These are
currently in one file, but I'll split them out into their separate files
in a later PR.
As a side effect of working with the selection buttons, it also improves
how we handle keyboard interaction for these buttons.
Here's what it looks like for single-select lists. Notice the missing
part of the input's border around the top (where the label *would* be if
we showed it). We should figure out how best to handle it. I've done
like this for now, but we can sort it out later.
![image](https://github.com/Unleash/unleash/assets/17786332/5af979c2-6635-481e-8d3e-5aad1c0ab46f)
2024-05-03 07:27:13 +02:00
|
|
|
>;
|
|
|
|
|
|
|
|
export const SingleSelectList: FC<SingleSelectListProps> = (props) => {
|
|
|
|
return <CombinedSelect {...props} />;
|
|
|
|
};
|
feat: configure CRs when creating projects (#6979)
This PR adds the ability to configure CRs when creating a project.
The design is unfinished, and the code certainly needs cleanup, but I'd
like to get this into sandbox so we can look at it.
Things that still need to be done:
1. What do we do about this button when the user has no environments
selected? As a rough draft, I've disabled it. However, we should make it
possible to navigate to and give you an explanation why it was disabled,
e.g. "You have no project environments selected. Please select at least
one project environment.".
2. The form design is not done: the width should be constant and not
jumpy the way it is now. Also, the search field is too wide.
3. I've made the desicion that if you deselect a project env, we also
remove that env from your CR config it it's in there.
4. Potential improvement: if you enable and then disable CRs for an env,
we *could* probably store the data in between, so that if you set
required approvers 5 and then disabled it, it'd still be 5 when you
re-enabled it. That sounds like a good user experience. We should also
be able to extend that to adding/removing environments from project
envs.
2024-05-07 08:14:28 +02:00
|
|
|
|
2024-05-07 08:56:53 +02:00
|
|
|
type TableSelectProps = Pick<
|
|
|
|
CombinedSelectProps,
|
|
|
|
'button' | 'search' | 'onOpen' | 'onClose'
|
|
|
|
> & {
|
feat: configure CRs when creating projects (#6979)
This PR adds the ability to configure CRs when creating a project.
The design is unfinished, and the code certainly needs cleanup, but I'd
like to get this into sandbox so we can look at it.
Things that still need to be done:
1. What do we do about this button when the user has no environments
selected? As a rough draft, I've disabled it. However, we should make it
possible to navigate to and give you an explanation why it was disabled,
e.g. "You have no project environments selected. Please select at least
one project environment.".
2. The form design is not done: the width should be constant and not
jumpy the way it is now. Also, the search field is too wide.
3. I've made the desicion that if you deselect a project env, we also
remove that env from your CR config it it's in there.
4. Potential improvement: if you enable and then disable CRs for an env,
we *could* probably store the data in between, so that if you set
required approvers 5 and then disabled it, it'd still be 5 when you
re-enabled it. That sounds like a good user experience. We should also
be able to extend that to adding/removing environments from project
envs.
2024-05-07 08:14:28 +02:00
|
|
|
updateProjectChangeRequestConfiguration: {
|
|
|
|
disableChangeRequests: (env: string) => void;
|
|
|
|
enableChangeRequests: (env: string, requiredApprovals: number) => void;
|
|
|
|
};
|
|
|
|
activeEnvironments: {
|
|
|
|
name: string;
|
|
|
|
type: string;
|
|
|
|
}[];
|
|
|
|
projectChangeRequestConfiguration: Record<
|
|
|
|
string,
|
|
|
|
{ requiredApprovals: number }
|
|
|
|
>;
|
|
|
|
disabled: boolean;
|
|
|
|
};
|
|
|
|
export const TableSelect: FC<TableSelectProps> = ({
|
|
|
|
button,
|
|
|
|
disabled,
|
|
|
|
search,
|
|
|
|
projectChangeRequestConfiguration,
|
|
|
|
updateProjectChangeRequestConfiguration,
|
|
|
|
activeEnvironments,
|
2024-05-07 08:56:53 +02:00
|
|
|
onOpen = () => {},
|
|
|
|
onClose = () => {},
|
feat: configure CRs when creating projects (#6979)
This PR adds the ability to configure CRs when creating a project.
The design is unfinished, and the code certainly needs cleanup, but I'd
like to get this into sandbox so we can look at it.
Things that still need to be done:
1. What do we do about this button when the user has no environments
selected? As a rough draft, I've disabled it. However, we should make it
possible to navigate to and give you an explanation why it was disabled,
e.g. "You have no project environments selected. Please select at least
one project environment.".
2. The form design is not done: the width should be constant and not
jumpy the way it is now. Also, the search field is too wide.
3. I've made the desicion that if you deselect a project env, we also
remove that env from your CR config it it's in there.
4. Potential improvement: if you enable and then disable CRs for an env,
we *could* probably store the data in between, so that if you set
required approvers 5 and then disabled it, it'd still be 5 when you
re-enabled it. That sounds like a good user experience. We should also
be able to extend that to adding/removing environments from project
envs.
2024-05-07 08:14:28 +02:00
|
|
|
}) => {
|
|
|
|
const configured = useMemo(() => {
|
|
|
|
return Object.fromEntries(
|
|
|
|
Object.entries(projectChangeRequestConfiguration).map(
|
|
|
|
([name, config]) => [
|
|
|
|
name,
|
|
|
|
{ ...config, changeRequestEnabled: true },
|
|
|
|
],
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}, [projectChangeRequestConfiguration]);
|
|
|
|
|
|
|
|
const tableEnvs = useMemo(
|
|
|
|
() =>
|
|
|
|
activeEnvironments.map(({ name, type }) => ({
|
|
|
|
name,
|
|
|
|
type,
|
|
|
|
...(configured[name] ?? { changeRequestEnabled: false }),
|
|
|
|
})),
|
|
|
|
[configured, activeEnvironments],
|
|
|
|
);
|
|
|
|
|
|
|
|
const onEnable = (name: string, requiredApprovals: number) => {
|
|
|
|
updateProjectChangeRequestConfiguration.enableChangeRequests(
|
|
|
|
name,
|
|
|
|
requiredApprovals,
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
const onDisable = (name: string) => {
|
|
|
|
updateProjectChangeRequestConfiguration.disableChangeRequests(name);
|
|
|
|
};
|
|
|
|
|
|
|
|
const ref = useRef<HTMLDivElement>(null);
|
|
|
|
const [anchorEl, setAnchorEl] = useState<HTMLDivElement | null>();
|
|
|
|
const [searchText, setSearchText] = useState('');
|
|
|
|
|
|
|
|
const open = () => {
|
|
|
|
setSearchText('');
|
|
|
|
setAnchorEl(ref.current);
|
2024-05-07 08:56:53 +02:00
|
|
|
onOpen();
|
feat: configure CRs when creating projects (#6979)
This PR adds the ability to configure CRs when creating a project.
The design is unfinished, and the code certainly needs cleanup, but I'd
like to get this into sandbox so we can look at it.
Things that still need to be done:
1. What do we do about this button when the user has no environments
selected? As a rough draft, I've disabled it. However, we should make it
possible to navigate to and give you an explanation why it was disabled,
e.g. "You have no project environments selected. Please select at least
one project environment.".
2. The form design is not done: the width should be constant and not
jumpy the way it is now. Also, the search field is too wide.
3. I've made the desicion that if you deselect a project env, we also
remove that env from your CR config it it's in there.
4. Potential improvement: if you enable and then disable CRs for an env,
we *could* probably store the data in between, so that if you set
required approvers 5 and then disabled it, it'd still be 5 when you
re-enabled it. That sounds like a good user experience. We should also
be able to extend that to adding/removing environments from project
envs.
2024-05-07 08:14:28 +02:00
|
|
|
};
|
|
|
|
|
2024-05-07 08:56:53 +02:00
|
|
|
const handleClose = () => {
|
feat: configure CRs when creating projects (#6979)
This PR adds the ability to configure CRs when creating a project.
The design is unfinished, and the code certainly needs cleanup, but I'd
like to get this into sandbox so we can look at it.
Things that still need to be done:
1. What do we do about this button when the user has no environments
selected? As a rough draft, I've disabled it. However, we should make it
possible to navigate to and give you an explanation why it was disabled,
e.g. "You have no project environments selected. Please select at least
one project environment.".
2. The form design is not done: the width should be constant and not
jumpy the way it is now. Also, the search field is too wide.
3. I've made the desicion that if you deselect a project env, we also
remove that env from your CR config it it's in there.
4. Potential improvement: if you enable and then disable CRs for an env,
we *could* probably store the data in between, so that if you set
required approvers 5 and then disabled it, it'd still be 5 when you
re-enabled it. That sounds like a good user experience. We should also
be able to extend that to adding/removing environments from project
envs.
2024-05-07 08:14:28 +02:00
|
|
|
setAnchorEl(null);
|
2024-05-07 08:56:53 +02:00
|
|
|
onClose();
|
feat: configure CRs when creating projects (#6979)
This PR adds the ability to configure CRs when creating a project.
The design is unfinished, and the code certainly needs cleanup, but I'd
like to get this into sandbox so we can look at it.
Things that still need to be done:
1. What do we do about this button when the user has no environments
selected? As a rough draft, I've disabled it. However, we should make it
possible to navigate to and give you an explanation why it was disabled,
e.g. "You have no project environments selected. Please select at least
one project environment.".
2. The form design is not done: the width should be constant and not
jumpy the way it is now. Also, the search field is too wide.
3. I've made the desicion that if you deselect a project env, we also
remove that env from your CR config it it's in there.
4. Potential improvement: if you enable and then disable CRs for an env,
we *could* probably store the data in between, so that if you set
required approvers 5 and then disabled it, it'd still be 5 when you
re-enabled it. That sounds like a good user experience. We should also
be able to extend that to adding/removing environments from project
envs.
2024-05-07 08:14:28 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
const filteredEnvs = tableEnvs.filter((env) =>
|
|
|
|
env.name.toLowerCase().includes(searchText.toLowerCase()),
|
|
|
|
);
|
|
|
|
|
|
|
|
const toggleTopItem = (event: React.KeyboardEvent) => {
|
|
|
|
if (
|
|
|
|
event.key === 'Enter' &&
|
|
|
|
searchText.trim().length > 0 &&
|
|
|
|
filteredEnvs.length > 0
|
|
|
|
) {
|
|
|
|
const firstEnv = filteredEnvs[0];
|
|
|
|
if (firstEnv.name in configured) {
|
|
|
|
onDisable(firstEnv.name);
|
|
|
|
} else {
|
|
|
|
onEnable(firstEnv.name, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<Box ref={ref}>
|
|
|
|
<Button
|
|
|
|
variant='outlined'
|
|
|
|
color='primary'
|
|
|
|
startIcon={button.icon}
|
|
|
|
onClick={() => {
|
|
|
|
open();
|
|
|
|
}}
|
|
|
|
disabled={disabled}
|
|
|
|
>
|
|
|
|
{button.label}
|
|
|
|
</Button>
|
|
|
|
</Box>
|
|
|
|
<StyledPopover
|
|
|
|
open={Boolean(anchorEl)}
|
|
|
|
anchorEl={anchorEl}
|
2024-05-07 08:56:53 +02:00
|
|
|
onClose={handleClose}
|
feat: configure CRs when creating projects (#6979)
This PR adds the ability to configure CRs when creating a project.
The design is unfinished, and the code certainly needs cleanup, but I'd
like to get this into sandbox so we can look at it.
Things that still need to be done:
1. What do we do about this button when the user has no environments
selected? As a rough draft, I've disabled it. However, we should make it
possible to navigate to and give you an explanation why it was disabled,
e.g. "You have no project environments selected. Please select at least
one project environment.".
2. The form design is not done: the width should be constant and not
jumpy the way it is now. Also, the search field is too wide.
3. I've made the desicion that if you deselect a project env, we also
remove that env from your CR config it it's in there.
4. Potential improvement: if you enable and then disable CRs for an env,
we *could* probably store the data in between, so that if you set
required approvers 5 and then disabled it, it'd still be 5 when you
re-enabled it. That sounds like a good user experience. We should also
be able to extend that to adding/removing environments from project
envs.
2024-05-07 08:14:28 +02:00
|
|
|
anchorOrigin={{
|
|
|
|
vertical: 'bottom',
|
|
|
|
horizontal: 'left',
|
|
|
|
}}
|
|
|
|
transformOrigin={{
|
|
|
|
vertical: 'top',
|
|
|
|
horizontal: 'left',
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<StyledDropdown>
|
|
|
|
<TableSearchInput
|
|
|
|
variant='outlined'
|
|
|
|
size='small'
|
|
|
|
value={searchText}
|
|
|
|
onChange={(event) => setSearchText(event.target.value)}
|
|
|
|
label={search.label}
|
|
|
|
placeholder={search.placeholder}
|
|
|
|
autoFocus
|
|
|
|
InputProps={{
|
|
|
|
startAdornment: (
|
|
|
|
<InputAdornment position='start'>
|
|
|
|
<Search fontSize='small' />
|
|
|
|
</InputAdornment>
|
|
|
|
),
|
|
|
|
}}
|
|
|
|
onKeyDown={toggleTopItem}
|
|
|
|
/>
|
|
|
|
<ChangeRequestTable
|
|
|
|
environments={filteredEnvs}
|
|
|
|
enableEnvironment={onEnable}
|
|
|
|
disableEnvironment={onDisable}
|
|
|
|
/>
|
|
|
|
</StyledDropdown>
|
|
|
|
</StyledPopover>
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
};
|