Skip to content

Commit

Permalink
feat: connect project overview table to search api (#5237)
Browse files Browse the repository at this point in the history
  • Loading branch information
kwasniew authored Nov 1, 2023
1 parent 598d022 commit d074254
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ interface IProjectFeatureTogglesProps {
features: IProject['features'];
environments: IProject['environments'];
loading: boolean;
onChange: () => void;
}

const staticColumns = ['Select', 'Actions', 'name', 'favorite'];
Expand All @@ -84,6 +85,7 @@ export const ProjectFeatureToggles = ({
features,
loading,
environments: newEnvironments = [],
onChange,
}: IProjectFeatureTogglesProps) => {
const { classes: styles } = useStyles();
const theme = useTheme();
Expand Down Expand Up @@ -118,7 +120,6 @@ export const ProjectFeatureToggles = ({
? [{ environment: 'a' }, { environment: 'b' }, { environment: 'c' }]
: newEnvironments,
);
const { refetch } = useProject(projectId);
const { isFavoritesPinned, sortTypes, onChangeIsFavoritePinned } =
usePinnedFavorites(
searchParams.has('favorites')
Expand All @@ -140,9 +141,9 @@ export const ProjectFeatureToggles = ({
} else {
await favorite(projectId, feature.name);
}
refetch();
onChange();
},
[projectId, refetch],
[projectId, onChange],
);

const showTagsColumn = useMemo(
Expand Down Expand Up @@ -263,7 +264,7 @@ export const ProjectFeatureToggles = ({
projectId,
name,
isChangeRequestEnabled,
refetch,
onChange,
onFeatureToggle,
);

Expand Down Expand Up @@ -617,16 +618,14 @@ export const ProjectFeatureToggles = ({
isOpen={Boolean(featureStaleDialogState.featureId)}
onClose={() => {
setFeatureStaleDialogState({});
refetch();
onChange();
}}
featureId={featureStaleDialogState.featureId || ''}
projectId={projectId}
/>
<FeatureArchiveDialog
isOpen={Boolean(featureArchiveState)}
onConfirm={() => {
refetch();
}}
onConfirm={onChange}
onClose={() => {
setFeatureArchiveState(undefined);
}}
Expand Down
49 changes: 47 additions & 2 deletions frontend/src/component/project/Project/ProjectOverview.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect } from 'react';
import { useEffect, useState } from 'react';
import useProject, {
useProjectNameOrId,
} from 'hooks/api/getters/useProject/useProject';
Expand All @@ -12,6 +12,7 @@ import { useLastViewedProject } from 'hooks/useLastViewedProject';
import { ProjectStats } from './ProjectStats/ProjectStats';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { useUiFlag } from 'hooks/useUiFlag';
import { useFeatureSearch } from '../../../hooks/api/getters/useFeatureSearch/useFeatureSearch';

const refreshInterval = 15 * 1000;

Expand All @@ -34,22 +35,65 @@ const StyledContentContainer = styled(Box)(() => ({
minWidth: 0,
}));

const InfiniteProjectOverview = () => {
const projectId = useRequiredPathParam('projectId');
const { project, loading: projectLoading } = useProject(projectId, {
refreshInterval,
});
const [nextCursor, setNextCursor] = useState('');
const {
features: searchFeatures,
refetch,
loading,
} = useFeatureSearch(nextCursor, projectId, { refreshInterval });
const { members, features, health, description, environments, stats } =
project;

return (
<StyledContainer>
<ProjectInfo
id={projectId}
description={description}
memberCount={members}
health={health}
features={features}
stats={stats}
/>
<StyledContentContainer>
<ProjectStats stats={project.stats} />
<StyledProjectToggles>
<ProjectFeatureToggles
key={loading ? 'loading' : 'ready'}
features={searchFeatures.features}
environments={environments}
loading={loading}
onChange={refetch}
/>
</StyledProjectToggles>
</StyledContentContainer>
</StyledContainer>
);
};

const ProjectOverview = () => {
const projectId = useRequiredPathParam('projectId');
const projectName = useProjectNameOrId(projectId);
const { project, loading } = useProject(projectId, {
const { project, loading, refetch } = useProject(projectId, {
refreshInterval,
});
const { members, features, health, description, environments, stats } =
project;
usePageTitle(`Project overview – ${projectName}`);
const { setLastViewed } = useLastViewedProject();
const featureSwitchRefactor = useUiFlag('featureSwitchRefactor');
const featureSearchFrontend = useUiFlag('featureSearchFrontend');

useEffect(() => {
setLastViewed(projectId);
}, [projectId, setLastViewed]);

if (featureSearchFrontend) return <InfiniteProjectOverview />;

return (
<StyledContainer>
<ProjectInfo
Expand All @@ -71,6 +115,7 @@ const ProjectOverview = () => {
features={features}
environments={environments}
loading={loading}
onChange={refetch}
/>
)}
elseShow={() => (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,18 @@ interface IUseFeatureSearchOutput {
refetch: () => void;
}

const fallbackFeatures: { features: IFeatureToggleListItem[] } = {
features: [],
};
const fallbackFeatures: { features: IFeatureToggleListItem[]; total: number } =
{
features: [],
total: 0,
};

export const useFeatureSearch = (
cursor: string,
projectId = '',
options: SWRConfiguration = {},
): IUseFeatureSearchOutput => {
const { KEY, fetcher } = getFeatureSearchFetcher();
const { KEY, fetcher } = getFeatureSearchFetcher(projectId, cursor);
const { data, error, mutate } = useSWR<IFeatureSearchResponse>(
KEY,
fetcher,
Expand All @@ -39,18 +43,18 @@ export const useFeatureSearch = (
};
};

const getFeatureSearchFetcher = () => {
const getFeatureSearchFetcher = (projectId: string, cursor: string) => {
const KEY = `api/admin/search/features?projectId=${projectId}&cursor=${cursor}`;

const fetcher = () => {
const path = formatApiPath(`api/admin/search/features`);
const path = formatApiPath(KEY);
return fetch(path, {
method: 'GET',
})
.then(handleErrorResponses('Feature search'))
.then((res) => res.json());
};

const KEY = `api/admin/search/features`;

return {
fetcher,
KEY,
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/interfaces/uiConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ export type UiFlags = {
playgroundImprovements?: boolean;
featureSwitchRefactor?: boolean;
scheduledConfigurationChanges?: boolean;
featureSearchAPI?: boolean;
featureSearchFrontend?: boolean;
};

export interface IVersionInfo {
Expand Down
1 change: 1 addition & 0 deletions src/lib/__snapshots__/create-config.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ exports[`should create default config 1`] = `
"embedProxyFrontend": true,
"featureNamingPattern": false,
"featureSearchAPI": false,
"featureSearchFrontend": false,
"featureSwitchRefactor": false,
"featuresExportImport": true,
"filterInvalidClientMetrics": false,
Expand Down
5 changes: 5 additions & 0 deletions src/lib/types/experimental.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export type IFlagKey =
| 'playgroundImprovements'
| 'featureSwitchRefactor'
| 'featureSearchAPI'
| 'featureSearchFrontend'
| 'scheduledConfigurationChanges';

export type IFlags = Partial<{ [key in IFlagKey]: boolean | Variant }>;
Expand Down Expand Up @@ -168,6 +169,10 @@ const flags: IFlags = {
process.env.UNLEASH_EXPERIMENTAL_FEATURE_SEARCH_API,
false,
),
featureSearchFrontend: parseEnvVarBoolean(
process.env.UNLEASH_EXPERIMENTAL_FEATURE_SEARCH_FRONTEND,
false,
),
scheduledConfigurationChanges: parseEnvVarBoolean(
process.env.UNLEASH_EXPERIMENTAL_SCHEDULED_CONFIGURATION_CHANGES,
false,
Expand Down
1 change: 1 addition & 0 deletions src/server-dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ process.nextTick(async () => {
playgroundImprovements: true,
featureSwitchRefactor: true,
featureSearchAPI: true,
featureSearchFrontend: false,
},
},
authentication: {
Expand Down

0 comments on commit d074254

Please sign in to comment.