mirror of
https://github.com/Unleash/unleash.git
synced 2025-06-04 01:18:20 +02:00
commit
407e3a5f55
@ -55,7 +55,7 @@ export const ReportTable = ({ projectId, features }: IReportTableProps) => {
|
|||||||
const initialState = useMemo(
|
const initialState = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
hiddenColumns: [],
|
hiddenColumns: [],
|
||||||
sortBy: [{ id: 'createdAt', desc: true }],
|
sortBy: [{ id: 'createdAt' }],
|
||||||
}),
|
}),
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
@ -119,6 +119,7 @@ const UsersList = () => {
|
|||||||
Cell: DateCell,
|
Cell: DateCell,
|
||||||
disableGlobalFilter: true,
|
disableGlobalFilter: true,
|
||||||
sortType: 'date',
|
sortType: 'date',
|
||||||
|
minWidth: 120,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: 'Avatar',
|
Header: 'Avatar',
|
||||||
@ -169,6 +170,7 @@ const UsersList = () => {
|
|||||||
),
|
),
|
||||||
disableGlobalFilter: true,
|
disableGlobalFilter: true,
|
||||||
sortType: 'date',
|
sortType: 'date',
|
||||||
|
minWidth: 150,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: 'Actions',
|
Header: 'Actions',
|
||||||
@ -193,7 +195,7 @@ const UsersList = () => {
|
|||||||
|
|
||||||
const initialState = useMemo(() => {
|
const initialState = useMemo(() => {
|
||||||
return {
|
return {
|
||||||
sortBy: [{ id: 'createdAt', desc: false }],
|
sortBy: [{ id: 'createdAt' }],
|
||||||
hiddenColumns: isBillingUsers ? [] : ['type'],
|
hiddenColumns: isBillingUsers ? [] : ['type'],
|
||||||
};
|
};
|
||||||
}, [isBillingUsers]);
|
}, [isBillingUsers]);
|
||||||
|
@ -1,50 +0,0 @@
|
|||||||
import { useFeaturesArchive } from 'hooks/api/getters/useFeaturesArchive/useFeaturesArchive';
|
|
||||||
import { FeatureToggleList } from '../feature/FeatureToggleList/FeatureToggleArchiveList';
|
|
||||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
|
||||||
import { useFeaturesFilter } from 'hooks/useFeaturesFilter';
|
|
||||||
import { useFeatureArchiveApi } from 'hooks/api/actions/useFeatureArchiveApi/useReviveFeatureApi';
|
|
||||||
import useToast from 'hooks/useToast';
|
|
||||||
import { useFeaturesSort } from 'hooks/useFeaturesSort';
|
|
||||||
|
|
||||||
export const ArchiveListContainer = () => {
|
|
||||||
const { setToastData, setToastApiError } = useToast();
|
|
||||||
const { uiConfig } = useUiConfig();
|
|
||||||
const { reviveFeature } = useFeatureArchiveApi();
|
|
||||||
|
|
||||||
const {
|
|
||||||
archivedFeatures = [],
|
|
||||||
refetchArchived,
|
|
||||||
loading,
|
|
||||||
} = useFeaturesArchive();
|
|
||||||
|
|
||||||
const { filtered, filter, setFilter } = useFeaturesFilter(archivedFeatures);
|
|
||||||
const { sorted, sort, setSort } = useFeaturesSort(filtered);
|
|
||||||
|
|
||||||
const onRevive = (feature: string) => {
|
|
||||||
reviveFeature(feature)
|
|
||||||
.then(refetchArchived)
|
|
||||||
.then(() =>
|
|
||||||
setToastData({
|
|
||||||
type: 'success',
|
|
||||||
title: "And we're back!",
|
|
||||||
text: 'The feature toggle has been revived.',
|
|
||||||
confetti: true,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.catch(e => setToastApiError(e.toString()));
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<FeatureToggleList
|
|
||||||
features={sorted}
|
|
||||||
loading={loading}
|
|
||||||
onRevive={onRevive}
|
|
||||||
flags={uiConfig.flags}
|
|
||||||
filter={filter}
|
|
||||||
setFilter={setFilter}
|
|
||||||
sort={sort}
|
|
||||||
setSort={setSort}
|
|
||||||
isArchive
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
360
frontend/src/component/archive/ArchiveTable/ArchiveTable.tsx
Normal file
360
frontend/src/component/archive/ArchiveTable/ArchiveTable.tsx
Normal file
@ -0,0 +1,360 @@
|
|||||||
|
import { PageContent } from 'component/common/PageContent/PageContent';
|
||||||
|
import { PageHeader } from 'component/common/PageHeader/PageHeader';
|
||||||
|
import {
|
||||||
|
SortableTableHeader,
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TablePlaceholder,
|
||||||
|
TableRow,
|
||||||
|
} from 'component/common/Table';
|
||||||
|
import { SortingRule, useFlexLayout, useSortBy, useTable } from 'react-table';
|
||||||
|
import { SearchHighlightProvider } from 'component/common/Table/SearchHighlightContext/SearchHighlightContext';
|
||||||
|
import { useMediaQuery } from '@mui/material';
|
||||||
|
import { sortTypes } from 'utils/sortTypes';
|
||||||
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
|
import { HighlightCell } from 'component/common/Table/cells/HighlightCell/HighlightCell';
|
||||||
|
import { DateCell } from 'component/common/Table/cells/DateCell/DateCell';
|
||||||
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
|
import { Search } from 'component/common/Search/Search';
|
||||||
|
import { FeatureTypeCell } from '../../common/Table/cells/FeatureTypeCell/FeatureTypeCell';
|
||||||
|
import { FeatureSeenCell } from '../../common/Table/cells/FeatureSeenCell/FeatureSeenCell';
|
||||||
|
import { LinkCell } from '../../common/Table/cells/LinkCell/LinkCell';
|
||||||
|
import { FeatureStaleCell } from '../../feature/FeatureToggleList/FeatureStaleCell/FeatureStaleCell';
|
||||||
|
import { ReviveArchivedFeatureCell } from 'component/archive/ArchiveTable/ReviveArchivedFeatureCell/ReviveArchivedFeatureCell';
|
||||||
|
import { useStyles } from '../../feature/FeatureToggleList/styles';
|
||||||
|
import { featuresPlaceholder } from '../../feature/FeatureToggleList/FeatureToggleListTable';
|
||||||
|
import theme from 'themes/theme';
|
||||||
|
import { FeatureSchema } from 'openapi';
|
||||||
|
import { useFeatureArchiveApi } from 'hooks/api/actions/useFeatureArchiveApi/useReviveFeatureApi';
|
||||||
|
import useToast from 'hooks/useToast';
|
||||||
|
import { formatUnknownError } from 'utils/formatUnknownError';
|
||||||
|
import { useSearch } from 'hooks/useSearch';
|
||||||
|
import { FeatureArchivedCell } from './FeatureArchivedCell/FeatureArchivedCell';
|
||||||
|
import { useVirtualizedRange } from 'hooks/useVirtualizedRange';
|
||||||
|
import { useSearchParams } from 'react-router-dom';
|
||||||
|
|
||||||
|
export interface IFeaturesArchiveTableProps {
|
||||||
|
archivedFeatures: FeatureSchema[];
|
||||||
|
title: string;
|
||||||
|
refetch: () => void;
|
||||||
|
loading: boolean;
|
||||||
|
storedParams: SortingRule<string>;
|
||||||
|
setStoredParams: (
|
||||||
|
newValue:
|
||||||
|
| SortingRule<string>
|
||||||
|
| ((prev: SortingRule<string>) => SortingRule<string>)
|
||||||
|
) => SortingRule<string>;
|
||||||
|
projectId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ArchiveTable = ({
|
||||||
|
archivedFeatures = [],
|
||||||
|
loading,
|
||||||
|
refetch,
|
||||||
|
storedParams,
|
||||||
|
setStoredParams,
|
||||||
|
title,
|
||||||
|
projectId,
|
||||||
|
}: IFeaturesArchiveTableProps) => {
|
||||||
|
const rowHeight = theme.shape.tableRowHeight;
|
||||||
|
const { classes } = useStyles();
|
||||||
|
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
|
||||||
|
const isMediumScreen = useMediaQuery(theme.breakpoints.down('lg'));
|
||||||
|
const { setToastData, setToastApiError } = useToast();
|
||||||
|
|
||||||
|
const [searchParams, setSearchParams] = useSearchParams();
|
||||||
|
const { reviveFeature } = useFeatureArchiveApi();
|
||||||
|
|
||||||
|
const [searchValue, setSearchValue] = useState(
|
||||||
|
searchParams.get('search') || ''
|
||||||
|
);
|
||||||
|
|
||||||
|
const onRevive = useCallback(
|
||||||
|
async (feature: string) => {
|
||||||
|
try {
|
||||||
|
await reviveFeature(feature);
|
||||||
|
await refetch();
|
||||||
|
setToastData({
|
||||||
|
type: 'success',
|
||||||
|
title: "And we're back!",
|
||||||
|
text: 'The feature toggle has been revived.',
|
||||||
|
});
|
||||||
|
} catch (e: unknown) {
|
||||||
|
setToastApiError(formatUnknownError(e));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[refetch, reviveFeature, setToastApiError, setToastData]
|
||||||
|
);
|
||||||
|
|
||||||
|
const columns = useMemo(
|
||||||
|
() => [
|
||||||
|
{
|
||||||
|
id: 'Seen',
|
||||||
|
Header: 'Seen',
|
||||||
|
width: 85,
|
||||||
|
canSort: true,
|
||||||
|
Cell: FeatureSeenCell,
|
||||||
|
accessor: 'lastSeenAt',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Header: 'Type',
|
||||||
|
accessor: 'type',
|
||||||
|
width: 85,
|
||||||
|
canSort: true,
|
||||||
|
Cell: FeatureTypeCell,
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Header: 'Feature toggle name',
|
||||||
|
accessor: 'name',
|
||||||
|
searchable: true,
|
||||||
|
minWidth: 100,
|
||||||
|
Cell: ({ value, row: { original } }: any) => (
|
||||||
|
<HighlightCell
|
||||||
|
value={value}
|
||||||
|
subtitle={original.description}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
sortType: 'alphanumeric',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Header: 'Created',
|
||||||
|
accessor: 'createdAt',
|
||||||
|
width: 150,
|
||||||
|
Cell: DateCell,
|
||||||
|
sortType: 'date',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Header: 'Archived',
|
||||||
|
accessor: 'archivedAt',
|
||||||
|
width: 150,
|
||||||
|
Cell: FeatureArchivedCell,
|
||||||
|
sortType: 'date',
|
||||||
|
},
|
||||||
|
...(!projectId
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
Header: 'Project ID',
|
||||||
|
accessor: 'project',
|
||||||
|
sortType: 'alphanumeric',
|
||||||
|
filterName: 'project',
|
||||||
|
searchable: true,
|
||||||
|
maxWidth: 170,
|
||||||
|
Cell: ({ value }: any) => (
|
||||||
|
<LinkCell
|
||||||
|
title={value}
|
||||||
|
to={`/projects/${value}`}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
{
|
||||||
|
Header: 'Status',
|
||||||
|
accessor: 'stale',
|
||||||
|
Cell: FeatureStaleCell,
|
||||||
|
sortType: 'boolean',
|
||||||
|
maxWidth: 120,
|
||||||
|
filterName: 'state',
|
||||||
|
filterParsing: (value: any) => (value ? 'stale' : 'active'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Header: 'Actions',
|
||||||
|
id: 'Actions',
|
||||||
|
align: 'center',
|
||||||
|
maxWidth: 85,
|
||||||
|
canSort: false,
|
||||||
|
disableGlobalFilter: true,
|
||||||
|
Cell: ({ row: { original } }: any) => (
|
||||||
|
<ReviveArchivedFeatureCell
|
||||||
|
project={original.project}
|
||||||
|
onRevive={() => onRevive(original.name)}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
// Always hidden -- for search
|
||||||
|
{
|
||||||
|
accessor: 'description',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
//eslint-disable-next-line
|
||||||
|
[projectId]
|
||||||
|
);
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: searchedData,
|
||||||
|
getSearchText,
|
||||||
|
getSearchContext,
|
||||||
|
} = useSearch(columns, searchValue, archivedFeatures);
|
||||||
|
|
||||||
|
const data = useMemo(
|
||||||
|
() => (loading ? featuresPlaceholder : searchedData),
|
||||||
|
[searchedData, loading]
|
||||||
|
);
|
||||||
|
|
||||||
|
const [initialState] = useState(() => ({
|
||||||
|
sortBy: [
|
||||||
|
{
|
||||||
|
id: searchParams.get('sort') || storedParams.id,
|
||||||
|
desc: searchParams.has('order')
|
||||||
|
? searchParams.get('order') === 'desc'
|
||||||
|
: storedParams.desc,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
hiddenColumns: ['description'],
|
||||||
|
}));
|
||||||
|
|
||||||
|
const {
|
||||||
|
headerGroups,
|
||||||
|
rows,
|
||||||
|
state: { sortBy },
|
||||||
|
getTableBodyProps,
|
||||||
|
getTableProps,
|
||||||
|
prepareRow,
|
||||||
|
setHiddenColumns,
|
||||||
|
} = useTable(
|
||||||
|
{
|
||||||
|
columns: columns as any[], // TODO: fix after `react-table` v8 update
|
||||||
|
data,
|
||||||
|
initialState,
|
||||||
|
sortTypes,
|
||||||
|
disableSortRemove: true,
|
||||||
|
autoResetSortBy: false,
|
||||||
|
},
|
||||||
|
useFlexLayout,
|
||||||
|
useSortBy
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const hiddenColumns = ['description'];
|
||||||
|
if (isMediumScreen) {
|
||||||
|
hiddenColumns.push('lastSeenAt', 'status');
|
||||||
|
}
|
||||||
|
if (isSmallScreen) {
|
||||||
|
hiddenColumns.push('type', 'createdAt');
|
||||||
|
}
|
||||||
|
setHiddenColumns(hiddenColumns);
|
||||||
|
}, [setHiddenColumns, isSmallScreen, isMediumScreen]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (loading) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const tableState: Record<string, string> = {};
|
||||||
|
tableState.sort = sortBy[0].id;
|
||||||
|
if (sortBy[0].desc) {
|
||||||
|
tableState.order = 'desc';
|
||||||
|
}
|
||||||
|
if (searchValue) {
|
||||||
|
tableState.search = searchValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
setSearchParams(tableState, {
|
||||||
|
replace: true,
|
||||||
|
});
|
||||||
|
setStoredParams({ id: sortBy[0].id, desc: sortBy[0].desc || false });
|
||||||
|
}, [loading, sortBy, searchValue]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||||
|
|
||||||
|
const [firstRenderedIndex, lastRenderedIndex] =
|
||||||
|
useVirtualizedRange(rowHeight);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PageContent
|
||||||
|
isLoading={loading}
|
||||||
|
header={
|
||||||
|
<PageHeader
|
||||||
|
title={`${title} (${
|
||||||
|
rows.length < data.length
|
||||||
|
? `${rows.length} of ${data.length}`
|
||||||
|
: data.length
|
||||||
|
})`}
|
||||||
|
actions={
|
||||||
|
<Search
|
||||||
|
initialValue={searchValue}
|
||||||
|
onChange={setSearchValue}
|
||||||
|
hasFilters
|
||||||
|
getSearchContext={getSearchContext}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<SearchHighlightProvider value={getSearchText(searchValue)}>
|
||||||
|
<Table
|
||||||
|
{...getTableProps()}
|
||||||
|
rowHeight={rowHeight}
|
||||||
|
style={{
|
||||||
|
height:
|
||||||
|
rowHeight * rows.length +
|
||||||
|
theme.shape.tableRowHeightCompact,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SortableTableHeader
|
||||||
|
headerGroups={headerGroups as any}
|
||||||
|
flex
|
||||||
|
/>
|
||||||
|
<TableBody {...getTableBodyProps()}>
|
||||||
|
{rows.map((row, index) => {
|
||||||
|
const isVirtual =
|
||||||
|
index < firstRenderedIndex ||
|
||||||
|
index > lastRenderedIndex;
|
||||||
|
|
||||||
|
if (isVirtual) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
prepareRow(row);
|
||||||
|
return (
|
||||||
|
<TableRow
|
||||||
|
hover
|
||||||
|
{...row.getRowProps()}
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
top:
|
||||||
|
index * rowHeight +
|
||||||
|
theme.shape.tableRowHeightCompact,
|
||||||
|
}}
|
||||||
|
className={classes.row}
|
||||||
|
>
|
||||||
|
{row.cells.map(cell => (
|
||||||
|
<TableCell
|
||||||
|
{...cell.getCellProps({
|
||||||
|
style: {
|
||||||
|
flex: cell.column.minWidth
|
||||||
|
? '1 0 auto'
|
||||||
|
: undefined,
|
||||||
|
},
|
||||||
|
})}
|
||||||
|
className={classes.cell}
|
||||||
|
>
|
||||||
|
{cell.render('Cell')}
|
||||||
|
</TableCell>
|
||||||
|
))}
|
||||||
|
</TableRow>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</SearchHighlightProvider>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={rows.length === 0 && searchValue?.length > 0}
|
||||||
|
show={
|
||||||
|
<TablePlaceholder>
|
||||||
|
No feature toggles found matching “
|
||||||
|
{searchValue}”
|
||||||
|
</TablePlaceholder>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={rows.length === 0 && searchValue?.length === 0}
|
||||||
|
show={
|
||||||
|
<TablePlaceholder>
|
||||||
|
None of the feature toggles where archived yet.
|
||||||
|
</TablePlaceholder>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</PageContent>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,36 @@
|
|||||||
|
import { VFC } from 'react';
|
||||||
|
import TimeAgo from 'react-timeago';
|
||||||
|
import { Tooltip, Typography } from '@mui/material';
|
||||||
|
import { formatDateYMD } from 'utils/formatDate';
|
||||||
|
import { TextCell } from 'component/common/Table/cells/TextCell/TextCell';
|
||||||
|
import { useLocationSettings } from 'hooks/useLocationSettings';
|
||||||
|
|
||||||
|
interface IFeatureArchivedCellProps {
|
||||||
|
value?: string | Date | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const FeatureArchivedCell: VFC<IFeatureArchivedCellProps> = ({
|
||||||
|
value: archivedAt,
|
||||||
|
}) => {
|
||||||
|
const { locationSettings } = useLocationSettings();
|
||||||
|
|
||||||
|
if (!archivedAt) return <TextCell />;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TextCell>
|
||||||
|
{archivedAt && (
|
||||||
|
<Tooltip
|
||||||
|
title={`Archived on: ${formatDateYMD(
|
||||||
|
archivedAt,
|
||||||
|
locationSettings.locale
|
||||||
|
)}`}
|
||||||
|
arrow
|
||||||
|
>
|
||||||
|
<Typography noWrap variant="body2" data-loading>
|
||||||
|
<TimeAgo date={new Date(archivedAt)} />
|
||||||
|
</Typography>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
</TextCell>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,28 @@
|
|||||||
|
import { VFC } from 'react';
|
||||||
|
import { ActionCell } from 'component/common/Table/cells/ActionCell/ActionCell';
|
||||||
|
import { Undo } from '@mui/icons-material';
|
||||||
|
import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton';
|
||||||
|
import { UPDATE_FEATURE } from 'component/providers/AccessProvider/permissions';
|
||||||
|
|
||||||
|
interface IReviveArchivedFeatureCell {
|
||||||
|
onRevive: () => void;
|
||||||
|
project: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ReviveArchivedFeatureCell: VFC<IReviveArchivedFeatureCell> = ({
|
||||||
|
onRevive,
|
||||||
|
project,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<ActionCell>
|
||||||
|
<PermissionIconButton
|
||||||
|
onClick={onRevive}
|
||||||
|
projectId={project}
|
||||||
|
permission={UPDATE_FEATURE}
|
||||||
|
tooltipProps={{ title: 'Revive feature' }}
|
||||||
|
>
|
||||||
|
<Undo />
|
||||||
|
</PermissionIconButton>
|
||||||
|
</ActionCell>
|
||||||
|
);
|
||||||
|
};
|
31
frontend/src/component/archive/FeaturesArchiveTable.tsx
Normal file
31
frontend/src/component/archive/FeaturesArchiveTable.tsx
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import { useFeaturesArchive } from '../../hooks/api/getters/useFeaturesArchive/useFeaturesArchive';
|
||||||
|
import { ArchiveTable } from './ArchiveTable/ArchiveTable';
|
||||||
|
import { SortingRule } from 'react-table';
|
||||||
|
import { usePageTitle } from 'hooks/usePageTitle';
|
||||||
|
import { createLocalStorage } from 'utils/createLocalStorage';
|
||||||
|
|
||||||
|
const defaultSort: SortingRule<string> = { id: 'createdAt', desc: true };
|
||||||
|
const { value, setValue } = createLocalStorage(
|
||||||
|
'FeaturesArchiveTable:v1',
|
||||||
|
defaultSort
|
||||||
|
);
|
||||||
|
|
||||||
|
export const FeaturesArchiveTable = () => {
|
||||||
|
usePageTitle('Archived');
|
||||||
|
const {
|
||||||
|
archivedFeatures = [],
|
||||||
|
loading,
|
||||||
|
refetchArchived,
|
||||||
|
} = useFeaturesArchive();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ArchiveTable
|
||||||
|
title="Archived"
|
||||||
|
archivedFeatures={archivedFeatures}
|
||||||
|
loading={loading}
|
||||||
|
storedParams={value}
|
||||||
|
setStoredParams={setValue}
|
||||||
|
refetch={refetchArchived}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
@ -1,58 +0,0 @@
|
|||||||
import { FC } from 'react';
|
|
||||||
import { useProjectFeaturesArchive } from 'hooks/api/getters/useProjectFeaturesArchive/useProjectFeaturesArchive';
|
|
||||||
import { FeatureToggleList } from '../feature/FeatureToggleList/FeatureToggleArchiveList';
|
|
||||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
|
||||||
import { useFeaturesFilter } from 'hooks/useFeaturesFilter';
|
|
||||||
import { useFeatureArchiveApi } from 'hooks/api/actions/useFeatureArchiveApi/useReviveFeatureApi';
|
|
||||||
import useToast from 'hooks/useToast';
|
|
||||||
import { useFeaturesSort } from 'hooks/useFeaturesSort';
|
|
||||||
|
|
||||||
interface IProjectFeaturesArchiveList {
|
|
||||||
projectId: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ProjectFeaturesArchiveList: FC<IProjectFeaturesArchiveList> = ({
|
|
||||||
projectId,
|
|
||||||
}) => {
|
|
||||||
const { setToastData, setToastApiError } = useToast();
|
|
||||||
const { uiConfig } = useUiConfig();
|
|
||||||
const { reviveFeature } = useFeatureArchiveApi();
|
|
||||||
|
|
||||||
const {
|
|
||||||
archivedFeatures = [],
|
|
||||||
refetchArchived,
|
|
||||||
loading,
|
|
||||||
} = useProjectFeaturesArchive(projectId);
|
|
||||||
|
|
||||||
const { filtered, filter, setFilter } = useFeaturesFilter(archivedFeatures);
|
|
||||||
const { sorted, sort, setSort } = useFeaturesSort(filtered);
|
|
||||||
|
|
||||||
const onRevive = (feature: string) => {
|
|
||||||
reviveFeature(feature)
|
|
||||||
.then(refetchArchived)
|
|
||||||
.then(() =>
|
|
||||||
setToastData({
|
|
||||||
type: 'success',
|
|
||||||
title: "And we're back!",
|
|
||||||
text: 'The feature toggle has been revived.',
|
|
||||||
confetti: true,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.catch(e => setToastApiError(e.toString()));
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<FeatureToggleList
|
|
||||||
features={sorted}
|
|
||||||
loading={loading}
|
|
||||||
onRevive={onRevive}
|
|
||||||
flags={uiConfig.flags}
|
|
||||||
filter={filter}
|
|
||||||
setFilter={setFilter}
|
|
||||||
sort={sort}
|
|
||||||
setSort={setSort}
|
|
||||||
isArchive
|
|
||||||
inProject={Boolean(projectId)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
@ -0,0 +1,37 @@
|
|||||||
|
import { ArchiveTable } from './ArchiveTable/ArchiveTable';
|
||||||
|
import { SortingRule } from 'react-table';
|
||||||
|
import { useProjectFeaturesArchive } from '../../hooks/api/getters/useProjectFeaturesArchive/useProjectFeaturesArchive';
|
||||||
|
import { createLocalStorage } from 'utils/createLocalStorage';
|
||||||
|
|
||||||
|
const defaultSort: SortingRule<string> = { id: 'archivedAt', desc: true };
|
||||||
|
|
||||||
|
interface IProjectFeaturesTable {
|
||||||
|
projectId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ProjectFeaturesArchiveTable = ({
|
||||||
|
projectId,
|
||||||
|
}: IProjectFeaturesTable) => {
|
||||||
|
const {
|
||||||
|
archivedFeatures = [],
|
||||||
|
refetchArchived,
|
||||||
|
loading,
|
||||||
|
} = useProjectFeaturesArchive(projectId);
|
||||||
|
|
||||||
|
const { value, setValue } = createLocalStorage(
|
||||||
|
`${projectId}:ProjectFeaturesArchiveTable`,
|
||||||
|
defaultSort
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ArchiveTable
|
||||||
|
title="Project Features Archive"
|
||||||
|
archivedFeatures={archivedFeatures}
|
||||||
|
loading={loading}
|
||||||
|
storedParams={value}
|
||||||
|
setStoredParams={setValue}
|
||||||
|
refetch={refetchArchived}
|
||||||
|
projectId={projectId}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
@ -93,7 +93,7 @@ export const Search = ({
|
|||||||
<IconButton
|
<IconButton
|
||||||
size="small"
|
size="small"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
onChange('');
|
onSearchChange('');
|
||||||
ref.current?.focus();
|
ref.current?.focus();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -1,178 +0,0 @@
|
|||||||
import { Dispatch, SetStateAction, useContext, VFC } from 'react';
|
|
||||||
import classnames from 'classnames';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import { List, ListItem } from '@mui/material';
|
|
||||||
import useMediaQuery from '@mui/material/useMediaQuery';
|
|
||||||
import { IFlags } from 'interfaces/uiConfig';
|
|
||||||
import { SearchField } from 'component/common/SearchField/SearchField';
|
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
|
||||||
import { PageContent } from 'component/common/PageContent/PageContent';
|
|
||||||
import { PageHeader } from 'component/common/PageHeader/PageHeader';
|
|
||||||
import AccessContext from 'contexts/AccessContext';
|
|
||||||
import { IFeaturesFilter } from 'hooks/useFeaturesFilter';
|
|
||||||
import { FeatureToggleListItem } from './FeatureToggleListItem/FeatureToggleListItem';
|
|
||||||
import { FeatureToggleListActions } from './FeatureToggleListActions/FeatureToggleListActions';
|
|
||||||
import { CreateFeatureButton } from '../CreateFeatureButton/CreateFeatureButton';
|
|
||||||
import { IFeaturesSort } from 'hooks/useFeaturesSort';
|
|
||||||
import { FeatureSchema } from 'openapi';
|
|
||||||
import { useStyles } from './styles';
|
|
||||||
|
|
||||||
interface IFeatureToggleListProps {
|
|
||||||
features: FeatureSchema[];
|
|
||||||
loading?: boolean;
|
|
||||||
flags?: IFlags;
|
|
||||||
filter: IFeaturesFilter;
|
|
||||||
setFilter: Dispatch<SetStateAction<IFeaturesFilter>>;
|
|
||||||
sort: IFeaturesSort;
|
|
||||||
setSort: Dispatch<SetStateAction<IFeaturesSort>>;
|
|
||||||
onRevive?: (feature: string) => void;
|
|
||||||
inProject?: boolean;
|
|
||||||
isArchive?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
const loadingFeaturesPlaceholder: FeatureSchema[] = Array(10)
|
|
||||||
.fill({
|
|
||||||
createdAt: '2021-03-19T09:16:21.329Z',
|
|
||||||
description: ' ',
|
|
||||||
enabled: true,
|
|
||||||
lastSeenAt: '2021-03-24T10:46:38.036Z',
|
|
||||||
name: '',
|
|
||||||
project: 'default',
|
|
||||||
stale: true,
|
|
||||||
strategies: [],
|
|
||||||
variants: [],
|
|
||||||
type: 'release',
|
|
||||||
archived: false,
|
|
||||||
environments: [],
|
|
||||||
impressionData: false,
|
|
||||||
})
|
|
||||||
.map((feature, index) => ({ ...feature, name: `${index}` })); // ID for React key
|
|
||||||
|
|
||||||
export const FeatureToggleList: VFC<IFeatureToggleListProps> = ({
|
|
||||||
features,
|
|
||||||
onRevive,
|
|
||||||
inProject,
|
|
||||||
isArchive,
|
|
||||||
loading,
|
|
||||||
flags,
|
|
||||||
filter,
|
|
||||||
setFilter,
|
|
||||||
sort,
|
|
||||||
setSort,
|
|
||||||
}) => {
|
|
||||||
const { hasAccess } = useContext(AccessContext);
|
|
||||||
const { classes: styles } = useStyles();
|
|
||||||
const smallScreen = useMediaQuery('(max-width:800px)');
|
|
||||||
const mobileView = useMediaQuery('(max-width:600px)');
|
|
||||||
|
|
||||||
const setFilterQuery = (v: string) => {
|
|
||||||
const query = v && typeof v === 'string' ? v.trim() : '';
|
|
||||||
setFilter(prev => ({ ...prev, query }));
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderFeatures = () => {
|
|
||||||
if (loading) {
|
|
||||||
return loadingFeaturesPlaceholder.map(feature => (
|
|
||||||
<FeatureToggleListItem
|
|
||||||
key={feature.name}
|
|
||||||
feature={feature}
|
|
||||||
onRevive={onRevive}
|
|
||||||
hasAccess={hasAccess}
|
|
||||||
className={'skeleton'}
|
|
||||||
flags={flags}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={features.length > 0}
|
|
||||||
show={features.map(feature => (
|
|
||||||
<FeatureToggleListItem
|
|
||||||
key={feature.name}
|
|
||||||
feature={feature}
|
|
||||||
onRevive={onRevive}
|
|
||||||
hasAccess={hasAccess}
|
|
||||||
flags={flags}
|
|
||||||
inProject={inProject}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
elseShow={
|
|
||||||
<ListItem className={styles.emptyStateListItem}>
|
|
||||||
No archived features.
|
|
||||||
</ListItem>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const searchResultsHeader = filter.query
|
|
||||||
? ` (${features.length} matches)`
|
|
||||||
: '';
|
|
||||||
|
|
||||||
const headerTitle = isArchive
|
|
||||||
? inProject
|
|
||||||
? `Archived project features ${searchResultsHeader}`
|
|
||||||
: `Archived features ${searchResultsHeader}`
|
|
||||||
: `Features ${searchResultsHeader}`;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
className={classnames(styles.searchBarContainer, {
|
|
||||||
dense: inProject,
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<SearchField
|
|
||||||
initialValue={filter.query}
|
|
||||||
updateValue={setFilterQuery}
|
|
||||||
showValueChip={!mobileView}
|
|
||||||
className={classnames(styles.searchBar, {
|
|
||||||
skeleton: loading,
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={!mobileView && !isArchive}
|
|
||||||
show={<Link to="/archive">Archive</Link>}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<PageContent
|
|
||||||
header={
|
|
||||||
<PageHeader
|
|
||||||
loading={loading}
|
|
||||||
title={headerTitle}
|
|
||||||
actions={
|
|
||||||
<div className={styles.actionsContainer}>
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={!smallScreen}
|
|
||||||
show={
|
|
||||||
<FeatureToggleListActions
|
|
||||||
filter={filter}
|
|
||||||
setFilter={setFilter}
|
|
||||||
sort={sort}
|
|
||||||
setSort={setSort}
|
|
||||||
loading={loading}
|
|
||||||
inProject={inProject}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={!isArchive}
|
|
||||||
show={
|
|
||||||
<CreateFeatureButton
|
|
||||||
filter={filter}
|
|
||||||
loading={Boolean(loading)}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<List>{renderFeatures()}</List>
|
|
||||||
</PageContent>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,99 +0,0 @@
|
|||||||
import { Dispatch, MouseEventHandler, SetStateAction, VFC } from 'react';
|
|
||||||
import { MenuItem, Typography } from '@mui/material';
|
|
||||||
import DropdownMenu from 'component/common/DropdownMenu/DropdownMenu';
|
|
||||||
import ProjectSelect from 'component/common/ProjectSelect/ProjectSelect';
|
|
||||||
import useLoading from 'hooks/useLoading';
|
|
||||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
|
||||||
import {
|
|
||||||
createFeaturesFilterSortOptions,
|
|
||||||
FeaturesSortType,
|
|
||||||
IFeaturesSort,
|
|
||||||
} from 'hooks/useFeaturesSort';
|
|
||||||
import { useStyles } from './styles';
|
|
||||||
import { IFeaturesFilter } from 'hooks/useFeaturesFilter';
|
|
||||||
|
|
||||||
let sortOptions = createFeaturesFilterSortOptions();
|
|
||||||
|
|
||||||
interface IFeatureToggleListActionsProps {
|
|
||||||
filter: IFeaturesFilter;
|
|
||||||
setFilter: Dispatch<SetStateAction<IFeaturesFilter>>;
|
|
||||||
sort: IFeaturesSort;
|
|
||||||
setSort: Dispatch<SetStateAction<IFeaturesSort>>;
|
|
||||||
loading?: boolean;
|
|
||||||
inProject?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const FeatureToggleListActions: VFC<IFeatureToggleListActionsProps> = ({
|
|
||||||
filter,
|
|
||||||
setFilter,
|
|
||||||
sort,
|
|
||||||
setSort,
|
|
||||||
loading = false,
|
|
||||||
inProject,
|
|
||||||
}) => {
|
|
||||||
const { classes: styles } = useStyles();
|
|
||||||
const { uiConfig } = useUiConfig();
|
|
||||||
const ref = useLoading(loading);
|
|
||||||
|
|
||||||
const handleSort: MouseEventHandler = e => {
|
|
||||||
const type = (e.target as Element)
|
|
||||||
.getAttribute('data-target')
|
|
||||||
?.trim() as FeaturesSortType;
|
|
||||||
if (type) {
|
|
||||||
setSort(prev => ({ ...prev, type }));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const selectedOption =
|
|
||||||
sortOptions.find(o => o.type === sort.type) || sortOptions[0];
|
|
||||||
|
|
||||||
if (inProject) {
|
|
||||||
sortOptions = sortOptions.filter(option => option.type !== 'project');
|
|
||||||
}
|
|
||||||
|
|
||||||
const renderSortingOptions = () =>
|
|
||||||
sortOptions.map(option => (
|
|
||||||
<MenuItem
|
|
||||||
style={{ fontSize: '14px' }}
|
|
||||||
key={option.type}
|
|
||||||
disabled={option.type === sort.type}
|
|
||||||
data-target={option.type}
|
|
||||||
>
|
|
||||||
{option.name}
|
|
||||||
</MenuItem>
|
|
||||||
));
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={styles.actions} ref={ref}>
|
|
||||||
<Typography variant="body2" data-loading>
|
|
||||||
Sorted by:
|
|
||||||
</Typography>
|
|
||||||
<DropdownMenu
|
|
||||||
id={'sorting'}
|
|
||||||
label={`By ${selectedOption.name}`}
|
|
||||||
callback={handleSort}
|
|
||||||
renderOptions={renderSortingOptions}
|
|
||||||
title="Sort by"
|
|
||||||
style={{ textTransform: 'lowercase', fontWeight: 'normal' }}
|
|
||||||
data-loading
|
|
||||||
/>
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={uiConfig.flags.P && !inProject}
|
|
||||||
show={
|
|
||||||
<ProjectSelect
|
|
||||||
currentProjectId={filter.project}
|
|
||||||
updateCurrentProject={project =>
|
|
||||||
setFilter(prev => ({ ...prev, project }))
|
|
||||||
}
|
|
||||||
style={{
|
|
||||||
textTransform: 'lowercase',
|
|
||||||
fontWeight: 'normal',
|
|
||||||
}}
|
|
||||||
data-loading
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,12 +0,0 @@
|
|||||||
import { makeStyles } from 'tss-react/mui';
|
|
||||||
|
|
||||||
export const useStyles = makeStyles()({
|
|
||||||
actions: {
|
|
||||||
'& > *': {
|
|
||||||
margin: '0 0.25rem',
|
|
||||||
},
|
|
||||||
marginRight: '0.25rem',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
},
|
|
||||||
});
|
|
@ -30,7 +30,7 @@ import { useStyles } from './styles';
|
|||||||
import { useSearch } from 'hooks/useSearch';
|
import { useSearch } from 'hooks/useSearch';
|
||||||
import { Search } from 'component/common/Search/Search';
|
import { Search } from 'component/common/Search/Search';
|
||||||
|
|
||||||
const featuresPlaceholder: FeatureSchema[] = Array(15).fill({
|
export const featuresPlaceholder: FeatureSchema[] = Array(15).fill({
|
||||||
name: 'Name of the feature',
|
name: 'Name of the feature',
|
||||||
description: 'Short description of the feature',
|
description: 'Short description of the feature',
|
||||||
type: '-',
|
type: '-',
|
||||||
@ -38,7 +38,9 @@ const featuresPlaceholder: FeatureSchema[] = Array(15).fill({
|
|||||||
project: 'projectID',
|
project: 'projectID',
|
||||||
});
|
});
|
||||||
|
|
||||||
type PageQueryType = Partial<Record<'sort' | 'order' | 'search', string>>;
|
export type PageQueryType = Partial<
|
||||||
|
Record<'sort' | 'order' | 'search', string>
|
||||||
|
>;
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
@ -97,7 +99,7 @@ const columns = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const defaultSort: SortingRule<string> = { id: 'createdAt', desc: true };
|
const defaultSort: SortingRule<string> = { id: 'createdAt' };
|
||||||
|
|
||||||
const { value: storedParams, setValue: setStoredParams } = createLocalStorage(
|
const { value: storedParams, setValue: setStoredParams } = createLocalStorage(
|
||||||
'FeatureToggleListTable:v1',
|
'FeatureToggleListTable:v1',
|
||||||
|
@ -20,10 +20,7 @@ export const FeatureMetricsTable = ({
|
|||||||
}: IFeatureMetricsTableProps) => {
|
}: IFeatureMetricsTableProps) => {
|
||||||
const isMediumScreen = useMediaQuery(theme.breakpoints.down('md'));
|
const isMediumScreen = useMediaQuery(theme.breakpoints.down('md'));
|
||||||
|
|
||||||
const initialState = useMemo(
|
const initialState = useMemo(() => ({ sortBy: [{ id: 'timestamp' }] }), []);
|
||||||
() => ({ sortBy: [{ id: 'timestamp', desc: true }] }),
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
getTableProps,
|
getTableProps,
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import { FeatureToggleListTable } from 'component/feature/FeatureToggleList/FeatureToggleListTable';
|
import { FeatureToggleListTable } from 'component/feature/FeatureToggleList/FeatureToggleListTable';
|
||||||
import { StrategyView } from 'component/strategies/StrategyView/StrategyView';
|
import { StrategyView } from 'component/strategies/StrategyView/StrategyView';
|
||||||
import { StrategiesList } from 'component/strategies/StrategiesList/StrategiesList';
|
import { StrategiesList } from 'component/strategies/StrategiesList/StrategiesList';
|
||||||
|
|
||||||
import { ArchiveListContainer } from 'component/archive/ArchiveListContainer';
|
|
||||||
import { TagTypeList } from 'component/tags/TagTypeList/TagTypeList';
|
import { TagTypeList } from 'component/tags/TagTypeList/TagTypeList';
|
||||||
import { AddonList } from 'component/addons/AddonList/AddonList';
|
import { AddonList } from 'component/addons/AddonList/AddonList';
|
||||||
import Admin from 'component/admin';
|
import Admin from 'component/admin';
|
||||||
@ -53,6 +51,7 @@ import { IRoute } from 'interfaces/route';
|
|||||||
import { EnvironmentTable } from 'component/environments/EnvironmentTable/EnvironmentTable';
|
import { EnvironmentTable } from 'component/environments/EnvironmentTable/EnvironmentTable';
|
||||||
import { SegmentTable } from 'component/segments/SegmentTable/SegmentTable';
|
import { SegmentTable } from 'component/segments/SegmentTable/SegmentTable';
|
||||||
import RedirectAdminInvoices from 'component/admin/billing/RedirectAdminInvoices/RedirectAdminInvoices';
|
import RedirectAdminInvoices from 'component/admin/billing/RedirectAdminInvoices/RedirectAdminInvoices';
|
||||||
|
import { FeaturesArchiveTable } from '../archive/FeaturesArchiveTable';
|
||||||
|
|
||||||
export const routes: IRoute[] = [
|
export const routes: IRoute[] = [
|
||||||
// Splash
|
// Splash
|
||||||
@ -378,7 +377,7 @@ export const routes: IRoute[] = [
|
|||||||
{
|
{
|
||||||
path: '/archive',
|
path: '/archive',
|
||||||
title: 'Archived toggles',
|
title: 'Archived toggles',
|
||||||
component: ArchiveListContainer,
|
component: FeaturesArchiveTable,
|
||||||
type: 'protected',
|
type: 'protected',
|
||||||
menu: {},
|
menu: {},
|
||||||
},
|
},
|
||||||
|
@ -67,10 +67,7 @@ const staticColumns = ['Actions', 'name'];
|
|||||||
|
|
||||||
const defaultSort: SortingRule<string> & {
|
const defaultSort: SortingRule<string> & {
|
||||||
columns?: string[];
|
columns?: string[];
|
||||||
} = {
|
} = { id: 'createdAt' };
|
||||||
id: 'createdAt',
|
|
||||||
desc: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ProjectFeatureToggles = ({
|
export const ProjectFeatureToggles = ({
|
||||||
features,
|
features,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ProjectFeaturesArchiveList } from 'component/archive/ProjectFeaturesArchiveList';
|
import { ProjectFeaturesArchiveTable } from 'component/archive/ProjectFeaturesArchiveTable';
|
||||||
import { usePageTitle } from 'hooks/usePageTitle';
|
import { usePageTitle } from 'hooks/usePageTitle';
|
||||||
|
|
||||||
interface IProjectFeaturesArchiveProps {
|
interface IProjectFeaturesArchiveProps {
|
||||||
@ -10,5 +10,5 @@ export const ProjectFeaturesArchive = ({
|
|||||||
}: IProjectFeaturesArchiveProps) => {
|
}: IProjectFeaturesArchiveProps) => {
|
||||||
usePageTitle('Project Archived Features');
|
usePageTitle('Project Archived Features');
|
||||||
|
|
||||||
return <ProjectFeaturesArchiveList projectId={projectId} />;
|
return <ProjectFeaturesArchiveTable projectId={projectId} />;
|
||||||
};
|
};
|
||||||
|
@ -30,7 +30,7 @@ export const SegmentTable = () => {
|
|||||||
const { segments, loading } = useSegments();
|
const { segments, loading } = useSegments();
|
||||||
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
|
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
|
||||||
const [initialState] = useState({
|
const [initialState] = useState({
|
||||||
sortBy: [{ id: 'createdAt', desc: false }],
|
sortBy: [{ id: 'createdAt' }],
|
||||||
hiddenColumns: ['description'],
|
hiddenColumns: ['description'],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,226 +0,0 @@
|
|||||||
import React, { useMemo } from 'react';
|
|
||||||
import { basePath } from 'utils/formatPath';
|
|
||||||
import { createPersistentGlobalStateHook } from './usePersistentGlobalState';
|
|
||||||
import {
|
|
||||||
expired,
|
|
||||||
getDiffInDays,
|
|
||||||
toggleExpiryByTypeMap,
|
|
||||||
} from 'component/Reporting/utils';
|
|
||||||
import { FeatureSchema } from 'openapi';
|
|
||||||
|
|
||||||
export type FeaturesSortType =
|
|
||||||
| 'name'
|
|
||||||
| 'expired'
|
|
||||||
| 'type'
|
|
||||||
| 'enabled'
|
|
||||||
| 'stale'
|
|
||||||
| 'created'
|
|
||||||
| 'last-seen'
|
|
||||||
| 'status'
|
|
||||||
| 'project';
|
|
||||||
|
|
||||||
export interface IFeaturesSort {
|
|
||||||
type: FeaturesSortType;
|
|
||||||
desc?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IFeaturesSortOutput {
|
|
||||||
sort: IFeaturesSort;
|
|
||||||
sorted: FeatureSchema[];
|
|
||||||
setSort: React.Dispatch<React.SetStateAction<IFeaturesSort>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IFeaturesFilterSortOption {
|
|
||||||
type: FeaturesSortType;
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store the features sort state globally, and in localStorage.
|
|
||||||
// When changing the format of IFeaturesSort, change the version as well.
|
|
||||||
const useFeaturesSortState = createPersistentGlobalStateHook<IFeaturesSort>(
|
|
||||||
`${basePath}:useFeaturesSort:v1`,
|
|
||||||
{ type: 'name' }
|
|
||||||
);
|
|
||||||
|
|
||||||
export const useFeaturesSort = (
|
|
||||||
features: FeatureSchema[]
|
|
||||||
): IFeaturesSortOutput => {
|
|
||||||
const [sort, setSort] = useFeaturesSortState();
|
|
||||||
|
|
||||||
const sorted = useMemo(() => {
|
|
||||||
return sortFeatures(features, sort);
|
|
||||||
}, [features, sort]);
|
|
||||||
|
|
||||||
return {
|
|
||||||
setSort,
|
|
||||||
sort,
|
|
||||||
sorted,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const createFeaturesFilterSortOptions =
|
|
||||||
(): IFeaturesFilterSortOption[] => {
|
|
||||||
return [
|
|
||||||
{ type: 'name', name: 'Name' },
|
|
||||||
{ type: 'type', name: 'Type' },
|
|
||||||
{ type: 'enabled', name: 'Enabled' },
|
|
||||||
{ type: 'stale', name: 'Stale' },
|
|
||||||
{ type: 'created', name: 'Created' },
|
|
||||||
{ type: 'last-seen', name: 'Last seen' },
|
|
||||||
{ type: 'project', name: 'Project' },
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
const sortAscendingFeatures = (
|
|
||||||
features: FeatureSchema[],
|
|
||||||
sort: IFeaturesSort
|
|
||||||
): FeatureSchema[] => {
|
|
||||||
switch (sort.type) {
|
|
||||||
case 'enabled':
|
|
||||||
return sortByEnabled(features);
|
|
||||||
case 'stale':
|
|
||||||
return sortByStale(features);
|
|
||||||
case 'created':
|
|
||||||
return sortByCreated(features);
|
|
||||||
case 'last-seen':
|
|
||||||
return sortByLastSeen(features);
|
|
||||||
case 'name':
|
|
||||||
return sortByName(features);
|
|
||||||
case 'project':
|
|
||||||
return sortByProject(features);
|
|
||||||
case 'type':
|
|
||||||
return sortByType(features);
|
|
||||||
case 'expired':
|
|
||||||
return sortByExpired(features);
|
|
||||||
case 'status':
|
|
||||||
return sortByStatus(features);
|
|
||||||
default:
|
|
||||||
console.error(`Unknown feature sort type: ${sort.type}`);
|
|
||||||
return features;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const sortFeatures = (
|
|
||||||
features: FeatureSchema[],
|
|
||||||
sort: IFeaturesSort
|
|
||||||
): FeatureSchema[] => {
|
|
||||||
const sorted = sortAscendingFeatures(features, sort);
|
|
||||||
|
|
||||||
if (sort.desc) {
|
|
||||||
return [...sorted].reverse();
|
|
||||||
}
|
|
||||||
|
|
||||||
return sorted;
|
|
||||||
};
|
|
||||||
|
|
||||||
const sortByEnabled = (
|
|
||||||
features: Readonly<FeatureSchema[]>
|
|
||||||
): FeatureSchema[] => {
|
|
||||||
return [...features].sort((a, b) =>
|
|
||||||
a.enabled === b.enabled ? 0 : a.enabled ? -1 : 1
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const sortByStale = (features: Readonly<FeatureSchema[]>): FeatureSchema[] => {
|
|
||||||
return [...features].sort((a, b) =>
|
|
||||||
a.stale === b.stale ? 0 : a.stale ? -1 : 1
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const sortByLastSeen = (
|
|
||||||
features: Readonly<FeatureSchema[]>
|
|
||||||
): FeatureSchema[] => {
|
|
||||||
return [...features].sort((a, b) =>
|
|
||||||
a.lastSeenAt && b.lastSeenAt
|
|
||||||
? compareNullableDates(b.lastSeenAt, a.lastSeenAt)
|
|
||||||
: a.lastSeenAt
|
|
||||||
? -1
|
|
||||||
: b.lastSeenAt
|
|
||||||
? 1
|
|
||||||
: compareNullableDates(b.createdAt, a.createdAt)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const sortByCreated = (
|
|
||||||
features: Readonly<FeatureSchema[]>
|
|
||||||
): FeatureSchema[] => {
|
|
||||||
return [...features].sort((a, b) =>
|
|
||||||
compareNullableDates(b.createdAt, a.createdAt)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const sortByName = (features: Readonly<FeatureSchema[]>): FeatureSchema[] => {
|
|
||||||
return [...features].sort((a, b) => a.name.localeCompare(b.name));
|
|
||||||
};
|
|
||||||
|
|
||||||
const sortByProject = (
|
|
||||||
features: Readonly<FeatureSchema[]>
|
|
||||||
): FeatureSchema[] => {
|
|
||||||
return [...features].sort((a, b) =>
|
|
||||||
a.project && b.project
|
|
||||||
? a.project.localeCompare(b.project)
|
|
||||||
: a.project
|
|
||||||
? 1
|
|
||||||
: b.project
|
|
||||||
? -1
|
|
||||||
: 0
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const sortByType = (features: Readonly<FeatureSchema[]>): FeatureSchema[] => {
|
|
||||||
return [...features].sort((a, b) =>
|
|
||||||
a.type && b.type
|
|
||||||
? a.type.localeCompare(b.type)
|
|
||||||
: a.type
|
|
||||||
? 1
|
|
||||||
: b.type
|
|
||||||
? -1
|
|
||||||
: 0
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const compareNullableDates = (
|
|
||||||
a: Date | null | undefined,
|
|
||||||
b: Date | null | undefined
|
|
||||||
): number => {
|
|
||||||
return a && b ? a?.getTime?.() - b?.getTime?.() : a ? 1 : b ? -1 : 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
const sortByExpired = (
|
|
||||||
features: Readonly<FeatureSchema[]>
|
|
||||||
): FeatureSchema[] => {
|
|
||||||
return [...features].sort((a, b) => {
|
|
||||||
const now = new Date();
|
|
||||||
const dateA = a.createdAt!;
|
|
||||||
const dateB = b.createdAt!;
|
|
||||||
|
|
||||||
const diffA = getDiffInDays(dateA, now);
|
|
||||||
const diffB = getDiffInDays(dateB, now);
|
|
||||||
|
|
||||||
if (!expired(diffA, a.type!) && expired(diffB, b.type!)) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (expired(diffA, a.type!) && !expired(diffB, b.type!)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const expiration = toggleExpiryByTypeMap as Record<string, number>;
|
|
||||||
const expiredByA = a.type ? diffA - expiration[a.type] : 0;
|
|
||||||
const expiredByB = b.type ? diffB - expiration[b.type] : 0;
|
|
||||||
|
|
||||||
return expiredByB - expiredByA;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const sortByStatus = (features: Readonly<FeatureSchema[]>): FeatureSchema[] => {
|
|
||||||
return [...features].sort((a, b) => {
|
|
||||||
if (a.stale) {
|
|
||||||
return 1;
|
|
||||||
} else if (b.stale) {
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
@ -15,9 +15,6 @@
|
|||||||
|
|
||||||
import * as runtime from '../runtime';
|
import * as runtime from '../runtime';
|
||||||
import {
|
import {
|
||||||
ChangeProjectSchema,
|
|
||||||
ChangeProjectSchemaFromJSON,
|
|
||||||
ChangeProjectSchemaToJSON,
|
|
||||||
CloneFeatureSchema,
|
CloneFeatureSchema,
|
||||||
CloneFeatureSchemaFromJSON,
|
CloneFeatureSchemaFromJSON,
|
||||||
CloneFeatureSchemaToJSON,
|
CloneFeatureSchemaToJSON,
|
||||||
@ -75,12 +72,6 @@ export interface ApiAdminArchiveFeaturesProjectIdGetRequest {
|
|||||||
projectId: string;
|
projectId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ApiAdminProjectsProjectIdFeaturesFeatureNameChangeProjectPostRequest {
|
|
||||||
projectId: string;
|
|
||||||
featureName: string;
|
|
||||||
changeProjectSchema: ChangeProjectSchema;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ArchiveFeatureRequest {
|
export interface ArchiveFeatureRequest {
|
||||||
projectId: string;
|
projectId: string;
|
||||||
featureName: string;
|
featureName: string;
|
||||||
@ -189,7 +180,7 @@ export class AdminApi extends runtime.BaseAPI {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async addStrategyRaw(requestParameters: AddStrategyRequest, initOverrides?: RequestInit): Promise<runtime.ApiResponse<FeatureStrategySchema>> {
|
async addStrategyRaw(requestParameters: AddStrategyRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<runtime.ApiResponse<FeatureStrategySchema>> {
|
||||||
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
||||||
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling addStrategy.');
|
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling addStrategy.');
|
||||||
}
|
}
|
||||||
@ -229,14 +220,14 @@ export class AdminApi extends runtime.BaseAPI {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async addStrategy(requestParameters: AddStrategyRequest, initOverrides?: RequestInit): Promise<FeatureStrategySchema> {
|
async addStrategy(requestParameters: AddStrategyRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<FeatureStrategySchema> {
|
||||||
const response = await this.addStrategyRaw(requestParameters, initOverrides);
|
const response = await this.addStrategyRaw(requestParameters, initOverrides);
|
||||||
return await response.value();
|
return await response.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async addTagRaw(requestParameters: AddTagRequest, initOverrides?: RequestInit): Promise<runtime.ApiResponse<TagSchema>> {
|
async addTagRaw(requestParameters: AddTagRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<runtime.ApiResponse<TagSchema>> {
|
||||||
if (requestParameters.featureName === null || requestParameters.featureName === undefined) {
|
if (requestParameters.featureName === null || requestParameters.featureName === undefined) {
|
||||||
throw new runtime.RequiredError('featureName','Required parameter requestParameters.featureName was null or undefined when calling addTag.');
|
throw new runtime.RequiredError('featureName','Required parameter requestParameters.featureName was null or undefined when calling addTag.');
|
||||||
}
|
}
|
||||||
@ -268,14 +259,14 @@ export class AdminApi extends runtime.BaseAPI {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async addTag(requestParameters: AddTagRequest, initOverrides?: RequestInit): Promise<TagSchema> {
|
async addTag(requestParameters: AddTagRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<TagSchema> {
|
||||||
const response = await this.addTagRaw(requestParameters, initOverrides);
|
const response = await this.addTagRaw(requestParameters, initOverrides);
|
||||||
return await response.value();
|
return await response.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async apiAdminArchiveFeaturesGetRaw(initOverrides?: RequestInit): Promise<runtime.ApiResponse<FeaturesSchema>> {
|
async apiAdminArchiveFeaturesGetRaw(initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<runtime.ApiResponse<FeaturesSchema>> {
|
||||||
const queryParameters: any = {};
|
const queryParameters: any = {};
|
||||||
|
|
||||||
const headerParameters: runtime.HTTPHeaders = {};
|
const headerParameters: runtime.HTTPHeaders = {};
|
||||||
@ -296,14 +287,14 @@ export class AdminApi extends runtime.BaseAPI {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async apiAdminArchiveFeaturesGet(initOverrides?: RequestInit): Promise<FeaturesSchema> {
|
async apiAdminArchiveFeaturesGet(initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<FeaturesSchema> {
|
||||||
const response = await this.apiAdminArchiveFeaturesGetRaw(initOverrides);
|
const response = await this.apiAdminArchiveFeaturesGetRaw(initOverrides);
|
||||||
return await response.value();
|
return await response.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async apiAdminArchiveFeaturesProjectIdGetRaw(requestParameters: ApiAdminArchiveFeaturesProjectIdGetRequest, initOverrides?: RequestInit): Promise<runtime.ApiResponse<FeaturesSchema>> {
|
async apiAdminArchiveFeaturesProjectIdGetRaw(requestParameters: ApiAdminArchiveFeaturesProjectIdGetRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<runtime.ApiResponse<FeaturesSchema>> {
|
||||||
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
||||||
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling apiAdminArchiveFeaturesProjectIdGet.');
|
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling apiAdminArchiveFeaturesProjectIdGet.');
|
||||||
}
|
}
|
||||||
@ -328,56 +319,14 @@ export class AdminApi extends runtime.BaseAPI {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async apiAdminArchiveFeaturesProjectIdGet(requestParameters: ApiAdminArchiveFeaturesProjectIdGetRequest, initOverrides?: RequestInit): Promise<FeaturesSchema> {
|
async apiAdminArchiveFeaturesProjectIdGet(requestParameters: ApiAdminArchiveFeaturesProjectIdGetRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<FeaturesSchema> {
|
||||||
const response = await this.apiAdminArchiveFeaturesProjectIdGetRaw(requestParameters, initOverrides);
|
const response = await this.apiAdminArchiveFeaturesProjectIdGetRaw(requestParameters, initOverrides);
|
||||||
return await response.value();
|
return await response.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async apiAdminProjectsProjectIdFeaturesFeatureNameChangeProjectPostRaw(requestParameters: ApiAdminProjectsProjectIdFeaturesFeatureNameChangeProjectPostRequest, initOverrides?: RequestInit): Promise<runtime.ApiResponse<void>> {
|
async archiveFeatureRaw(requestParameters: ArchiveFeatureRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<runtime.ApiResponse<object>> {
|
||||||
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
|
||||||
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling apiAdminProjectsProjectIdFeaturesFeatureNameChangeProjectPost.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (requestParameters.featureName === null || requestParameters.featureName === undefined) {
|
|
||||||
throw new runtime.RequiredError('featureName','Required parameter requestParameters.featureName was null or undefined when calling apiAdminProjectsProjectIdFeaturesFeatureNameChangeProjectPost.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (requestParameters.changeProjectSchema === null || requestParameters.changeProjectSchema === undefined) {
|
|
||||||
throw new runtime.RequiredError('changeProjectSchema','Required parameter requestParameters.changeProjectSchema was null or undefined when calling apiAdminProjectsProjectIdFeaturesFeatureNameChangeProjectPost.');
|
|
||||||
}
|
|
||||||
|
|
||||||
const queryParameters: any = {};
|
|
||||||
|
|
||||||
const headerParameters: runtime.HTTPHeaders = {};
|
|
||||||
|
|
||||||
headerParameters['Content-Type'] = 'application/json';
|
|
||||||
|
|
||||||
if (this.configuration && this.configuration.apiKey) {
|
|
||||||
headerParameters["Authorization"] = this.configuration.apiKey("Authorization"); // apiKey authentication
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await this.request({
|
|
||||||
path: `/api/admin/projects/{projectId}/features/{featureName}/changeProject`.replace(`{${"projectId"}}`, encodeURIComponent(String(requestParameters.projectId))).replace(`{${"featureName"}}`, encodeURIComponent(String(requestParameters.featureName))),
|
|
||||||
method: 'POST',
|
|
||||||
headers: headerParameters,
|
|
||||||
query: queryParameters,
|
|
||||||
body: ChangeProjectSchemaToJSON(requestParameters.changeProjectSchema),
|
|
||||||
}, initOverrides);
|
|
||||||
|
|
||||||
return new runtime.VoidApiResponse(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
async apiAdminProjectsProjectIdFeaturesFeatureNameChangeProjectPost(requestParameters: ApiAdminProjectsProjectIdFeaturesFeatureNameChangeProjectPostRequest, initOverrides?: RequestInit): Promise<void> {
|
|
||||||
await this.apiAdminProjectsProjectIdFeaturesFeatureNameChangeProjectPostRaw(requestParameters, initOverrides);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
async archiveFeatureRaw(requestParameters: ArchiveFeatureRequest, initOverrides?: RequestInit): Promise<runtime.ApiResponse<object>> {
|
|
||||||
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
||||||
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling archiveFeature.');
|
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling archiveFeature.');
|
||||||
}
|
}
|
||||||
@ -406,14 +355,14 @@ export class AdminApi extends runtime.BaseAPI {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async archiveFeature(requestParameters: ArchiveFeatureRequest, initOverrides?: RequestInit): Promise<object> {
|
async archiveFeature(requestParameters: ArchiveFeatureRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<object> {
|
||||||
const response = await this.archiveFeatureRaw(requestParameters, initOverrides);
|
const response = await this.archiveFeatureRaw(requestParameters, initOverrides);
|
||||||
return await response.value();
|
return await response.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async cloneFeatureRaw(requestParameters: CloneFeatureRequest, initOverrides?: RequestInit): Promise<runtime.ApiResponse<FeatureSchema>> {
|
async cloneFeatureRaw(requestParameters: CloneFeatureRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<runtime.ApiResponse<FeatureSchema>> {
|
||||||
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
||||||
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling cloneFeature.');
|
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling cloneFeature.');
|
||||||
}
|
}
|
||||||
@ -449,14 +398,14 @@ export class AdminApi extends runtime.BaseAPI {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async cloneFeature(requestParameters: CloneFeatureRequest, initOverrides?: RequestInit): Promise<FeatureSchema> {
|
async cloneFeature(requestParameters: CloneFeatureRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<FeatureSchema> {
|
||||||
const response = await this.cloneFeatureRaw(requestParameters, initOverrides);
|
const response = await this.cloneFeatureRaw(requestParameters, initOverrides);
|
||||||
return await response.value();
|
return await response.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async createFeatureRaw(requestParameters: CreateFeatureRequest, initOverrides?: RequestInit): Promise<runtime.ApiResponse<FeatureSchema>> {
|
async createFeatureRaw(requestParameters: CreateFeatureRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<runtime.ApiResponse<FeatureSchema>> {
|
||||||
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
||||||
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling createFeature.');
|
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling createFeature.');
|
||||||
}
|
}
|
||||||
@ -488,14 +437,14 @@ export class AdminApi extends runtime.BaseAPI {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async createFeature(requestParameters: CreateFeatureRequest, initOverrides?: RequestInit): Promise<FeatureSchema> {
|
async createFeature(requestParameters: CreateFeatureRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<FeatureSchema> {
|
||||||
const response = await this.createFeatureRaw(requestParameters, initOverrides);
|
const response = await this.createFeatureRaw(requestParameters, initOverrides);
|
||||||
return await response.value();
|
return await response.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async deleteStrategyRaw(requestParameters: DeleteStrategyRequest, initOverrides?: RequestInit): Promise<runtime.ApiResponse<object>> {
|
async deleteStrategyRaw(requestParameters: DeleteStrategyRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<runtime.ApiResponse<object>> {
|
||||||
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
||||||
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling deleteStrategy.');
|
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling deleteStrategy.');
|
||||||
}
|
}
|
||||||
@ -532,14 +481,14 @@ export class AdminApi extends runtime.BaseAPI {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async deleteStrategy(requestParameters: DeleteStrategyRequest, initOverrides?: RequestInit): Promise<object> {
|
async deleteStrategy(requestParameters: DeleteStrategyRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<object> {
|
||||||
const response = await this.deleteStrategyRaw(requestParameters, initOverrides);
|
const response = await this.deleteStrategyRaw(requestParameters, initOverrides);
|
||||||
return await response.value();
|
return await response.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async getAllTogglesRaw(initOverrides?: RequestInit): Promise<runtime.ApiResponse<FeaturesSchema>> {
|
async getAllTogglesRaw(initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<runtime.ApiResponse<FeaturesSchema>> {
|
||||||
const queryParameters: any = {};
|
const queryParameters: any = {};
|
||||||
|
|
||||||
const headerParameters: runtime.HTTPHeaders = {};
|
const headerParameters: runtime.HTTPHeaders = {};
|
||||||
@ -560,14 +509,14 @@ export class AdminApi extends runtime.BaseAPI {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async getAllToggles(initOverrides?: RequestInit): Promise<FeaturesSchema> {
|
async getAllToggles(initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<FeaturesSchema> {
|
||||||
const response = await this.getAllTogglesRaw(initOverrides);
|
const response = await this.getAllTogglesRaw(initOverrides);
|
||||||
return await response.value();
|
return await response.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async getEnvironmentRaw(requestParameters: GetEnvironmentRequest, initOverrides?: RequestInit): Promise<runtime.ApiResponse<FeatureEnvironmentSchema>> {
|
async getEnvironmentRaw(requestParameters: GetEnvironmentRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<runtime.ApiResponse<FeatureEnvironmentSchema>> {
|
||||||
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
||||||
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling getEnvironment.');
|
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling getEnvironment.');
|
||||||
}
|
}
|
||||||
@ -600,14 +549,14 @@ export class AdminApi extends runtime.BaseAPI {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async getEnvironment(requestParameters: GetEnvironmentRequest, initOverrides?: RequestInit): Promise<FeatureEnvironmentSchema> {
|
async getEnvironment(requestParameters: GetEnvironmentRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<FeatureEnvironmentSchema> {
|
||||||
const response = await this.getEnvironmentRaw(requestParameters, initOverrides);
|
const response = await this.getEnvironmentRaw(requestParameters, initOverrides);
|
||||||
return await response.value();
|
return await response.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async getFeatureRaw(requestParameters: GetFeatureRequest, initOverrides?: RequestInit): Promise<runtime.ApiResponse<FeatureSchema>> {
|
async getFeatureRaw(requestParameters: GetFeatureRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<runtime.ApiResponse<FeatureSchema>> {
|
||||||
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
||||||
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling getFeature.');
|
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling getFeature.');
|
||||||
}
|
}
|
||||||
@ -636,14 +585,14 @@ export class AdminApi extends runtime.BaseAPI {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async getFeature(requestParameters: GetFeatureRequest, initOverrides?: RequestInit): Promise<FeatureSchema> {
|
async getFeature(requestParameters: GetFeatureRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<FeatureSchema> {
|
||||||
const response = await this.getFeatureRaw(requestParameters, initOverrides);
|
const response = await this.getFeatureRaw(requestParameters, initOverrides);
|
||||||
return await response.value();
|
return await response.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async getFeaturesRaw(requestParameters: GetFeaturesRequest, initOverrides?: RequestInit): Promise<runtime.ApiResponse<FeaturesSchema>> {
|
async getFeaturesRaw(requestParameters: GetFeaturesRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<runtime.ApiResponse<FeaturesSchema>> {
|
||||||
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
||||||
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling getFeatures.');
|
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling getFeatures.');
|
||||||
}
|
}
|
||||||
@ -668,14 +617,14 @@ export class AdminApi extends runtime.BaseAPI {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async getFeatures(requestParameters: GetFeaturesRequest, initOverrides?: RequestInit): Promise<FeaturesSchema> {
|
async getFeatures(requestParameters: GetFeaturesRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<FeaturesSchema> {
|
||||||
const response = await this.getFeaturesRaw(requestParameters, initOverrides);
|
const response = await this.getFeaturesRaw(requestParameters, initOverrides);
|
||||||
return await response.value();
|
return await response.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async getStrategiesRaw(requestParameters: GetStrategiesRequest, initOverrides?: RequestInit): Promise<runtime.ApiResponse<Array<StrategySchema>>> {
|
async getStrategiesRaw(requestParameters: GetStrategiesRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<runtime.ApiResponse<Array<StrategySchema>>> {
|
||||||
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
||||||
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling getStrategies.');
|
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling getStrategies.');
|
||||||
}
|
}
|
||||||
@ -708,14 +657,14 @@ export class AdminApi extends runtime.BaseAPI {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async getStrategies(requestParameters: GetStrategiesRequest, initOverrides?: RequestInit): Promise<Array<StrategySchema>> {
|
async getStrategies(requestParameters: GetStrategiesRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<Array<StrategySchema>> {
|
||||||
const response = await this.getStrategiesRaw(requestParameters, initOverrides);
|
const response = await this.getStrategiesRaw(requestParameters, initOverrides);
|
||||||
return await response.value();
|
return await response.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async getStrategyRaw(requestParameters: GetStrategyRequest, initOverrides?: RequestInit): Promise<runtime.ApiResponse<FeatureStrategySchema>> {
|
async getStrategyRaw(requestParameters: GetStrategyRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<runtime.ApiResponse<FeatureStrategySchema>> {
|
||||||
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
||||||
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling getStrategy.');
|
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling getStrategy.');
|
||||||
}
|
}
|
||||||
@ -752,14 +701,14 @@ export class AdminApi extends runtime.BaseAPI {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async getStrategy(requestParameters: GetStrategyRequest, initOverrides?: RequestInit): Promise<FeatureStrategySchema> {
|
async getStrategy(requestParameters: GetStrategyRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<FeatureStrategySchema> {
|
||||||
const response = await this.getStrategyRaw(requestParameters, initOverrides);
|
const response = await this.getStrategyRaw(requestParameters, initOverrides);
|
||||||
return await response.value();
|
return await response.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async listTagsRaw(requestParameters: ListTagsRequest, initOverrides?: RequestInit): Promise<runtime.ApiResponse<TagsResponseSchema>> {
|
async listTagsRaw(requestParameters: ListTagsRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<runtime.ApiResponse<TagsResponseSchema>> {
|
||||||
if (requestParameters.featureName === null || requestParameters.featureName === undefined) {
|
if (requestParameters.featureName === null || requestParameters.featureName === undefined) {
|
||||||
throw new runtime.RequiredError('featureName','Required parameter requestParameters.featureName was null or undefined when calling listTags.');
|
throw new runtime.RequiredError('featureName','Required parameter requestParameters.featureName was null or undefined when calling listTags.');
|
||||||
}
|
}
|
||||||
@ -784,14 +733,14 @@ export class AdminApi extends runtime.BaseAPI {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async listTags(requestParameters: ListTagsRequest, initOverrides?: RequestInit): Promise<TagsResponseSchema> {
|
async listTags(requestParameters: ListTagsRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<TagsResponseSchema> {
|
||||||
const response = await this.listTagsRaw(requestParameters, initOverrides);
|
const response = await this.listTagsRaw(requestParameters, initOverrides);
|
||||||
return await response.value();
|
return await response.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async patchFeatureRaw(requestParameters: PatchFeatureRequest, initOverrides?: RequestInit): Promise<runtime.ApiResponse<FeatureSchema>> {
|
async patchFeatureRaw(requestParameters: PatchFeatureRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<runtime.ApiResponse<FeatureSchema>> {
|
||||||
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
||||||
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling patchFeature.');
|
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling patchFeature.');
|
||||||
}
|
}
|
||||||
@ -827,14 +776,14 @@ export class AdminApi extends runtime.BaseAPI {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async patchFeature(requestParameters: PatchFeatureRequest, initOverrides?: RequestInit): Promise<FeatureSchema> {
|
async patchFeature(requestParameters: PatchFeatureRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<FeatureSchema> {
|
||||||
const response = await this.patchFeatureRaw(requestParameters, initOverrides);
|
const response = await this.patchFeatureRaw(requestParameters, initOverrides);
|
||||||
return await response.value();
|
return await response.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async patchStrategyRaw(requestParameters: PatchStrategyRequest, initOverrides?: RequestInit): Promise<runtime.ApiResponse<FeatureStrategySchema>> {
|
async patchStrategyRaw(requestParameters: PatchStrategyRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<runtime.ApiResponse<FeatureStrategySchema>> {
|
||||||
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
||||||
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling patchStrategy.');
|
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling patchStrategy.');
|
||||||
}
|
}
|
||||||
@ -878,14 +827,14 @@ export class AdminApi extends runtime.BaseAPI {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async patchStrategy(requestParameters: PatchStrategyRequest, initOverrides?: RequestInit): Promise<FeatureStrategySchema> {
|
async patchStrategy(requestParameters: PatchStrategyRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<FeatureStrategySchema> {
|
||||||
const response = await this.patchStrategyRaw(requestParameters, initOverrides);
|
const response = await this.patchStrategyRaw(requestParameters, initOverrides);
|
||||||
return await response.value();
|
return await response.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async removeTagRaw(requestParameters: RemoveTagRequest, initOverrides?: RequestInit): Promise<runtime.ApiResponse<object>> {
|
async removeTagRaw(requestParameters: RemoveTagRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<runtime.ApiResponse<object>> {
|
||||||
if (requestParameters.featureName === null || requestParameters.featureName === undefined) {
|
if (requestParameters.featureName === null || requestParameters.featureName === undefined) {
|
||||||
throw new runtime.RequiredError('featureName','Required parameter requestParameters.featureName was null or undefined when calling removeTag.');
|
throw new runtime.RequiredError('featureName','Required parameter requestParameters.featureName was null or undefined when calling removeTag.');
|
||||||
}
|
}
|
||||||
@ -918,14 +867,14 @@ export class AdminApi extends runtime.BaseAPI {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async removeTag(requestParameters: RemoveTagRequest, initOverrides?: RequestInit): Promise<object> {
|
async removeTag(requestParameters: RemoveTagRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<object> {
|
||||||
const response = await this.removeTagRaw(requestParameters, initOverrides);
|
const response = await this.removeTagRaw(requestParameters, initOverrides);
|
||||||
return await response.value();
|
return await response.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async toggleEnvironmentOffRaw(requestParameters: ToggleEnvironmentOffRequest, initOverrides?: RequestInit): Promise<runtime.ApiResponse<FeatureSchema>> {
|
async toggleEnvironmentOffRaw(requestParameters: ToggleEnvironmentOffRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<runtime.ApiResponse<FeatureSchema>> {
|
||||||
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
||||||
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling toggleEnvironmentOff.');
|
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling toggleEnvironmentOff.');
|
||||||
}
|
}
|
||||||
@ -958,14 +907,14 @@ export class AdminApi extends runtime.BaseAPI {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async toggleEnvironmentOff(requestParameters: ToggleEnvironmentOffRequest, initOverrides?: RequestInit): Promise<FeatureSchema> {
|
async toggleEnvironmentOff(requestParameters: ToggleEnvironmentOffRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<FeatureSchema> {
|
||||||
const response = await this.toggleEnvironmentOffRaw(requestParameters, initOverrides);
|
const response = await this.toggleEnvironmentOffRaw(requestParameters, initOverrides);
|
||||||
return await response.value();
|
return await response.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async toggleEnvironmentOnRaw(requestParameters: ToggleEnvironmentOnRequest, initOverrides?: RequestInit): Promise<runtime.ApiResponse<FeatureSchema>> {
|
async toggleEnvironmentOnRaw(requestParameters: ToggleEnvironmentOnRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<runtime.ApiResponse<FeatureSchema>> {
|
||||||
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
||||||
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling toggleEnvironmentOn.');
|
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling toggleEnvironmentOn.');
|
||||||
}
|
}
|
||||||
@ -998,14 +947,14 @@ export class AdminApi extends runtime.BaseAPI {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async toggleEnvironmentOn(requestParameters: ToggleEnvironmentOnRequest, initOverrides?: RequestInit): Promise<FeatureSchema> {
|
async toggleEnvironmentOn(requestParameters: ToggleEnvironmentOnRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<FeatureSchema> {
|
||||||
const response = await this.toggleEnvironmentOnRaw(requestParameters, initOverrides);
|
const response = await this.toggleEnvironmentOnRaw(requestParameters, initOverrides);
|
||||||
return await response.value();
|
return await response.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async updateFeatureRaw(requestParameters: UpdateFeatureRequest, initOverrides?: RequestInit): Promise<runtime.ApiResponse<FeatureSchema>> {
|
async updateFeatureRaw(requestParameters: UpdateFeatureRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<runtime.ApiResponse<FeatureSchema>> {
|
||||||
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
||||||
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling updateFeature.');
|
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling updateFeature.');
|
||||||
}
|
}
|
||||||
@ -1041,14 +990,14 @@ export class AdminApi extends runtime.BaseAPI {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async updateFeature(requestParameters: UpdateFeatureRequest, initOverrides?: RequestInit): Promise<FeatureSchema> {
|
async updateFeature(requestParameters: UpdateFeatureRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<FeatureSchema> {
|
||||||
const response = await this.updateFeatureRaw(requestParameters, initOverrides);
|
const response = await this.updateFeatureRaw(requestParameters, initOverrides);
|
||||||
return await response.value();
|
return await response.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async updateStrategyRaw(requestParameters: UpdateStrategyRequest, initOverrides?: RequestInit): Promise<runtime.ApiResponse<FeatureStrategySchema>> {
|
async updateStrategyRaw(requestParameters: UpdateStrategyRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<runtime.ApiResponse<FeatureStrategySchema>> {
|
||||||
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
|
||||||
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling updateStrategy.');
|
throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling updateStrategy.');
|
||||||
}
|
}
|
||||||
@ -1092,14 +1041,14 @@ export class AdminApi extends runtime.BaseAPI {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async updateStrategy(requestParameters: UpdateStrategyRequest, initOverrides?: RequestInit): Promise<FeatureStrategySchema> {
|
async updateStrategy(requestParameters: UpdateStrategyRequest, initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<FeatureStrategySchema> {
|
||||||
const response = await this.updateStrategyRaw(requestParameters, initOverrides);
|
const response = await this.updateStrategyRaw(requestParameters, initOverrides);
|
||||||
return await response.value();
|
return await response.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async validateFeatureRaw(initOverrides?: RequestInit): Promise<runtime.ApiResponse<object>> {
|
async validateFeatureRaw(initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<runtime.ApiResponse<object>> {
|
||||||
const queryParameters: any = {};
|
const queryParameters: any = {};
|
||||||
|
|
||||||
const headerParameters: runtime.HTTPHeaders = {};
|
const headerParameters: runtime.HTTPHeaders = {};
|
||||||
@ -1120,7 +1069,7 @@ export class AdminApi extends runtime.BaseAPI {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async validateFeature(initOverrides?: RequestInit): Promise<object> {
|
async validateFeature(initOverrides?: RequestInit | runtime.InitOverideFunction): Promise<object> {
|
||||||
const response = await this.validateFeatureRaw(initOverrides);
|
const response = await this.validateFeatureRaw(initOverrides);
|
||||||
return await response.value();
|
return await response.value();
|
||||||
}
|
}
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
/**
|
|
||||||
* Unleash API
|
|
||||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
|
||||||
*
|
|
||||||
* The version of the OpenAPI document: 4.11.0-beta.2
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
|
||||||
* https://openapi-generator.tech
|
|
||||||
* Do not edit the class manually.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { exists, mapValues } from '../runtime';
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
* @interface ChangeProjectSchema
|
|
||||||
*/
|
|
||||||
export interface ChangeProjectSchema {
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof ChangeProjectSchema
|
|
||||||
*/
|
|
||||||
newProjectId: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function ChangeProjectSchemaFromJSON(json: any): ChangeProjectSchema {
|
|
||||||
return ChangeProjectSchemaFromJSONTyped(json, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function ChangeProjectSchemaFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChangeProjectSchema {
|
|
||||||
if ((json === undefined) || (json === null)) {
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
|
|
||||||
'newProjectId': json['newProjectId'],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function ChangeProjectSchemaToJSON(value?: ChangeProjectSchema | null): any {
|
|
||||||
if (value === undefined) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
if (value === null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
|
|
||||||
'newProjectId': value.newProjectId,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -57,27 +57,29 @@ export interface ConstraintSchema {
|
|||||||
value?: string;
|
value?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @export
|
* @export
|
||||||
* @enum {string}
|
*/
|
||||||
*/
|
export const ConstraintSchemaOperatorEnum = {
|
||||||
export enum ConstraintSchemaOperatorEnum {
|
NotIn: 'NOT_IN',
|
||||||
NotIn = 'NOT_IN',
|
In: 'IN',
|
||||||
In = 'IN',
|
StrEndsWith: 'STR_ENDS_WITH',
|
||||||
StrEndsWith = 'STR_ENDS_WITH',
|
StrStartsWith: 'STR_STARTS_WITH',
|
||||||
StrStartsWith = 'STR_STARTS_WITH',
|
StrContains: 'STR_CONTAINS',
|
||||||
StrContains = 'STR_CONTAINS',
|
NumEq: 'NUM_EQ',
|
||||||
NumEq = 'NUM_EQ',
|
NumGt: 'NUM_GT',
|
||||||
NumGt = 'NUM_GT',
|
NumGte: 'NUM_GTE',
|
||||||
NumGte = 'NUM_GTE',
|
NumLt: 'NUM_LT',
|
||||||
NumLt = 'NUM_LT',
|
NumLte: 'NUM_LTE',
|
||||||
NumLte = 'NUM_LTE',
|
DateAfter: 'DATE_AFTER',
|
||||||
DateAfter = 'DATE_AFTER',
|
DateBefore: 'DATE_BEFORE',
|
||||||
DateBefore = 'DATE_BEFORE',
|
SemverEq: 'SEMVER_EQ',
|
||||||
SemverEq = 'SEMVER_EQ',
|
SemverGt: 'SEMVER_GT',
|
||||||
SemverGt = 'SEMVER_GT',
|
SemverLt: 'SEMVER_LT'
|
||||||
SemverLt = 'SEMVER_LT'
|
} as const;
|
||||||
}
|
export type ConstraintSchemaOperatorEnum = typeof ConstraintSchemaOperatorEnum[keyof typeof ConstraintSchemaOperatorEnum];
|
||||||
|
|
||||||
|
|
||||||
export function ConstraintSchemaFromJSON(json: any): ConstraintSchema {
|
export function ConstraintSchemaFromJSON(json: any): ConstraintSchema {
|
||||||
return ConstraintSchemaFromJSONTyped(json, false);
|
return ConstraintSchemaFromJSONTyped(json, false);
|
||||||
|
@ -92,6 +92,12 @@ export interface FeatureSchema {
|
|||||||
* @memberof FeatureSchema
|
* @memberof FeatureSchema
|
||||||
*/
|
*/
|
||||||
createdAt?: Date | null;
|
createdAt?: Date | null;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {Date}
|
||||||
|
* @memberof FeatureSchema
|
||||||
|
*/
|
||||||
|
archivedAt?: Date | null;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {Date}
|
* @type {Date}
|
||||||
@ -137,6 +143,7 @@ export function FeatureSchemaFromJSONTyped(json: any, ignoreDiscriminator: boole
|
|||||||
'stale': !exists(json, 'stale') ? undefined : json['stale'],
|
'stale': !exists(json, 'stale') ? undefined : json['stale'],
|
||||||
'impressionData': !exists(json, 'impressionData') ? undefined : json['impressionData'],
|
'impressionData': !exists(json, 'impressionData') ? undefined : json['impressionData'],
|
||||||
'createdAt': !exists(json, 'createdAt') ? undefined : (json['createdAt'] === null ? null : new Date(json['createdAt'])),
|
'createdAt': !exists(json, 'createdAt') ? undefined : (json['createdAt'] === null ? null : new Date(json['createdAt'])),
|
||||||
|
'archivedAt': !exists(json, 'archivedAt') ? undefined : (json['archivedAt'] === null ? null : new Date(json['archivedAt'])),
|
||||||
'lastSeenAt': !exists(json, 'lastSeenAt') ? undefined : (json['lastSeenAt'] === null ? null : new Date(json['lastSeenAt'])),
|
'lastSeenAt': !exists(json, 'lastSeenAt') ? undefined : (json['lastSeenAt'] === null ? null : new Date(json['lastSeenAt'])),
|
||||||
'environments': !exists(json, 'environments') ? undefined : ((json['environments'] as Array<any>).map(FeatureEnvironmentSchemaFromJSON)),
|
'environments': !exists(json, 'environments') ? undefined : ((json['environments'] as Array<any>).map(FeatureEnvironmentSchemaFromJSON)),
|
||||||
'strategies': !exists(json, 'strategies') ? undefined : ((json['strategies'] as Array<any>).map(StrategySchemaFromJSON)),
|
'strategies': !exists(json, 'strategies') ? undefined : ((json['strategies'] as Array<any>).map(StrategySchemaFromJSON)),
|
||||||
@ -162,6 +169,7 @@ export function FeatureSchemaToJSON(value?: FeatureSchema | null): any {
|
|||||||
'stale': value.stale,
|
'stale': value.stale,
|
||||||
'impressionData': value.impressionData,
|
'impressionData': value.impressionData,
|
||||||
'createdAt': value.createdAt === undefined ? undefined : (value.createdAt === null ? null : value.createdAt.toISOString().substr(0,10)),
|
'createdAt': value.createdAt === undefined ? undefined : (value.createdAt === null ? null : value.createdAt.toISOString().substr(0,10)),
|
||||||
|
'archivedAt': value.archivedAt === undefined ? undefined : (value.archivedAt === null ? null : value.archivedAt.toISOString().substr(0,10)),
|
||||||
'lastSeenAt': value.lastSeenAt === undefined ? undefined : (value.lastSeenAt === null ? null : value.lastSeenAt.toISOString().substr(0,10)),
|
'lastSeenAt': value.lastSeenAt === undefined ? undefined : (value.lastSeenAt === null ? null : value.lastSeenAt.toISOString().substr(0,10)),
|
||||||
'environments': value.environments === undefined ? undefined : ((value.environments as Array<any>).map(FeatureEnvironmentSchemaToJSON)),
|
'environments': value.environments === undefined ? undefined : ((value.environments as Array<any>).map(FeatureEnvironmentSchemaToJSON)),
|
||||||
'strategies': value.strategies === undefined ? undefined : ((value.strategies as Array<any>).map(StrategySchemaToJSON)),
|
'strategies': value.strategies === undefined ? undefined : ((value.strategies as Array<any>).map(StrategySchemaToJSON)),
|
||||||
|
@ -45,17 +45,19 @@ export interface PatchOperationSchema {
|
|||||||
value?: any | null;
|
value?: any | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @export
|
* @export
|
||||||
* @enum {string}
|
*/
|
||||||
*/
|
export const PatchOperationSchemaOpEnum = {
|
||||||
export enum PatchOperationSchemaOpEnum {
|
Add: 'add',
|
||||||
Add = 'add',
|
Remove: 'remove',
|
||||||
Remove = 'remove',
|
Replace: 'replace',
|
||||||
Replace = 'replace',
|
Copy: 'copy',
|
||||||
Copy = 'copy',
|
Move: 'move'
|
||||||
Move = 'move'
|
} as const;
|
||||||
}
|
export type PatchOperationSchemaOpEnum = typeof PatchOperationSchemaOpEnum[keyof typeof PatchOperationSchemaOpEnum];
|
||||||
|
|
||||||
|
|
||||||
export function PatchOperationSchemaFromJSON(json: any): PatchOperationSchema {
|
export function PatchOperationSchemaFromJSON(json: any): PatchOperationSchema {
|
||||||
return PatchOperationSchemaFromJSONTyped(json, false);
|
return PatchOperationSchemaFromJSONTyped(json, false);
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
/* tslint:disable */
|
/* tslint:disable */
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
export * from './ChangeProjectSchema';
|
|
||||||
export * from './CloneFeatureSchema';
|
export * from './CloneFeatureSchema';
|
||||||
export * from './ConstraintSchema';
|
export * from './ConstraintSchema';
|
||||||
export * from './CreateFeatureSchema';
|
export * from './CreateFeatureSchema';
|
||||||
|
@ -15,119 +15,6 @@
|
|||||||
|
|
||||||
export const BASE_PATH = "http://localhost:4242".replace(/\/+$/, "");
|
export const BASE_PATH = "http://localhost:4242".replace(/\/+$/, "");
|
||||||
|
|
||||||
const isBlob = (value: any) => typeof Blob !== 'undefined' && value instanceof Blob;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is the base class for all generated API classes.
|
|
||||||
*/
|
|
||||||
export class BaseAPI {
|
|
||||||
|
|
||||||
private middleware: Middleware[];
|
|
||||||
|
|
||||||
constructor(protected configuration = new Configuration()) {
|
|
||||||
this.middleware = configuration.middleware;
|
|
||||||
}
|
|
||||||
|
|
||||||
withMiddleware<T extends BaseAPI>(this: T, ...middlewares: Middleware[]) {
|
|
||||||
const next = this.clone<T>();
|
|
||||||
next.middleware = next.middleware.concat(...middlewares);
|
|
||||||
return next;
|
|
||||||
}
|
|
||||||
|
|
||||||
withPreMiddleware<T extends BaseAPI>(this: T, ...preMiddlewares: Array<Middleware['pre']>) {
|
|
||||||
const middlewares = preMiddlewares.map((pre) => ({ pre }));
|
|
||||||
return this.withMiddleware<T>(...middlewares);
|
|
||||||
}
|
|
||||||
|
|
||||||
withPostMiddleware<T extends BaseAPI>(this: T, ...postMiddlewares: Array<Middleware['post']>) {
|
|
||||||
const middlewares = postMiddlewares.map((post) => ({ post }));
|
|
||||||
return this.withMiddleware<T>(...middlewares);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async request(context: RequestOpts, initOverrides?: RequestInit): Promise<Response> {
|
|
||||||
const { url, init } = this.createFetchParams(context, initOverrides);
|
|
||||||
const response = await this.fetchApi(url, init);
|
|
||||||
if (response.status >= 200 && response.status < 300) {
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
throw response;
|
|
||||||
}
|
|
||||||
|
|
||||||
private createFetchParams(context: RequestOpts, initOverrides?: RequestInit) {
|
|
||||||
let url = this.configuration.basePath + context.path;
|
|
||||||
if (context.query !== undefined && Object.keys(context.query).length !== 0) {
|
|
||||||
// only add the querystring to the URL if there are query parameters.
|
|
||||||
// this is done to avoid urls ending with a "?" character which buggy webservers
|
|
||||||
// do not handle correctly sometimes.
|
|
||||||
url += '?' + this.configuration.queryParamsStringify(context.query);
|
|
||||||
}
|
|
||||||
const body = ((typeof FormData !== "undefined" && context.body instanceof FormData) || context.body instanceof URLSearchParams || isBlob(context.body))
|
|
||||||
? context.body
|
|
||||||
: JSON.stringify(context.body);
|
|
||||||
|
|
||||||
const headers = Object.assign({}, this.configuration.headers, context.headers);
|
|
||||||
const init = {
|
|
||||||
method: context.method,
|
|
||||||
headers: headers,
|
|
||||||
body,
|
|
||||||
credentials: this.configuration.credentials,
|
|
||||||
...initOverrides
|
|
||||||
};
|
|
||||||
return { url, init };
|
|
||||||
}
|
|
||||||
|
|
||||||
private fetchApi = async (url: string, init: RequestInit) => {
|
|
||||||
let fetchParams = { url, init };
|
|
||||||
for (const middleware of this.middleware) {
|
|
||||||
if (middleware.pre) {
|
|
||||||
fetchParams = await middleware.pre({
|
|
||||||
fetch: this.fetchApi,
|
|
||||||
...fetchParams,
|
|
||||||
}) || fetchParams;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let response = await (this.configuration.fetchApi || fetch)(fetchParams.url, fetchParams.init);
|
|
||||||
for (const middleware of this.middleware) {
|
|
||||||
if (middleware.post) {
|
|
||||||
response = await middleware.post({
|
|
||||||
fetch: this.fetchApi,
|
|
||||||
url: fetchParams.url,
|
|
||||||
init: fetchParams.init,
|
|
||||||
response: response.clone(),
|
|
||||||
}) || response;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a shallow clone of `this` by constructing a new instance
|
|
||||||
* and then shallow cloning data members.
|
|
||||||
*/
|
|
||||||
private clone<T extends BaseAPI>(this: T): T {
|
|
||||||
const constructor = this.constructor as any;
|
|
||||||
const next = new constructor(this.configuration);
|
|
||||||
next.middleware = this.middleware.slice();
|
|
||||||
return next;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export class RequiredError extends Error {
|
|
||||||
name: "RequiredError" = "RequiredError";
|
|
||||||
constructor(public field: string, msg?: string) {
|
|
||||||
super(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const COLLECTION_FORMATS = {
|
|
||||||
csv: ",",
|
|
||||||
ssv: " ",
|
|
||||||
tsv: "\t",
|
|
||||||
pipes: "|",
|
|
||||||
};
|
|
||||||
|
|
||||||
export type FetchAPI = GlobalFetch['fetch'];
|
|
||||||
|
|
||||||
export interface ConfigurationParameters {
|
export interface ConfigurationParameters {
|
||||||
basePath?: string; // override base path
|
basePath?: string; // override base path
|
||||||
fetchApi?: FetchAPI; // override for fetch implementation
|
fetchApi?: FetchAPI; // override for fetch implementation
|
||||||
@ -144,6 +31,10 @@ export interface ConfigurationParameters {
|
|||||||
export class Configuration {
|
export class Configuration {
|
||||||
constructor(private configuration: ConfigurationParameters = {}) {}
|
constructor(private configuration: ConfigurationParameters = {}) {}
|
||||||
|
|
||||||
|
set config(configuration: Configuration) {
|
||||||
|
this.configuration = configuration;
|
||||||
|
}
|
||||||
|
|
||||||
get basePath(): string {
|
get basePath(): string {
|
||||||
return this.configuration.basePath != null ? this.configuration.basePath : BASE_PATH;
|
return this.configuration.basePath != null ? this.configuration.basePath : BASE_PATH;
|
||||||
}
|
}
|
||||||
@ -193,13 +84,166 @@ export class Configuration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const DefaultConfig = new Configuration();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the base class for all generated API classes.
|
||||||
|
*/
|
||||||
|
export class BaseAPI {
|
||||||
|
|
||||||
|
private middleware: Middleware[];
|
||||||
|
|
||||||
|
constructor(protected configuration = DefaultConfig) {
|
||||||
|
this.middleware = configuration.middleware;
|
||||||
|
}
|
||||||
|
|
||||||
|
withMiddleware<T extends BaseAPI>(this: T, ...middlewares: Middleware[]) {
|
||||||
|
const next = this.clone<T>();
|
||||||
|
next.middleware = next.middleware.concat(...middlewares);
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
withPreMiddleware<T extends BaseAPI>(this: T, ...preMiddlewares: Array<Middleware['pre']>) {
|
||||||
|
const middlewares = preMiddlewares.map((pre) => ({ pre }));
|
||||||
|
return this.withMiddleware<T>(...middlewares);
|
||||||
|
}
|
||||||
|
|
||||||
|
withPostMiddleware<T extends BaseAPI>(this: T, ...postMiddlewares: Array<Middleware['post']>) {
|
||||||
|
const middlewares = postMiddlewares.map((post) => ({ post }));
|
||||||
|
return this.withMiddleware<T>(...middlewares);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async request(context: RequestOpts, initOverrides?: RequestInit | InitOverideFunction): Promise<Response> {
|
||||||
|
const { url, init } = await this.createFetchParams(context, initOverrides);
|
||||||
|
const response = await this.fetchApi(url, init);
|
||||||
|
if (response.status >= 200 && response.status < 300) {
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
throw new ResponseError(response, 'Response returned an error code');
|
||||||
|
}
|
||||||
|
|
||||||
|
private async createFetchParams(context: RequestOpts, initOverrides?: RequestInit | InitOverideFunction) {
|
||||||
|
let url = this.configuration.basePath + context.path;
|
||||||
|
if (context.query !== undefined && Object.keys(context.query).length !== 0) {
|
||||||
|
// only add the querystring to the URL if there are query parameters.
|
||||||
|
// this is done to avoid urls ending with a "?" character which buggy webservers
|
||||||
|
// do not handle correctly sometimes.
|
||||||
|
url += '?' + this.configuration.queryParamsStringify(context.query);
|
||||||
|
}
|
||||||
|
|
||||||
|
const headers = Object.assign({}, this.configuration.headers, context.headers);
|
||||||
|
Object.keys(headers).forEach(key => headers[key] === undefined ? delete headers[key] : {});
|
||||||
|
|
||||||
|
const initOverrideFn =
|
||||||
|
typeof initOverrides === "function"
|
||||||
|
? initOverrides
|
||||||
|
: async () => initOverrides;
|
||||||
|
|
||||||
|
const initParams = {
|
||||||
|
method: context.method,
|
||||||
|
headers,
|
||||||
|
body: context.body,
|
||||||
|
credentials: this.configuration.credentials,
|
||||||
|
};
|
||||||
|
|
||||||
|
const overridedInit: RequestInit = {
|
||||||
|
...initParams,
|
||||||
|
...(await initOverrideFn({
|
||||||
|
init: initParams,
|
||||||
|
context,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
const init: RequestInit = {
|
||||||
|
...overridedInit,
|
||||||
|
body:
|
||||||
|
isFormData(overridedInit.body) ||
|
||||||
|
overridedInit.body instanceof URLSearchParams ||
|
||||||
|
isBlob(overridedInit.body)
|
||||||
|
? overridedInit.body
|
||||||
|
: JSON.stringify(overridedInit.body),
|
||||||
|
};
|
||||||
|
|
||||||
|
return { url, init };
|
||||||
|
}
|
||||||
|
|
||||||
|
private fetchApi = async (url: string, init: RequestInit) => {
|
||||||
|
let fetchParams = { url, init };
|
||||||
|
for (const middleware of this.middleware) {
|
||||||
|
if (middleware.pre) {
|
||||||
|
fetchParams = await middleware.pre({
|
||||||
|
fetch: this.fetchApi,
|
||||||
|
...fetchParams,
|
||||||
|
}) || fetchParams;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let response = await (this.configuration.fetchApi || fetch)(fetchParams.url, fetchParams.init);
|
||||||
|
for (const middleware of this.middleware) {
|
||||||
|
if (middleware.post) {
|
||||||
|
response = await middleware.post({
|
||||||
|
fetch: this.fetchApi,
|
||||||
|
url: fetchParams.url,
|
||||||
|
init: fetchParams.init,
|
||||||
|
response: response.clone(),
|
||||||
|
}) || response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a shallow clone of `this` by constructing a new instance
|
||||||
|
* and then shallow cloning data members.
|
||||||
|
*/
|
||||||
|
private clone<T extends BaseAPI>(this: T): T {
|
||||||
|
const constructor = this.constructor as any;
|
||||||
|
const next = new constructor(this.configuration);
|
||||||
|
next.middleware = this.middleware.slice();
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function isBlob(value: any): value is Blob {
|
||||||
|
return typeof Blob !== 'undefined' && value instanceof Blob
|
||||||
|
}
|
||||||
|
|
||||||
|
function isFormData(value: any): value is FormData {
|
||||||
|
return typeof FormData !== "undefined" && value instanceof FormData
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ResponseError extends Error {
|
||||||
|
name: "ResponseError" = "ResponseError";
|
||||||
|
constructor(public response: Response, msg?: string) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class RequiredError extends Error {
|
||||||
|
name: "RequiredError" = "RequiredError";
|
||||||
|
constructor(public field: string, msg?: string) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const COLLECTION_FORMATS = {
|
||||||
|
csv: ",",
|
||||||
|
ssv: " ",
|
||||||
|
tsv: "\t",
|
||||||
|
pipes: "|",
|
||||||
|
};
|
||||||
|
|
||||||
|
export type FetchAPI = WindowOrWorkerGlobalScope['fetch'];
|
||||||
|
|
||||||
export type Json = any;
|
export type Json = any;
|
||||||
export type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD';
|
export type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD';
|
||||||
export type HTTPHeaders = { [key: string]: string };
|
export type HTTPHeaders = { [key: string]: string };
|
||||||
export type HTTPQuery = { [key: string]: string | number | null | boolean | Array<string | number | null | boolean> | HTTPQuery };
|
export type HTTPQuery = { [key: string]: string | number | null | boolean | Array<string | number | null | boolean> | Set<string | number | null | boolean> | HTTPQuery };
|
||||||
export type HTTPBody = Json | FormData | URLSearchParams;
|
export type HTTPBody = Json | FormData | URLSearchParams;
|
||||||
|
export type HTTPRequestInit = { headers?: HTTPHeaders; method: HTTPMethod; credentials?: RequestCredentials; body?: HTTPBody }
|
||||||
export type ModelPropertyNaming = 'camelCase' | 'snake_case' | 'PascalCase' | 'original';
|
export type ModelPropertyNaming = 'camelCase' | 'snake_case' | 'PascalCase' | 'original';
|
||||||
|
|
||||||
|
export type InitOverideFunction = (requestContext: { init: HTTPRequestInit, context: RequestOpts }) => Promise<RequestInit>
|
||||||
|
|
||||||
export interface FetchParams {
|
export interface FetchParams {
|
||||||
url: string;
|
url: string;
|
||||||
init: RequestInit;
|
init: RequestInit;
|
||||||
@ -220,26 +264,31 @@ export function exists(json: any, key: string) {
|
|||||||
|
|
||||||
export function querystring(params: HTTPQuery, prefix: string = ''): string {
|
export function querystring(params: HTTPQuery, prefix: string = ''): string {
|
||||||
return Object.keys(params)
|
return Object.keys(params)
|
||||||
.map((key) => {
|
.map(key => querystringSingleKey(key, params[key], prefix))
|
||||||
const fullKey = prefix + (prefix.length ? `[${key}]` : key);
|
|
||||||
const value = params[key];
|
|
||||||
if (value instanceof Array) {
|
|
||||||
const multiValue = value.map(singleValue => encodeURIComponent(String(singleValue)))
|
|
||||||
.join(`&${encodeURIComponent(fullKey)}=`);
|
|
||||||
return `${encodeURIComponent(fullKey)}=${multiValue}`;
|
|
||||||
}
|
|
||||||
if (value instanceof Date) {
|
|
||||||
return `${encodeURIComponent(fullKey)}=${encodeURIComponent(value.toISOString())}`;
|
|
||||||
}
|
|
||||||
if (value instanceof Object) {
|
|
||||||
return querystring(value as HTTPQuery, fullKey);
|
|
||||||
}
|
|
||||||
return `${encodeURIComponent(fullKey)}=${encodeURIComponent(String(value))}`;
|
|
||||||
})
|
|
||||||
.filter(part => part.length > 0)
|
.filter(part => part.length > 0)
|
||||||
.join('&');
|
.join('&');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function querystringSingleKey(key: string, value: string | number | null | boolean | Array<string | number | null | boolean> | Set<string | number | null | boolean> | HTTPQuery, keyPrefix: string = ''): string {
|
||||||
|
const fullKey = keyPrefix + (keyPrefix.length ? `[${key}]` : key);
|
||||||
|
if (value instanceof Array) {
|
||||||
|
const multiValue = value.map(singleValue => encodeURIComponent(String(singleValue)))
|
||||||
|
.join(`&${encodeURIComponent(fullKey)}=`);
|
||||||
|
return `${encodeURIComponent(fullKey)}=${multiValue}`;
|
||||||
|
}
|
||||||
|
if (value instanceof Set) {
|
||||||
|
const valueAsArray = Array.from(value);
|
||||||
|
return querystringSingleKey(key, valueAsArray, keyPrefix);
|
||||||
|
}
|
||||||
|
if (value instanceof Date) {
|
||||||
|
return `${encodeURIComponent(fullKey)}=${encodeURIComponent(value.toISOString())}`;
|
||||||
|
}
|
||||||
|
if (value instanceof Object) {
|
||||||
|
return querystring(value as HTTPQuery, fullKey);
|
||||||
|
}
|
||||||
|
return `${encodeURIComponent(fullKey)}=${encodeURIComponent(String(value))}`;
|
||||||
|
}
|
||||||
|
|
||||||
export function mapValues(data: any, fn: (item: any) => any) {
|
export function mapValues(data: any, fn: (item: any) => any) {
|
||||||
return Object.keys(data).reduce(
|
return Object.keys(data).reduce(
|
||||||
(acc, key) => ({ ...acc, [key]: fn(data[key]) }),
|
(acc, key) => ({ ...acc, [key]: fn(data[key]) }),
|
||||||
|
@ -7,7 +7,7 @@ export const sortTypes = {
|
|||||||
date: (v1: any, v2: any, id: string) => {
|
date: (v1: any, v2: any, id: string) => {
|
||||||
const a = new Date(v1?.values?.[id] || 0);
|
const a = new Date(v1?.values?.[id] || 0);
|
||||||
const b = new Date(v2?.values?.[id] || 0);
|
const b = new Date(v2?.values?.[id] || 0);
|
||||||
return a?.getTime() - b?.getTime();
|
return b?.getTime() - a?.getTime(); // newest first by default
|
||||||
},
|
},
|
||||||
boolean: (v1: any, v2: any, id: string) => {
|
boolean: (v1: any, v2: any, id: string) => {
|
||||||
const a = v1?.values?.[id];
|
const a = v1?.values?.[id];
|
||||||
|
Loading…
Reference in New Issue
Block a user