mirror of
https://github.com/Unleash/unleash.git
synced 2025-06-04 01:18:20 +02:00
Feature toggle types list (#4260)
## About the changes 
This commit is contained in:
parent
35fbd8f271
commit
ef495a35ee
@ -5,12 +5,11 @@ import { IRole, PredefinedRoleType } from 'interfaces/role';
|
|||||||
import useToast from 'hooks/useToast';
|
import useToast from 'hooks/useToast';
|
||||||
import { formatUnknownError } from 'utils/formatUnknownError';
|
import { formatUnknownError } from 'utils/formatUnknownError';
|
||||||
import { PageContent } from 'component/common/PageContent/PageContent';
|
import { PageContent } from 'component/common/PageContent/PageContent';
|
||||||
import { useMediaQuery } from '@mui/material';
|
import { useTheme, useMediaQuery } from '@mui/material';
|
||||||
import { SearchHighlightProvider } from 'component/common/Table/SearchHighlightContext/SearchHighlightContext';
|
import { SearchHighlightProvider } from 'component/common/Table/SearchHighlightContext/SearchHighlightContext';
|
||||||
import { useFlexLayout, useSortBy, useTable } from 'react-table';
|
import { useFlexLayout, useSortBy, useTable } from 'react-table';
|
||||||
import { sortTypes } from 'utils/sortTypes';
|
import { sortTypes } from 'utils/sortTypes';
|
||||||
import { TextCell } from 'component/common/Table/cells/TextCell/TextCell';
|
import { TextCell } from 'component/common/Table/cells/TextCell/TextCell';
|
||||||
import theme from 'themes/theme';
|
|
||||||
import { useConditionallyHiddenColumns } from 'hooks/useConditionallyHiddenColumns';
|
import { useConditionallyHiddenColumns } from 'hooks/useConditionallyHiddenColumns';
|
||||||
import { useSearch } from 'hooks/useSearch';
|
import { useSearch } from 'hooks/useSearch';
|
||||||
import { IconCell } from 'component/common/Table/cells/IconCell/IconCell';
|
import { IconCell } from 'component/common/Table/cells/IconCell/IconCell';
|
||||||
@ -42,6 +41,7 @@ export const RolesTable = ({
|
|||||||
setSelectedRole,
|
setSelectedRole,
|
||||||
}: IRolesTableProps) => {
|
}: IRolesTableProps) => {
|
||||||
const { setToastData, setToastApiError } = useToast();
|
const { setToastData, setToastApiError } = useToast();
|
||||||
|
const theme = useTheme();
|
||||||
|
|
||||||
const { roles, projectRoles, refetch, loading } = useRoles();
|
const { roles, projectRoles, refetch, loading } = useRoles();
|
||||||
const { removeRole } = useRolesApi();
|
const { removeRole } = useRolesApi();
|
||||||
|
190
frontend/src/component/featureTypes/FeatureTypesList.tsx
Normal file
190
frontend/src/component/featureTypes/FeatureTypesList.tsx
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
import { useMemo } from 'react';
|
||||||
|
import { useSortBy, useTable } from 'react-table';
|
||||||
|
import { sortTypes } from 'utils/sortTypes';
|
||||||
|
import { PageContent } from 'component/common/PageContent/PageContent';
|
||||||
|
import useFeatureTypes from 'hooks/api/getters/useFeatureTypes/useFeatureTypes';
|
||||||
|
import { PageHeader } from 'component/common/PageHeader/PageHeader';
|
||||||
|
import { Box, Typography, useMediaQuery, useTheme } from '@mui/material';
|
||||||
|
import {
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableRow,
|
||||||
|
SortableTableHeader,
|
||||||
|
} from 'component/common/Table';
|
||||||
|
import { TextCell } from 'component/common/Table/cells/TextCell/TextCell';
|
||||||
|
import { getFeatureTypeIcons } from 'utils/getFeatureTypeIcons';
|
||||||
|
import { IconCell } from 'component/common/Table/cells/IconCell/IconCell';
|
||||||
|
import { ActionCell } from 'component/common/Table/cells/ActionCell/ActionCell';
|
||||||
|
import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton';
|
||||||
|
import { ADMIN } from 'component/providers/AccessProvider/permissions';
|
||||||
|
import { Edit } from '@mui/icons-material';
|
||||||
|
import { useConditionallyHiddenColumns } from 'hooks/useConditionallyHiddenColumns';
|
||||||
|
|
||||||
|
export const FeatureTypesList = () => {
|
||||||
|
const { featureTypes, loading } = useFeatureTypes();
|
||||||
|
const theme = useTheme();
|
||||||
|
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
|
||||||
|
|
||||||
|
const columns = useMemo(
|
||||||
|
() => [
|
||||||
|
{
|
||||||
|
accessor: 'id',
|
||||||
|
Cell: ({ value }: { value: string }) => {
|
||||||
|
const IconComponent = getFeatureTypeIcons(value);
|
||||||
|
return (
|
||||||
|
<IconCell
|
||||||
|
icon={
|
||||||
|
<IconComponent
|
||||||
|
data-loading="true"
|
||||||
|
color="action"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
width: 50,
|
||||||
|
disableSortBy: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Header: 'Name',
|
||||||
|
accessor: 'name',
|
||||||
|
minWidth: 125,
|
||||||
|
Cell: TextCell,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Header: 'Description',
|
||||||
|
accessor: 'description',
|
||||||
|
width: '80%',
|
||||||
|
Cell: ({ value }: { value: string }) => (
|
||||||
|
<Typography
|
||||||
|
component="div"
|
||||||
|
variant="body2"
|
||||||
|
color="text.secondary"
|
||||||
|
lineHeight={2}
|
||||||
|
>
|
||||||
|
<TextCell lineClamp={1}>{value}</TextCell>
|
||||||
|
</Typography>
|
||||||
|
),
|
||||||
|
disableSortBy: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Header: 'Lifetime',
|
||||||
|
accessor: 'lifetimeDays',
|
||||||
|
Cell: ({ value }: { value: number }) => {
|
||||||
|
if (value) {
|
||||||
|
return (
|
||||||
|
<TextCell>
|
||||||
|
{value === 1 ? '1 day' : `${value} days`}
|
||||||
|
</TextCell>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return <TextCell>doesn't expire</TextCell>;
|
||||||
|
},
|
||||||
|
sortInverted: true,
|
||||||
|
minWidth: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Header: 'Actions',
|
||||||
|
Cell: ({ row: { original: featureType } }: any) => (
|
||||||
|
<Box sx={theme => ({ padding: theme.spacing(0.5, 0) })}>
|
||||||
|
<ActionCell>
|
||||||
|
<PermissionIconButton
|
||||||
|
disabled={!featureType.id}
|
||||||
|
data-loading="true"
|
||||||
|
onClick={() => {}}
|
||||||
|
permission={ADMIN}
|
||||||
|
tooltipProps={{
|
||||||
|
title: 'Edit feature toggle type',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Edit />
|
||||||
|
</PermissionIconButton>
|
||||||
|
</ActionCell>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
disableSortBy: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
const data = useMemo(
|
||||||
|
() =>
|
||||||
|
loading
|
||||||
|
? Array(5).fill({
|
||||||
|
id: '',
|
||||||
|
name: 'Loading...',
|
||||||
|
description: 'Loading...',
|
||||||
|
lifetimeDays: 1,
|
||||||
|
})
|
||||||
|
: featureTypes,
|
||||||
|
[loading, featureTypes]
|
||||||
|
);
|
||||||
|
|
||||||
|
const {
|
||||||
|
getTableProps,
|
||||||
|
getTableBodyProps,
|
||||||
|
headerGroups,
|
||||||
|
rows,
|
||||||
|
prepareRow,
|
||||||
|
setHiddenColumns,
|
||||||
|
} = useTable(
|
||||||
|
{
|
||||||
|
columns: columns as any[],
|
||||||
|
data,
|
||||||
|
sortTypes,
|
||||||
|
autoResetSortBy: false,
|
||||||
|
disableSortRemove: true,
|
||||||
|
},
|
||||||
|
useSortBy
|
||||||
|
);
|
||||||
|
|
||||||
|
useConditionallyHiddenColumns(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
condition: isSmallScreen,
|
||||||
|
columns: ['description'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
setHiddenColumns,
|
||||||
|
columns
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PageContent
|
||||||
|
isLoading={loading}
|
||||||
|
header={
|
||||||
|
<PageHeader>
|
||||||
|
<Typography
|
||||||
|
component="h2"
|
||||||
|
sx={theme => ({
|
||||||
|
fontSize: theme.fontSizes.mainHeader,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
Feature toggle types
|
||||||
|
</Typography>
|
||||||
|
</PageHeader>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Table {...getTableProps()}>
|
||||||
|
<SortableTableHeader headerGroups={headerGroups} />
|
||||||
|
<TableBody {...getTableBodyProps()}>
|
||||||
|
{rows.map(row => {
|
||||||
|
prepareRow(row);
|
||||||
|
return (
|
||||||
|
<TableRow hover {...row.getRowProps()}>
|
||||||
|
{row.cells.map(cell => (
|
||||||
|
<TableCell {...cell.getCellProps()}>
|
||||||
|
{cell.render('Cell')}
|
||||||
|
</TableCell>
|
||||||
|
))}
|
||||||
|
</TableRow>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</PageContent>
|
||||||
|
);
|
||||||
|
};
|
@ -193,6 +193,17 @@ exports[`returns all baseRoutes 1`] = `
|
|||||||
"title": "Context fields",
|
"title": "Context fields",
|
||||||
"type": "protected",
|
"type": "protected",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"component": [Function],
|
||||||
|
"flag": "configurableFeatureTypeLifetimes",
|
||||||
|
"menu": {
|
||||||
|
"advanced": true,
|
||||||
|
"mobile": true,
|
||||||
|
},
|
||||||
|
"path": "/feature-toggle-type",
|
||||||
|
"title": "Feature toggle types",
|
||||||
|
"type": "protected",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"component": [Function],
|
"component": [Function],
|
||||||
"menu": {},
|
"menu": {},
|
||||||
|
@ -44,6 +44,7 @@ import { LazyAdmin } from 'component/admin/LazyAdmin';
|
|||||||
import { LazyProject } from 'component/project/Project/LazyProject';
|
import { LazyProject } from 'component/project/Project/LazyProject';
|
||||||
import { AdminRedirect } from 'component/admin/AdminRedirect';
|
import { AdminRedirect } from 'component/admin/AdminRedirect';
|
||||||
import { LoginHistory } from 'component/loginHistory/LoginHistory';
|
import { LoginHistory } from 'component/loginHistory/LoginHistory';
|
||||||
|
import { FeatureTypesList } from 'component/featureTypes/FeatureTypesList';
|
||||||
|
|
||||||
export const routes: IRoute[] = [
|
export const routes: IRoute[] = [
|
||||||
// Splash
|
// Splash
|
||||||
@ -209,6 +210,16 @@ export const routes: IRoute[] = [
|
|||||||
menu: { mobile: true, advanced: true },
|
menu: { mobile: true, advanced: true },
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Feature types
|
||||||
|
{
|
||||||
|
path: '/feature-toggle-type',
|
||||||
|
title: 'Feature toggle types',
|
||||||
|
component: FeatureTypesList,
|
||||||
|
type: 'protected',
|
||||||
|
menu: { mobile: true, advanced: true },
|
||||||
|
flag: 'configurableFeatureTypeLifetimes',
|
||||||
|
},
|
||||||
|
|
||||||
// Strategies
|
// Strategies
|
||||||
{
|
{
|
||||||
path: '/strategies/create',
|
path: '/strategies/create',
|
||||||
|
@ -53,6 +53,7 @@ export interface IFlags {
|
|||||||
customRootRoles?: boolean;
|
customRootRoles?: boolean;
|
||||||
strategyVariant?: boolean;
|
strategyVariant?: boolean;
|
||||||
newProjectLayout?: boolean;
|
newProjectLayout?: boolean;
|
||||||
|
configurableFeatureTypeLifetimes?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IVersionInfo {
|
export interface IVersionInfo {
|
||||||
|
Loading…
Reference in New Issue
Block a user