Skip to content
This repository has been archived by the owner on Oct 27, 2022. It is now read-only.

Commit

Permalink
feat: show archived toggles on a project level (#942)
Browse files Browse the repository at this point in the history
* feat: show archived toggles on a project level

* Update src/component/feature/FeatureToggleList/FeatureToggleListActions/FeatureToggleListActions.tsx

Co-authored-by: Fredrik Strand Oseberg <fredrik.no@gmail.com>

* refactor: adapt code to PR comments, clarity

Co-authored-by: Fredrik Strand Oseberg <fredrik.no@gmail.com>
  • Loading branch information
nunogois and FredrikOseberg authored May 3, 2022
1 parent 0eb2ba9 commit 08ed45f
Show file tree
Hide file tree
Showing 20 changed files with 202 additions and 122 deletions.
58 changes: 58 additions & 0 deletions src/component/archive/ProjectFeaturesArchiveList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { FC } from 'react';
import { useProjectFeaturesArchive } from 'hooks/api/getters/useProjectFeaturesArchive/useProjectFeaturesArchive';
import { FeatureToggleList } from '../feature/FeatureToggleList/FeatureToggleList';
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)}
/>
);
};
14 changes: 12 additions & 2 deletions src/component/feature/FeatureToggleList/FeatureToggleList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ interface IFeatureToggleListProps {
sort: IFeaturesSort;
setSort: Dispatch<SetStateAction<IFeaturesSort>>;
onRevive?: (feature: string) => void;
inProject?: boolean;
isArchive?: boolean;
}

Expand All @@ -52,6 +53,7 @@ const loadingFeaturesPlaceholder: FeatureSchema[] = Array(10)
export const FeatureToggleList: VFC<IFeatureToggleListProps> = ({
features,
onRevive,
inProject,
isArchive,
loading,
flags,
Expand Down Expand Up @@ -95,6 +97,7 @@ export const FeatureToggleList: VFC<IFeatureToggleListProps> = ({
onRevive={onRevive}
hasAccess={hasAccess}
flags={flags}
inProject={inProject}
/>
))}
elseShow={
Expand Down Expand Up @@ -128,12 +131,18 @@ export const FeatureToggleList: VFC<IFeatureToggleListProps> = ({
: '';

const headerTitle = isArchive
? `Archived Features ${searchResultsHeader}`
? inProject
? `Project Archived Features ${searchResultsHeader}`
: `Archived Features ${searchResultsHeader}`
: `Features ${searchResultsHeader}`;

return (
<div>
<div className={styles.searchBarContainer}>
<div
className={classnames(styles.searchBarContainer, {
dense: inProject,
})}
>
<SearchField
initialValue={filter.query}
updateValue={setFilterQuery}
Expand Down Expand Up @@ -164,6 +173,7 @@ export const FeatureToggleList: VFC<IFeatureToggleListProps> = ({
sort={sort}
setSort={setSort}
loading={loading}
inProject={inProject}
/>
}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@ import {
import { useStyles } from './styles';
import { IFeaturesFilter } from 'hooks/useFeaturesFilter';

const sortOptions = createFeaturesFilterSortOptions();
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> = ({
Expand All @@ -29,6 +30,7 @@ export const FeatureToggleListActions: VFC<IFeatureToggleListActionsProps> = ({
sort,
setSort,
loading = false,
inProject,
}) => {
const { classes: styles } = useStyles();
const { uiConfig } = useUiConfig();
Expand All @@ -46,6 +48,10 @@ export const FeatureToggleListActions: VFC<IFeatureToggleListActionsProps> = ({
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
Expand Down Expand Up @@ -73,7 +79,7 @@ export const FeatureToggleListActions: VFC<IFeatureToggleListActionsProps> = ({
data-loading
/>
<ConditionallyRender
condition={uiConfig.flags.P}
condition={uiConfig.flags.P && !inProject}
show={
<ProjectSelect
currentProjectId={filter.project}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,20 @@ interface IFeatureToggleListItemProps {
onRevive?: (id: string) => void;
hasAccess: IAccessContext['hasAccess'];
flags?: IFlags;
inProject?: boolean;
className?: string;
}

export const FeatureToggleListItem = memo<IFeatureToggleListItemProps>(
({ feature, onRevive, hasAccess, flags = {}, className, ...rest }) => {
({
feature,
onRevive,
hasAccess,
flags = {},
inProject,
className,
...rest
}) => {
const { classes: styles } = useStyles();

const { projects } = useProjects();
Expand Down Expand Up @@ -153,21 +162,30 @@ export const FeatureToggleListItem = memo<IFeatureToggleListItemProps>(
)}
>
<StatusChip stale={Boolean(stale)} showActive={false} />
<Link
to={`/projects/${project}`}
style={{ textDecoration: 'none' }}
className={classnames({
[`${styles.disabledLink}`]: !projectExists(),
})}
>
<Chip
color="primary"
variant="outlined"
style={{ marginLeft: '8px', cursor: 'pointer' }}
title={`Project: ${project}`}
label={project}
/>
</Link>
<ConditionallyRender
condition={!inProject}
show={
<Link
to={`/projects/${project}`}
style={{ textDecoration: 'none' }}
className={classnames({
[`${styles.disabledLink}`]:
!projectExists(),
})}
>
<Chip
color="primary"
variant="outlined"
style={{
marginLeft: '8px',
cursor: 'pointer',
}}
title={`Project: ${project}`}
label={project}
/>
</Link>
}
/>
</span>
<ConditionallyRender
condition={isArchive}
Expand Down
3 changes: 3 additions & 0 deletions src/component/feature/FeatureToggleList/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ export const useStyles = makeStyles()(theme => ({
[theme.breakpoints.down('sm')]: {
display: 'block',
},
'&.dense': {
marginBottom: '1rem',
},
},
searchBar: {
minWidth: '450px',
Expand Down
7 changes: 7 additions & 0 deletions src/component/project/Project/Project.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import useQueryParams from 'hooks/useQueryParams';
import { useEffect } from 'react';
import { ProjectAccess } from '../ProjectAccess/ProjectAccess';
import ProjectEnvironment from '../ProjectEnvironment/ProjectEnvironment';
import { ProjectFeaturesArchive } from './ProjectFeaturesArchive/ProjectFeaturesArchive';
import ProjectOverview from './ProjectOverview';
import ProjectHealth from './ProjectHealth/ProjectHealth';
import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton';
Expand Down Expand Up @@ -52,6 +53,12 @@ const Project = () => {
path: `${basePath}/environments`,
name: 'environments',
},
{
title: 'Archive',
component: <ProjectFeaturesArchive projectId={id} />,
path: `${basePath}/archive`,
name: 'archive',
},
];

const activeTabIdx = activeTab
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { ProjectFeaturesArchiveList } from 'component/archive/ProjectFeaturesArchiveList';
import { usePageTitle } from 'hooks/usePageTitle';

interface IProjectFeaturesArchiveProps {
projectId: string;
}

export const ProjectFeaturesArchive = ({
projectId,
}: IProjectFeaturesArchiveProps) => {
usePageTitle('Project Archived Features');

return <ProjectFeaturesArchiveList projectId={projectId} />;
};
5 changes: 4 additions & 1 deletion src/hooks/api/getters/useApiGetter/useApiGetter.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import useSWR, { SWRConfiguration, mutate } from 'swr';
import { useCallback } from 'react';

type CacheKey = 'apiAdminFeaturesGet' | 'apiAdminArchiveFeaturesGet';
type CacheKey =
| 'apiAdminFeaturesGet'
| 'apiAdminArchiveFeaturesGet'
| ['apiAdminArchiveFeaturesGet', string?];

interface IUseApiGetterOutput<T> {
data?: T;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { openApiAdmin } from 'utils/openapiClient';
import { FeatureSchema } from 'openapi';
import { useApiGetter } from 'hooks/api/getters/useApiGetter/useApiGetter';

export interface IUseProjectFeaturesArchiveOutput {
archivedFeatures?: FeatureSchema[];
refetchArchived: () => void;
loading: boolean;
error?: Error;
}

export const useProjectFeaturesArchive = (
projectId: string
): IUseProjectFeaturesArchiveOutput => {
const { data, refetch, loading, error } = useApiGetter(
['apiAdminArchiveFeaturesGet', projectId],
() => {
if (projectId) {
return openApiAdmin.apiAdminArchiveFeaturesProjectIdGet({
projectId,
});
}
return openApiAdmin.apiAdminArchiveFeaturesGet();
}
);

return {
archivedFeatures: data?.features,
refetchArchived: refetch,
loading,
error,
};
};
Loading

0 comments on commit 08ed45f

Please sign in to comment.