mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01: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