mirror of
https://github.com/Unleash/unleash.git
synced 2025-05-22 01:16:07 +02:00
refactor: remove unused code (#1036)
* refactor: remove unused code * refactor: remove more unused code
This commit is contained in:
parent
ae012d62e6
commit
eb5e83cdb4
@ -1,75 +1,9 @@
|
|||||||
import React, { ReactElement } from 'react';
|
import React from 'react';
|
||||||
import { ConfiguredAddons } from './ConfiguredAddons/ConfiguredAddons';
|
import { ConfiguredAddons } from './ConfiguredAddons/ConfiguredAddons';
|
||||||
import { AvailableAddons } from './AvailableAddons/AvailableAddons';
|
import { AvailableAddons } from './AvailableAddons/AvailableAddons';
|
||||||
import { Avatar } from '@mui/material';
|
|
||||||
import { DeviceHub } from '@mui/icons-material';
|
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import slackIcon from 'assets/icons/slack.svg';
|
|
||||||
import jiraIcon from 'assets/icons/jira.svg';
|
|
||||||
import webhooksIcon from 'assets/icons/webhooks.svg';
|
|
||||||
import teamsIcon from 'assets/icons/teams.svg';
|
|
||||||
import dataDogIcon from 'assets/icons/datadog.svg';
|
|
||||||
import { formatAssetPath } from 'utils/formatPath';
|
|
||||||
import useAddons from 'hooks/api/getters/useAddons/useAddons';
|
import useAddons from 'hooks/api/getters/useAddons/useAddons';
|
||||||
|
|
||||||
const style: React.CSSProperties = {
|
|
||||||
width: '32.5px',
|
|
||||||
height: '32.5px',
|
|
||||||
marginRight: '16px',
|
|
||||||
borderRadius: '50%',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getAddonIcon = (name: string): ReactElement => {
|
|
||||||
switch (name) {
|
|
||||||
case 'slack':
|
|
||||||
return (
|
|
||||||
<img
|
|
||||||
style={style}
|
|
||||||
alt="Slack logo"
|
|
||||||
src={formatAssetPath(slackIcon)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
case 'jira-comment':
|
|
||||||
return (
|
|
||||||
<img
|
|
||||||
style={style}
|
|
||||||
alt="JIRA logo"
|
|
||||||
src={formatAssetPath(jiraIcon)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
case 'webhook':
|
|
||||||
return (
|
|
||||||
<img
|
|
||||||
style={style}
|
|
||||||
alt="Generic Webhook logo"
|
|
||||||
src={formatAssetPath(webhooksIcon)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
case 'teams':
|
|
||||||
return (
|
|
||||||
<img
|
|
||||||
style={style}
|
|
||||||
alt="Microsoft Teams logo"
|
|
||||||
src={formatAssetPath(teamsIcon)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
case 'datadog':
|
|
||||||
return (
|
|
||||||
<img
|
|
||||||
style={style}
|
|
||||||
alt="Datadog logo"
|
|
||||||
src={formatAssetPath(dataDogIcon)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
default:
|
|
||||||
return (
|
|
||||||
<Avatar>
|
|
||||||
<DeviceHub />
|
|
||||||
</Avatar>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const AddonList = () => {
|
export const AddonList = () => {
|
||||||
const { providers, addons, loading } = useAddons();
|
const { providers, addons, loading } = useAddons();
|
||||||
|
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
import { makeStyles } from 'tss-react/mui';
|
|
||||||
|
|
||||||
export const useStyles = makeStyles()(theme => ({
|
|
||||||
panel: {
|
|
||||||
width: '100%',
|
|
||||||
marginBottom: theme.spacing(2),
|
|
||||||
borderRadius: theme.spacing(1.5),
|
|
||||||
paddingBottom: theme.spacing(4),
|
|
||||||
},
|
|
||||||
}));
|
|
@ -1,18 +0,0 @@
|
|||||||
import { forwardRef } from 'react';
|
|
||||||
import { Paper, PaperProps } from '@mui/material';
|
|
||||||
import { useStyles } from './TableContainer.styles';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
export const TableContainer = forwardRef<HTMLDivElement, PaperProps>(
|
|
||||||
({ children, ...props }, ref) => {
|
|
||||||
const { classes } = useStyles();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Paper ref={ref} className={classes.panel} {...props}>
|
|
||||||
{children}
|
|
||||||
</Paper>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
@ -1,7 +1,6 @@
|
|||||||
export const P = 'P';
|
export const P = 'P';
|
||||||
export const C = 'C';
|
export const C = 'C';
|
||||||
export const E = 'E';
|
export const E = 'E';
|
||||||
export const RBAC = 'RBAC';
|
|
||||||
export const EEA = 'EEA';
|
export const EEA = 'EEA';
|
||||||
export const RE = 'RE';
|
export const RE = 'RE';
|
||||||
export const SE = 'SE';
|
export const SE = 'SE';
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { useContext, useMemo, useState, VFC } from 'react';
|
import { useMemo, useState, VFC } from 'react';
|
||||||
import { useGlobalFilter, useSortBy, useTable } from 'react-table';
|
import { useGlobalFilter, useSortBy, useTable } from 'react-table';
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
@ -12,7 +12,6 @@ import {
|
|||||||
import { PageContent } from 'component/common/PageContent/PageContent';
|
import { PageContent } from 'component/common/PageContent/PageContent';
|
||||||
import { PageHeader } from 'component/common/PageHeader/PageHeader';
|
import { PageHeader } from 'component/common/PageHeader/PageHeader';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import { UPDATE_CONTEXT_FIELD } from 'component/providers/AccessProvider/permissions';
|
|
||||||
import { Dialogue as ConfirmDialogue } from 'component/common/Dialogue/Dialogue';
|
import { Dialogue as ConfirmDialogue } from 'component/common/Dialogue/Dialogue';
|
||||||
import useUnleashContext from 'hooks/api/getters/useUnleashContext/useUnleashContext';
|
import useUnleashContext from 'hooks/api/getters/useUnleashContext/useUnleashContext';
|
||||||
import useContextsApi from 'hooks/api/actions/useContextsApi/useContextsApi';
|
import useContextsApi from 'hooks/api/actions/useContextsApi/useContextsApi';
|
||||||
@ -25,7 +24,6 @@ import { LinkCell } from 'component/common/Table/cells/LinkCell/LinkCell';
|
|||||||
import { ContextActionsCell } from './ContextActionsCell/ContextActionsCell';
|
import { ContextActionsCell } from './ContextActionsCell/ContextActionsCell';
|
||||||
import { Adjust } from '@mui/icons-material';
|
import { Adjust } from '@mui/icons-material';
|
||||||
import { IconCell } from 'component/common/Table/cells/IconCell/IconCell';
|
import { IconCell } from 'component/common/Table/cells/IconCell/IconCell';
|
||||||
import AccessContext from 'contexts/AccessContext';
|
|
||||||
|
|
||||||
const ContextList: VFC = () => {
|
const ContextList: VFC = () => {
|
||||||
const [showDelDialogue, setShowDelDialogue] = useState(false);
|
const [showDelDialogue, setShowDelDialogue] = useState(false);
|
||||||
@ -33,7 +31,6 @@ const ContextList: VFC = () => {
|
|||||||
const { context, refetchUnleashContext, loading } = useUnleashContext();
|
const { context, refetchUnleashContext, loading } = useUnleashContext();
|
||||||
const { removeContext } = useContextsApi();
|
const { removeContext } = useContextsApi();
|
||||||
const { setToastData, setToastApiError } = useToast();
|
const { setToastData, setToastApiError } = useToast();
|
||||||
const { hasAccess } = useContext(AccessContext);
|
|
||||||
|
|
||||||
const data = useMemo(() => {
|
const data = useMemo(() => {
|
||||||
if (loading) {
|
if (loading) {
|
||||||
|
@ -1,58 +0,0 @@
|
|||||||
import { makeStyles } from 'tss-react/mui';
|
|
||||||
|
|
||||||
export const useStyles = makeStyles()(theme => ({
|
|
||||||
tableRow: {
|
|
||||||
'&:hover': {
|
|
||||||
backgroundColor: theme.palette.grey[200],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
tableCell: {
|
|
||||||
border: 'none',
|
|
||||||
padding: '0.25rem 0',
|
|
||||||
},
|
|
||||||
tableCellHeader: {
|
|
||||||
paddingBottom: '0.5rem',
|
|
||||||
fontWeight: 'normal',
|
|
||||||
color: theme.palette.grey[600],
|
|
||||||
borderBottom: '1px solid ' + theme.palette.grey[200],
|
|
||||||
},
|
|
||||||
tableCellHeaderSortable: {
|
|
||||||
cursor: 'pointer',
|
|
||||||
background: theme.palette.grey[50],
|
|
||||||
},
|
|
||||||
tableCellStatus: {
|
|
||||||
width: '60px',
|
|
||||||
},
|
|
||||||
tableCellName: {
|
|
||||||
paddingLeft: '10px',
|
|
||||||
},
|
|
||||||
tableCellEnv: {
|
|
||||||
width: '90px',
|
|
||||||
[theme.breakpoints.down('md')]: {
|
|
||||||
display: 'none',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
tableCellCreated: {
|
|
||||||
[theme.breakpoints.down('md')]: {
|
|
||||||
display: 'none',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
tableCellType: {
|
|
||||||
width: '32px',
|
|
||||||
alignItems: 'center',
|
|
||||||
[theme.breakpoints.down(600)]: {
|
|
||||||
display: 'none',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
link: {
|
|
||||||
textDecoration: 'none',
|
|
||||||
color: theme.palette.primary.main,
|
|
||||||
fontWeight: theme.fontWeight.bold,
|
|
||||||
},
|
|
||||||
sortButton: {
|
|
||||||
all: 'unset',
|
|
||||||
'&:focus-visible, &:active': {
|
|
||||||
outline: 'revert',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}));
|
|
@ -1,297 +0,0 @@
|
|||||||
import { useState, useEffect, useContext } from 'react';
|
|
||||||
import {
|
|
||||||
Table,
|
|
||||||
TableBody,
|
|
||||||
TableCell,
|
|
||||||
TableHead,
|
|
||||||
TableRow,
|
|
||||||
} from '@mui/material';
|
|
||||||
import classnames from 'classnames';
|
|
||||||
import { useStyles } from './FeatureToggleListNew.styles';
|
|
||||||
import FeatureToggleListNewItem from './FeatureToggleListNewItem/FeatureToggleListNewItem';
|
|
||||||
import usePagination from 'hooks/usePagination';
|
|
||||||
import loadingFeatures from './FeatureToggleListNewItem/loadingFeatures';
|
|
||||||
import { IFeatureToggleListItem } from 'interfaces/featureToggle';
|
|
||||||
import PaginateUI from 'component/common/PaginateUI/PaginateUI';
|
|
||||||
import StringTruncator from 'component/common/StringTruncator/StringTruncator';
|
|
||||||
import { createGlobalStateHook } from 'hooks/useGlobalState';
|
|
||||||
import { AnnouncerContext } from 'component/common/Announcer/AnnouncerContext/AnnouncerContext';
|
|
||||||
|
|
||||||
interface IFeatureToggleListNewProps {
|
|
||||||
features: IFeatureToggleListItem[];
|
|
||||||
loading: boolean;
|
|
||||||
projectId: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// @ts-expect-error
|
|
||||||
const sortList = (list, sortOpt) => {
|
|
||||||
if (!list) {
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
if (!sortOpt.field) {
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
if (sortOpt.type === 'string') {
|
|
||||||
// @ts-expect-error
|
|
||||||
return list.sort((a, b) => {
|
|
||||||
const fieldA = a[sortOpt.field]?.toUpperCase();
|
|
||||||
const fieldB = b[sortOpt.field]?.toUpperCase();
|
|
||||||
const direction = sortOpt.direction;
|
|
||||||
|
|
||||||
if (fieldA < fieldB) {
|
|
||||||
return direction === 0 ? -1 : 1;
|
|
||||||
}
|
|
||||||
if (fieldA > fieldB) {
|
|
||||||
return direction === 0 ? 1 : -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (sortOpt.type === 'date') {
|
|
||||||
// @ts-expect-error
|
|
||||||
return list.sort((a, b) => {
|
|
||||||
const fieldA = new Date(a[sortOpt.field]);
|
|
||||||
const fieldB = new Date(b[sortOpt.field]);
|
|
||||||
|
|
||||||
if (fieldA < fieldB) {
|
|
||||||
return sortOpt.direction === 0 ? 1 : -1;
|
|
||||||
}
|
|
||||||
if (fieldA > fieldB) {
|
|
||||||
return sortOpt.direction === 0 ? -1 : 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
};
|
|
||||||
|
|
||||||
interface ISortedState {
|
|
||||||
field: string;
|
|
||||||
type: string;
|
|
||||||
direction: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
const useFeatureToggLeProjectSort = createGlobalStateHook<ISortedState>(
|
|
||||||
'useFeatureToggLeProjectSort',
|
|
||||||
{ field: 'name', type: 'string', direction: 0 }
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
const FeatureToggleListNew = ({
|
|
||||||
features,
|
|
||||||
loading,
|
|
||||||
projectId,
|
|
||||||
}: IFeatureToggleListNewProps) => {
|
|
||||||
const { classes: styles } = useStyles();
|
|
||||||
const { setAnnouncement } = useContext(AnnouncerContext);
|
|
||||||
const [sortOpt, setSortOpt] = useFeatureToggLeProjectSort();
|
|
||||||
|
|
||||||
const [sortedFeatures, setSortedFeatures] = useState<
|
|
||||||
IFeatureToggleListItem[]
|
|
||||||
>(sortList([...features], sortOpt));
|
|
||||||
|
|
||||||
const { page, pages, nextPage, prevPage, setPageIndex, pageIndex } =
|
|
||||||
usePagination(sortedFeatures, 50);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setSortedFeatures(sortList([...features], sortOpt));
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [features]);
|
|
||||||
|
|
||||||
const updateSort = (field: string) => {
|
|
||||||
let newSortOpt;
|
|
||||||
if (field === sortOpt.field) {
|
|
||||||
newSortOpt = { ...sortOpt, direction: (sortOpt.direction + 1) % 2 };
|
|
||||||
} else if (['createdAt', 'lastSeenAt'].includes(field)) {
|
|
||||||
newSortOpt = {
|
|
||||||
field,
|
|
||||||
type: 'date',
|
|
||||||
direction: 0,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
newSortOpt = {
|
|
||||||
field,
|
|
||||||
type: 'string',
|
|
||||||
direction: 0,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
setSortOpt(newSortOpt);
|
|
||||||
setSortedFeatures(sortList([...features], newSortOpt));
|
|
||||||
setPageIndex(0);
|
|
||||||
|
|
||||||
setAnnouncement(
|
|
||||||
`Sorted table by ${field}, ${
|
|
||||||
sortOpt.direction ? 'ascending' : 'descending'
|
|
||||||
}`
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const getEnvironments = () => {
|
|
||||||
if (features.length > 0) {
|
|
||||||
const envs = features[0].environments || [];
|
|
||||||
return envs;
|
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
name: 'default',
|
|
||||||
enabled: false,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderFeatures = () => {
|
|
||||||
if (loading) {
|
|
||||||
return loadingFeatures.map((feature: IFeatureToggleListItem) => {
|
|
||||||
return (
|
|
||||||
<FeatureToggleListNewItem
|
|
||||||
key={feature.name}
|
|
||||||
name={feature.name}
|
|
||||||
type={feature.type}
|
|
||||||
environments={feature.environments}
|
|
||||||
projectId={projectId}
|
|
||||||
createdAt={new Date().toISOString()}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return page.map((feature: IFeatureToggleListItem) => {
|
|
||||||
return (
|
|
||||||
<FeatureToggleListNewItem
|
|
||||||
key={feature.name}
|
|
||||||
name={feature.name}
|
|
||||||
type={feature.type}
|
|
||||||
environments={feature.environments}
|
|
||||||
projectId={projectId}
|
|
||||||
lastSeenAt={feature.lastSeenAt}
|
|
||||||
createdAt={feature.createdAt}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const ariaSort = (field: string) => {
|
|
||||||
return field === sortOpt.field
|
|
||||||
? sortOpt.direction
|
|
||||||
? 'ascending'
|
|
||||||
: 'descending'
|
|
||||||
: undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Table>
|
|
||||||
<TableHead>
|
|
||||||
<TableRow>
|
|
||||||
<TableCell
|
|
||||||
className={classnames(
|
|
||||||
styles.tableCell,
|
|
||||||
styles.tableCellStatus,
|
|
||||||
styles.tableCellHeader,
|
|
||||||
styles.tableCellHeaderSortable
|
|
||||||
)}
|
|
||||||
align="left"
|
|
||||||
aria-sort={ariaSort('lastSeenAt')}
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
data-loading
|
|
||||||
onClick={() => updateSort('lastSeenAt')}
|
|
||||||
className={styles.sortButton}
|
|
||||||
>
|
|
||||||
Last use
|
|
||||||
</button>
|
|
||||||
</TableCell>
|
|
||||||
<TableCell
|
|
||||||
className={classnames(
|
|
||||||
styles.tableCell,
|
|
||||||
styles.tableCellType,
|
|
||||||
styles.tableCellHeader,
|
|
||||||
styles.tableCellHeaderSortable
|
|
||||||
)}
|
|
||||||
align="center"
|
|
||||||
aria-sort={ariaSort('type')}
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
data-loading
|
|
||||||
onClick={() => updateSort('type')}
|
|
||||||
className={styles.sortButton}
|
|
||||||
>
|
|
||||||
Type
|
|
||||||
</button>
|
|
||||||
</TableCell>
|
|
||||||
<TableCell
|
|
||||||
className={classnames(
|
|
||||||
styles.tableCell,
|
|
||||||
styles.tableCellName,
|
|
||||||
styles.tableCellHeader,
|
|
||||||
styles.tableCellHeaderSortable
|
|
||||||
)}
|
|
||||||
align="left"
|
|
||||||
aria-sort={ariaSort('name')}
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
data-loading
|
|
||||||
onClick={() => updateSort('name')}
|
|
||||||
className={styles.sortButton}
|
|
||||||
>
|
|
||||||
Name
|
|
||||||
</button>
|
|
||||||
</TableCell>
|
|
||||||
<TableCell
|
|
||||||
className={classnames(
|
|
||||||
styles.tableCell,
|
|
||||||
styles.tableCellCreated,
|
|
||||||
styles.tableCellHeader,
|
|
||||||
styles.tableCellHeaderSortable
|
|
||||||
)}
|
|
||||||
align="left"
|
|
||||||
aria-sort={ariaSort('createdAt')}
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
data-loading
|
|
||||||
onClick={() => updateSort('createdAt')}
|
|
||||||
className={styles.sortButton}
|
|
||||||
>
|
|
||||||
Created
|
|
||||||
</button>
|
|
||||||
</TableCell>
|
|
||||||
{getEnvironments().map((env: any) => {
|
|
||||||
return (
|
|
||||||
<TableCell
|
|
||||||
key={env.name}
|
|
||||||
className={classnames(
|
|
||||||
styles.tableCell,
|
|
||||||
styles.tableCellEnv,
|
|
||||||
styles.tableCellHeader,
|
|
||||||
styles.tableCellHeaderSortable
|
|
||||||
)}
|
|
||||||
align="center"
|
|
||||||
>
|
|
||||||
<StringTruncator
|
|
||||||
text={env.name}
|
|
||||||
maxLength={15}
|
|
||||||
maxWidth="90"
|
|
||||||
data-loading
|
|
||||||
/>
|
|
||||||
</TableCell>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</TableRow>
|
|
||||||
</TableHead>
|
|
||||||
<TableBody>{renderFeatures()}</TableBody>
|
|
||||||
</Table>
|
|
||||||
<PaginateUI
|
|
||||||
pages={pages}
|
|
||||||
pageIndex={pageIndex}
|
|
||||||
setPageIndex={setPageIndex}
|
|
||||||
nextPage={nextPage}
|
|
||||||
prevPage={prevPage}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default FeatureToggleListNew;
|
|
@ -1,25 +0,0 @@
|
|||||||
import { Tooltip } from '@mui/material';
|
|
||||||
import { useLocationSettings } from 'hooks/useLocationSettings';
|
|
||||||
import { formatDateYMD, formatDateYMDHMS } from 'utils/formatDate';
|
|
||||||
|
|
||||||
interface ICreatedAtProps {
|
|
||||||
time: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const CreatedAt = ({ time }: ICreatedAtProps) => {
|
|
||||||
const { locationSettings } = useLocationSettings();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Tooltip
|
|
||||||
title={`Created at ${formatDateYMDHMS(
|
|
||||||
time,
|
|
||||||
locationSettings.locale
|
|
||||||
)}`}
|
|
||||||
arrow
|
|
||||||
>
|
|
||||||
<span>{formatDateYMD(time, locationSettings.locale)}</span>
|
|
||||||
</Tooltip>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default CreatedAt;
|
|
@ -1,158 +0,0 @@
|
|||||||
import React, { useRef, useState } from 'react';
|
|
||||||
import { TableCell, TableRow } from '@mui/material';
|
|
||||||
import { useStyles } from '../FeatureToggleListNew.styles';
|
|
||||||
import useToggleFeatureByEnv from 'hooks/api/actions/useToggleFeatureByEnv/useToggleFeatureByEnv';
|
|
||||||
import { IEnvironments } from 'interfaces/featureToggle';
|
|
||||||
import useToast from 'hooks/useToast';
|
|
||||||
import { getTogglePath } from 'utils/routePathHelpers';
|
|
||||||
import FeatureStatus from 'component/feature/FeatureView/FeatureStatus/FeatureStatus';
|
|
||||||
import FeatureType from 'component/feature/FeatureView/FeatureType/FeatureType';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import CreatedAt from './CreatedAt';
|
|
||||||
import useProject from 'hooks/api/getters/useProject/useProject';
|
|
||||||
import { UPDATE_FEATURE_ENVIRONMENT } from 'component/providers/AccessProvider/permissions';
|
|
||||||
import PermissionSwitch from 'component/common/PermissionSwitch/PermissionSwitch';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import { ENVIRONMENT_STRATEGY_ERROR } from 'constants/apiErrors';
|
|
||||||
import EnvironmentStrategyDialog from 'component/common/EnvironmentStrategiesDialog/EnvironmentStrategyDialog';
|
|
||||||
|
|
||||||
interface IFeatureToggleListNewItemProps {
|
|
||||||
name: string;
|
|
||||||
type: string;
|
|
||||||
environments: IEnvironments[];
|
|
||||||
projectId: string;
|
|
||||||
lastSeenAt?: string;
|
|
||||||
createdAt: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const FeatureToggleListNewItem = ({
|
|
||||||
name,
|
|
||||||
lastSeenAt,
|
|
||||||
type,
|
|
||||||
environments,
|
|
||||||
projectId,
|
|
||||||
createdAt,
|
|
||||||
}: IFeatureToggleListNewItemProps) => {
|
|
||||||
const { setToastData, setToastApiError } = useToast();
|
|
||||||
const { toggleFeatureByEnvironment } = useToggleFeatureByEnv(
|
|
||||||
projectId,
|
|
||||||
name
|
|
||||||
);
|
|
||||||
|
|
||||||
const { refetch } = useProject(projectId);
|
|
||||||
const { classes: styles } = useStyles();
|
|
||||||
const ref = useRef<HTMLButtonElement>(null);
|
|
||||||
const [showInfoBox, setShowInfoBox] = useState(false);
|
|
||||||
const [environmentName, setEnvironmentName] = useState('');
|
|
||||||
|
|
||||||
const closeInfoBox = () => {
|
|
||||||
setShowInfoBox(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleToggle = (env: IEnvironments) => {
|
|
||||||
toggleFeatureByEnvironment(env.name, env.enabled)
|
|
||||||
.then(() => {
|
|
||||||
setToastData({
|
|
||||||
type: 'success',
|
|
||||||
title: 'Updated toggle status',
|
|
||||||
text: 'Successfully updated toggle status.',
|
|
||||||
});
|
|
||||||
refetch();
|
|
||||||
})
|
|
||||||
.catch(e => {
|
|
||||||
if (e.message === ENVIRONMENT_STRATEGY_ERROR) {
|
|
||||||
setShowInfoBox(true);
|
|
||||||
} else {
|
|
||||||
setToastApiError(e.message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<TableRow className={styles.tableRow}>
|
|
||||||
<TableCell
|
|
||||||
className={classNames(
|
|
||||||
styles.tableCell,
|
|
||||||
styles.tableCellStatus
|
|
||||||
)}
|
|
||||||
align="left"
|
|
||||||
>
|
|
||||||
<FeatureStatus
|
|
||||||
lastSeenAt={lastSeenAt}
|
|
||||||
tooltipPlacement="left"
|
|
||||||
/>
|
|
||||||
</TableCell>
|
|
||||||
<TableCell
|
|
||||||
className={classNames(
|
|
||||||
styles.tableCell,
|
|
||||||
styles.tableCellType
|
|
||||||
)}
|
|
||||||
align="center"
|
|
||||||
>
|
|
||||||
<FeatureType type={type} />
|
|
||||||
</TableCell>
|
|
||||||
<TableCell
|
|
||||||
className={classNames(
|
|
||||||
styles.tableCell,
|
|
||||||
styles.tableCellName
|
|
||||||
)}
|
|
||||||
align="left"
|
|
||||||
>
|
|
||||||
<Link
|
|
||||||
to={getTogglePath(projectId, name)}
|
|
||||||
className={styles.link}
|
|
||||||
>
|
|
||||||
<span data-loading>{name}</span>
|
|
||||||
</Link>
|
|
||||||
</TableCell>
|
|
||||||
<TableCell
|
|
||||||
className={classNames(
|
|
||||||
styles.tableCell,
|
|
||||||
styles.tableCellCreated
|
|
||||||
)}
|
|
||||||
align="left"
|
|
||||||
>
|
|
||||||
<CreatedAt time={createdAt} />
|
|
||||||
</TableCell>
|
|
||||||
|
|
||||||
{environments.map((env: IEnvironments) => {
|
|
||||||
return (
|
|
||||||
<TableCell
|
|
||||||
className={classNames(
|
|
||||||
styles.tableCell,
|
|
||||||
styles.tableCellEnv
|
|
||||||
)}
|
|
||||||
align="center"
|
|
||||||
key={env.name}
|
|
||||||
>
|
|
||||||
<span data-loading style={{ display: 'block' }}>
|
|
||||||
<PermissionSwitch
|
|
||||||
checked={env.enabled}
|
|
||||||
environmentId={env.name}
|
|
||||||
projectId={projectId}
|
|
||||||
permission={UPDATE_FEATURE_ENVIRONMENT}
|
|
||||||
inputProps={{ 'aria-label': env.name }}
|
|
||||||
ref={ref}
|
|
||||||
onClick={() => {
|
|
||||||
handleToggle(env);
|
|
||||||
setEnvironmentName(env.name);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
</TableCell>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</TableRow>
|
|
||||||
<EnvironmentStrategyDialog
|
|
||||||
open={showInfoBox}
|
|
||||||
onClose={closeInfoBox}
|
|
||||||
projectId={projectId}
|
|
||||||
featureId={name}
|
|
||||||
environmentName={environmentName}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default FeatureToggleListNewItem;
|
|
@ -1,105 +0,0 @@
|
|||||||
import { IFeatureToggleListItem } from 'interfaces/featureToggle';
|
|
||||||
|
|
||||||
const loadingFeatures: IFeatureToggleListItem[] = [
|
|
||||||
{
|
|
||||||
type: 'release',
|
|
||||||
name: 'loading1',
|
|
||||||
createdAt: '2006-01-02T15:04:05Z',
|
|
||||||
environments: [
|
|
||||||
{
|
|
||||||
name: ':global:',
|
|
||||||
enabled: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'release',
|
|
||||||
name: 'loadg2',
|
|
||||||
createdAt: '2006-01-02T15:04:05Z',
|
|
||||||
environments: [
|
|
||||||
{
|
|
||||||
name: ':global:',
|
|
||||||
enabled: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'release',
|
|
||||||
name: 'loading3',
|
|
||||||
createdAt: '2006-01-02T15:04:05Z',
|
|
||||||
environments: [
|
|
||||||
{
|
|
||||||
name: ':global:',
|
|
||||||
enabled: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'release',
|
|
||||||
name: 'loadi4',
|
|
||||||
createdAt: '2006-01-02T15:04:05Z',
|
|
||||||
environments: [
|
|
||||||
{
|
|
||||||
name: ':global:',
|
|
||||||
enabled: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'release',
|
|
||||||
name: 'loadi5',
|
|
||||||
createdAt: '2006-01-02T15:04:05Z',
|
|
||||||
environments: [
|
|
||||||
{
|
|
||||||
name: ':global:',
|
|
||||||
enabled: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'release',
|
|
||||||
name: 'loadg6',
|
|
||||||
createdAt: '2006-01-02T15:04:05Z',
|
|
||||||
environments: [
|
|
||||||
{
|
|
||||||
name: ':global:',
|
|
||||||
enabled: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'release',
|
|
||||||
name: 'loading7',
|
|
||||||
createdAt: '2006-01-02T15:04:05Z',
|
|
||||||
environments: [
|
|
||||||
{
|
|
||||||
name: ':global:',
|
|
||||||
enabled: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'release',
|
|
||||||
name: 'ln8',
|
|
||||||
createdAt: '2006-01-02T15:04:05Z',
|
|
||||||
environments: [
|
|
||||||
{
|
|
||||||
name: ':global:',
|
|
||||||
enabled: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'release',
|
|
||||||
name: 'load9',
|
|
||||||
createdAt: '2006-01-02T15:04:05Z',
|
|
||||||
environments: [
|
|
||||||
{
|
|
||||||
name: ':global:',
|
|
||||||
enabled: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export default loadingFeatures;
|
|
@ -136,5 +136,3 @@ const useFeatureMetricsApplications = (featureId: string): Set<string> => {
|
|||||||
|
|
||||||
return new Set(applications);
|
return new Set(applications);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default FeatureMetrics;
|
|
||||||
|
@ -1,98 +0,0 @@
|
|||||||
import { useContext, useEffect, useState } from 'react';
|
|
||||||
import * as jsonpatch from 'fast-json-patch';
|
|
||||||
import { TextField } from '@mui/material';
|
|
||||||
import PermissionButton from 'component/common/PermissionButton/PermissionButton';
|
|
||||||
import FeatureTypeSelect from './FeatureTypeSelect/FeatureTypeSelect';
|
|
||||||
import AccessContext from 'contexts/AccessContext';
|
|
||||||
import { UPDATE_FEATURE } from 'component/providers/AccessProvider/permissions';
|
|
||||||
import { useFeature } from 'hooks/api/getters/useFeature/useFeature';
|
|
||||||
import useToast from 'hooks/useToast';
|
|
||||||
import useFeatureApi from 'hooks/api/actions/useFeatureApi/useFeatureApi';
|
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
|
||||||
import { formatUnknownError } from 'utils/formatUnknownError';
|
|
||||||
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
|
||||||
|
|
||||||
const FeatureSettingsMetadata = () => {
|
|
||||||
const { hasAccess } = useContext(AccessContext);
|
|
||||||
const projectId = useRequiredPathParam('projectId');
|
|
||||||
const featureId = useRequiredPathParam('featureId');
|
|
||||||
const { feature, refetchFeature } = useFeature(projectId, featureId);
|
|
||||||
const [description, setDescription] = useState(feature.description);
|
|
||||||
const [type, setType] = useState(feature.type);
|
|
||||||
const editable = hasAccess(UPDATE_FEATURE, projectId);
|
|
||||||
const { setToastData, setToastApiError } = useToast();
|
|
||||||
const [dirty, setDirty] = useState(false);
|
|
||||||
const { patchFeatureToggle } = useFeatureApi();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setType(feature.type);
|
|
||||||
setDescription(feature.description);
|
|
||||||
}, [feature]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (description !== feature.description || type !== feature.type) {
|
|
||||||
setDirty(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setDirty(false);
|
|
||||||
/* eslint-disable-next-line */
|
|
||||||
}, [description, type]);
|
|
||||||
|
|
||||||
const createPatch = () => {
|
|
||||||
const comparison = { ...feature, type, description };
|
|
||||||
const patch = jsonpatch.compare(feature, comparison);
|
|
||||||
return patch;
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
|
||||||
try {
|
|
||||||
const patch = createPatch();
|
|
||||||
await patchFeatureToggle(projectId, featureId, patch);
|
|
||||||
setToastData({
|
|
||||||
title: 'Updated metadata',
|
|
||||||
type: 'success',
|
|
||||||
text: 'Successfully updated feature toggle metadata',
|
|
||||||
});
|
|
||||||
setDirty(false);
|
|
||||||
refetchFeature();
|
|
||||||
} catch (error: unknown) {
|
|
||||||
setToastApiError(formatUnknownError(error));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<FeatureTypeSelect
|
|
||||||
value={type}
|
|
||||||
id="feature-type-select"
|
|
||||||
onChange={setType}
|
|
||||||
label="Feature type"
|
|
||||||
editable={editable}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<TextField
|
|
||||||
label="Description"
|
|
||||||
required
|
|
||||||
multiline
|
|
||||||
rows={4}
|
|
||||||
variant="outlined"
|
|
||||||
value={description}
|
|
||||||
onChange={e => setDescription(e.target.value)}
|
|
||||||
/>
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={dirty}
|
|
||||||
show={
|
|
||||||
<PermissionButton
|
|
||||||
permission={UPDATE_FEATURE}
|
|
||||||
onClick={handleSubmit}
|
|
||||||
projectId={projectId}
|
|
||||||
>
|
|
||||||
Save changes
|
|
||||||
</PermissionButton>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default FeatureSettingsMetadata;
|
|
@ -1,119 +0,0 @@
|
|||||||
import { useContext, useMemo, useState } from 'react';
|
|
||||||
import { Add } from '@mui/icons-material';
|
|
||||||
import { Link, useNavigate } from 'react-router-dom';
|
|
||||||
import AccessContext from 'contexts/AccessContext';
|
|
||||||
import { SearchField } from 'component/common/SearchField/SearchField';
|
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
|
||||||
import { PageHeader } from 'component/common/PageHeader/PageHeader';
|
|
||||||
import { PageContent } from 'component/common/PageContent/PageContent';
|
|
||||||
import ResponsiveButton from 'component/common/ResponsiveButton/ResponsiveButton';
|
|
||||||
import FeatureToggleListNew from 'component/feature/FeatureToggleListNew/FeatureToggleListNew';
|
|
||||||
import { IFeatureToggleListItem } from 'interfaces/featureToggle';
|
|
||||||
import { getCreateTogglePath } from 'utils/routePathHelpers';
|
|
||||||
import { useStyles } from './ProjectFeatureToggles.styles';
|
|
||||||
import { CREATE_FEATURE } from 'component/providers/AccessProvider/permissions';
|
|
||||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
|
||||||
import classnames from 'classnames';
|
|
||||||
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
|
||||||
|
|
||||||
interface IProjectFeatureTogglesProps {
|
|
||||||
features: IFeatureToggleListItem[];
|
|
||||||
loading: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
export const ProjectFeatureToggles = ({
|
|
||||||
features,
|
|
||||||
loading,
|
|
||||||
}: IProjectFeatureTogglesProps) => {
|
|
||||||
const { classes: styles } = useStyles();
|
|
||||||
const projectId = useRequiredPathParam('projectId');
|
|
||||||
const navigate = useNavigate();
|
|
||||||
const { hasAccess } = useContext(AccessContext);
|
|
||||||
const { uiConfig } = useUiConfig();
|
|
||||||
const [filter, setFilter] = useState('');
|
|
||||||
|
|
||||||
const filteredFeatures = useMemo(() => {
|
|
||||||
const regExp = new RegExp(filter, 'i');
|
|
||||||
return filter
|
|
||||||
? features.filter(feature => regExp.test(feature.name))
|
|
||||||
: features;
|
|
||||||
}, [features, filter]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<PageContent
|
|
||||||
className={styles.container}
|
|
||||||
bodyClass={styles.bodyClass}
|
|
||||||
header={
|
|
||||||
<PageHeader
|
|
||||||
className={styles.title}
|
|
||||||
title={`Project feature toggles (${filteredFeatures.length})`}
|
|
||||||
actions={
|
|
||||||
<div className={styles.actionsContainer}>
|
|
||||||
<SearchField
|
|
||||||
initialValue={filter}
|
|
||||||
updateValue={setFilter}
|
|
||||||
className={classnames(styles.search, {
|
|
||||||
skeleton: loading,
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ResponsiveButton
|
|
||||||
onClick={() =>
|
|
||||||
navigate(
|
|
||||||
getCreateTogglePath(
|
|
||||||
projectId,
|
|
||||||
uiConfig.flags.E
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
maxWidth="700px"
|
|
||||||
Icon={Add}
|
|
||||||
projectId={projectId}
|
|
||||||
permission={CREATE_FEATURE}
|
|
||||||
className={styles.button}
|
|
||||||
>
|
|
||||||
New feature toggle
|
|
||||||
</ResponsiveButton>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={filteredFeatures.length > 0}
|
|
||||||
show={
|
|
||||||
<FeatureToggleListNew
|
|
||||||
features={filteredFeatures}
|
|
||||||
loading={loading}
|
|
||||||
projectId={projectId}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
elseShow={
|
|
||||||
<>
|
|
||||||
<p data-loading className={styles.noTogglesFound}>
|
|
||||||
No feature toggles added yet.
|
|
||||||
</p>
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={hasAccess(CREATE_FEATURE, projectId)}
|
|
||||||
show={
|
|
||||||
<Link
|
|
||||||
to={getCreateTogglePath(
|
|
||||||
projectId,
|
|
||||||
uiConfig.flags.E
|
|
||||||
)}
|
|
||||||
className={styles.link}
|
|
||||||
data-loading
|
|
||||||
>
|
|
||||||
Add your first toggle
|
|
||||||
</Link>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</PageContent>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,36 +0,0 @@
|
|||||||
import useProject from 'hooks/api/getters/useProject/useProject';
|
|
||||||
import useAPI from '../useApi/useApi';
|
|
||||||
|
|
||||||
const useToggleFeatureByEnv = (projectId: string, name: string) => {
|
|
||||||
const { refetch } = useProject(projectId);
|
|
||||||
const { makeRequest, createRequest, errors } = useAPI({
|
|
||||||
propagateErrors: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const toggleFeatureByEnvironment = async (
|
|
||||||
env: string,
|
|
||||||
enabled: boolean
|
|
||||||
) => {
|
|
||||||
const path = getToggleAPIPath(env, enabled);
|
|
||||||
const req = createRequest(path, { method: 'POST' });
|
|
||||||
|
|
||||||
try {
|
|
||||||
const res = await makeRequest(req.caller, req.id);
|
|
||||||
refetch();
|
|
||||||
return res;
|
|
||||||
} catch (e) {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const getToggleAPIPath = (env: string, enabled: boolean) => {
|
|
||||||
if (enabled) {
|
|
||||||
return `api/admin/projects/${projectId}/features/${name}/environments/${env}/off`;
|
|
||||||
}
|
|
||||||
return `api/admin/projects/${projectId}/features/${name}/environments/${env}/on`;
|
|
||||||
};
|
|
||||||
|
|
||||||
return { toggleFeatureByEnvironment, errors };
|
|
||||||
};
|
|
||||||
|
|
||||||
export default useToggleFeatureByEnv;
|
|
@ -18,11 +18,6 @@ export interface IUsersSortOutput {
|
|||||||
setSort: React.Dispatch<React.SetStateAction<IUsersSort>>;
|
setSort: React.Dispatch<React.SetStateAction<IUsersSort>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IUsersFilterSortOption {
|
|
||||||
type: UsersSortType;
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store the users sort state globally, and in localStorage.
|
// Store the users sort state globally, and in localStorage.
|
||||||
// When changing the format of IUsersSort, change the version as well.
|
// When changing the format of IUsersSort, change the version as well.
|
||||||
const useUsersSortState = createPersistentGlobalStateHook<IUsersSort>(
|
const useUsersSortState = createPersistentGlobalStateHook<IUsersSort>(
|
||||||
@ -45,15 +40,6 @@ export const useUsersSort = (users: IUser[]): IUsersSortOutput => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const createUsersFilterSortOptions = (): IUsersFilterSortOption[] => {
|
|
||||||
return [
|
|
||||||
{ type: 'created', name: 'Created' },
|
|
||||||
{ type: 'name', name: 'Name' },
|
|
||||||
{ type: 'role', name: 'Role' },
|
|
||||||
{ type: 'last-seen', name: 'Last seen' },
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
const sortAscendingUsers = (
|
const sortAscendingUsers = (
|
||||||
users: IUser[],
|
users: IUser[],
|
||||||
roles: IRole[],
|
roles: IRole[],
|
||||||
|
@ -14,14 +14,6 @@ export interface IEnvironments {
|
|||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IFeatureTogglePayload {
|
|
||||||
description: string;
|
|
||||||
name: string;
|
|
||||||
projectId: string;
|
|
||||||
type: string;
|
|
||||||
impressionData: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IFeatureToggle {
|
export interface IFeatureToggle {
|
||||||
stale: boolean;
|
stale: boolean;
|
||||||
archived: boolean;
|
archived: boolean;
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
export interface IInvoice {
|
|
||||||
amountFormatted: string;
|
|
||||||
invoicePDF: string;
|
|
||||||
invoiceURL: string;
|
|
||||||
paid: boolean;
|
|
||||||
status: string;
|
|
||||||
dueDate?: Date;
|
|
||||||
}
|
|
@ -3,24 +3,6 @@ import { formatDateYMDHMS } from 'utils/formatDate';
|
|||||||
import { ILocationSettings } from 'hooks/useLocationSettings';
|
import { ILocationSettings } from 'hooks/useLocationSettings';
|
||||||
import { CURRENT_TIME_CONTEXT_FIELD } from 'utils/operatorsForContext';
|
import { CURRENT_TIME_CONTEXT_FIELD } from 'utils/operatorsForContext';
|
||||||
|
|
||||||
export const formatConstraintValuesOrValue = (
|
|
||||||
constraint: IConstraint,
|
|
||||||
locationSettings: ILocationSettings
|
|
||||||
): string | undefined => {
|
|
||||||
return (
|
|
||||||
formatConstraintValues(constraint) ??
|
|
||||||
formatConstraintValue(constraint, locationSettings)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const formatConstraintValues = (
|
|
||||||
constraint: IConstraint
|
|
||||||
): string | undefined => {
|
|
||||||
if (constraint.values && constraint.values.length > 0) {
|
|
||||||
return constraint.values.join(', ');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const formatConstraintValue = (
|
export const formatConstraintValue = (
|
||||||
constraint: IConstraint,
|
constraint: IConstraint,
|
||||||
locationSettings: ILocationSettings
|
locationSettings: ILocationSettings
|
||||||
|
@ -31,7 +31,6 @@ export const FEATURE_ENVIRONMENT_ACCORDION = 'FEATURE_ENVIRONMENT_ACCORDION';
|
|||||||
export const ADD_NEW_STRATEGY_ID = 'ADD_NEW_STRATEGY_ID';
|
export const ADD_NEW_STRATEGY_ID = 'ADD_NEW_STRATEGY_ID';
|
||||||
export const ROLLOUT_SLIDER_ID = 'ROLLOUT_SLIDER_ID';
|
export const ROLLOUT_SLIDER_ID = 'ROLLOUT_SLIDER_ID';
|
||||||
export const DIALOGUE_CONFIRM_ID = 'DIALOGUE_CONFIRM_ID';
|
export const DIALOGUE_CONFIRM_ID = 'DIALOGUE_CONFIRM_ID';
|
||||||
export const CONSTRAINT_AUTOCOMPLETE_ID = 'CONSTRAINT_AUTOCOMPLETE_ID';
|
|
||||||
export const FLEXIBLE_STRATEGY_STICKINESS_ID =
|
export const FLEXIBLE_STRATEGY_STICKINESS_ID =
|
||||||
'FLEXIBLE_STRATEGY_STICKINESS_ID';
|
'FLEXIBLE_STRATEGY_STICKINESS_ID';
|
||||||
export const FLEXIBLE_STRATEGY_GROUP_ID = 'FLEXIBLE_STRATEGY_GROUP_ID';
|
export const FLEXIBLE_STRATEGY_GROUP_ID = 'FLEXIBLE_STRATEGY_GROUP_ID';
|
||||||
|
Loading…
Reference in New Issue
Block a user