1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-01-25 00:07:47 +01:00

fix: avoid erasing previous environments data on refetch (#990)

* refactor: avoid duplicate useLoading call

* fix: avoid erasing previous environments data on refetch

* refactor: keep mutataion logic within useEnvironments
This commit is contained in:
olav 2022-05-18 11:26:38 +02:00 committed by GitHub
parent 159c54ed37
commit 98b6214c28
3 changed files with 85 additions and 84 deletions

View File

@ -26,7 +26,8 @@ const EnvironmentList = () => {
enabled: true,
protected: false,
};
const { environments, refetchEnvironments } = useEnvironments();
const { environments, mutateEnvironments, refetchEnvironments } =
useEnvironments();
const { uiConfig } = useUiConfig();
const { refetch: refetchProjectRolePermissions } =
useProjectRolePermissions();
@ -52,7 +53,7 @@ const EnvironmentList = () => {
const item = newEnvList.splice(dragIndex, 1)[0];
newEnvList.splice(hoverIndex, 0, item);
refetchEnvironments({ environments: newEnvList }, false);
mutateEnvironments(newEnvList);
return newEnvList;
};

View File

@ -1,28 +1,23 @@
import { useEffect, useState } from 'react';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { useStyles } from './ProjectEnvironment.styles';
import useLoading from 'hooks/useLoading';
import { PageContent } from 'component/common/PageContent/PageContent';
import { PageHeader } from 'component/common/PageHeader/PageHeader';
import { UPDATE_PROJECT } from 'component/providers/AccessProvider/permissions';
import ApiError from 'component/common/ApiError/ApiError';
import useToast from 'hooks/useToast';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import { useEnvironments } from 'hooks/api/getters/useEnvironments/useEnvironments';
import useProject from 'hooks/api/getters/useProject/useProject';
import { FormControlLabel, FormGroup } from '@mui/material';
import { FormControlLabel, FormGroup, Alert } from '@mui/material';
import useProjectApi from 'hooks/api/actions/useProjectApi/useProjectApi';
import EnvironmentDisableConfirm from './EnvironmentDisableConfirm/EnvironmentDisableConfirm';
import { Link } from 'react-router-dom';
import { Alert } from '@mui/material';
import PermissionSwitch from 'component/common/PermissionSwitch/PermissionSwitch';
import { IProjectEnvironment } from 'interfaces/environments';
import { getEnabledEnvs } from './helpers';
import StringTruncator from 'component/common/StringTruncator/StringTruncator';
import { useThemeStyles } from 'themes/themeStyles';
import { isDescendantOrSelf } from '@testing-library/user-event/dist/types/utils';
interface IProjectEnvironmentListProps {
projectId: string;
@ -45,7 +40,6 @@ const ProjectEnvironmentList = ({
// local state
const [selectedEnv, setSelectedEnv] = useState<IProjectEnvironment>();
const [confirmName, setConfirmName] = useState('');
const ref = useLoading(loading);
const { classes: styles } = useStyles();
const { isOss } = useUiConfig();
@ -179,68 +173,60 @@ const ProjectEnvironmentList = ({
};
return (
<div ref={ref}>
<PageContent
header={
<PageHeader
title={`Configure environments for "${project?.name}" project`}
/>
}
>
<ConditionallyRender
condition={uiConfig.flags.E}
show={
<div className={styles.container}>
<ConditionallyRender
condition={error}
show={renderError()}
/>
<Alert
severity="info"
style={{ marginBottom: '20px' }}
>
<b>Important!</b> In order for your application
to retrieve configured activation strategies for
a specific environment, the application
<br /> must use an environment specific API key.
You can look up the environment-specific API
keys <Link to="/admin/api">here.</Link>
<br />
<br />
Your administrator can configure an
environment-specific API key to be used in the
SDK. If you are an administrator you can{' '}
<Link to="/admin/api">
create a new API key.
</Link>
</Alert>
<ConditionallyRender
condition={environments.length < 1 && !loading}
show={<div>No environments available.</div>}
elseShow={renderEnvironments()}
/>
<EnvironmentDisableConfirm
env={selectedEnv}
open={Boolean(selectedEnv)}
handleDisableEnvironment={
handleDisableEnvironment
}
handleCancelDisableEnvironment={
handleCancelDisableEnvironment
}
confirmName={confirmName}
setConfirmName={setConfirmName}
/>
</div>
}
elseShow={
<Alert security="success">
This feature has not been Unleashed for you yet.
</Alert>
}
<PageContent
header={
<PageHeader
title={`Configure environments for "${project?.name}" project`}
/>
</PageContent>
</div>
}
isLoading={loading}
>
<ConditionallyRender
condition={uiConfig.flags.E}
show={
<div className={styles.container}>
<ConditionallyRender
condition={Boolean(error)}
show={renderError()}
/>
<Alert severity="info" style={{ marginBottom: '20px' }}>
<b>Important!</b> In order for your application to
retrieve configured activation strategies for a
specific environment, the application
<br /> must use an environment specific API key. You
can look up the environment-specific API keys{' '}
<Link to="/admin/api">here.</Link>
<br />
<br />
Your administrator can configure an
environment-specific API key to be used in the SDK.
If you are an administrator you can{' '}
<Link to="/admin/api">create a new API key.</Link>
</Alert>
<ConditionallyRender
condition={environments.length < 1 && !loading}
show={<div>No environments available.</div>}
elseShow={renderEnvironments()}
/>
<EnvironmentDisableConfirm
env={selectedEnv}
open={Boolean(selectedEnv)}
handleDisableEnvironment={handleDisableEnvironment}
handleCancelDisableEnvironment={
handleCancelDisableEnvironment
}
confirmName={confirmName}
setConfirmName={setConfirmName}
/>
</div>
}
elseShow={
<Alert security="success">
This feature has not been Unleashed for you yet.
</Alert>
}
/>
</PageContent>
);
};

View File

@ -1,35 +1,49 @@
import useSWR, { mutate } from 'swr';
import { useCallback, useMemo } from 'react';
import { IEnvironmentResponse } from 'interfaces/environments';
import useSWR from 'swr';
import { useMemo, useCallback } from 'react';
import { IEnvironmentResponse, IEnvironment } from 'interfaces/environments';
import { formatApiPath } from 'utils/formatPath';
import handleErrorResponses from '../httpErrorResponseHandler';
const PATH = formatApiPath(`api/admin/environments`);
interface IUseEnvironmentsOutput {
environments: IEnvironment[];
loading: boolean;
error?: Error;
mutateEnvironments: (environments: IEnvironment[]) => Promise<void>;
refetchEnvironments: () => Promise<void>;
}
export const useEnvironments = () => {
const { data, error } = useSWR<IEnvironmentResponse>(PATH, fetcher);
const refetchEnvironments = useCallback(
(data?: IEnvironmentResponse, revalidate?: boolean) => {
mutate(PATH, data, revalidate).catch(console.warn);
},
[]
export const useEnvironments = (): IUseEnvironmentsOutput => {
const { data, error, mutate } = useSWR<IEnvironmentResponse>(
formatApiPath(`api/admin/environments`),
fetcher
);
const environments = useMemo(() => {
return data?.environments || [];
}, [data]);
const refetchEnvironments = useCallback(async () => {
await mutate();
}, [mutate]);
const mutateEnvironments = useCallback(
async (environments: IEnvironment[]) => {
await mutate({ environments }, false);
},
[mutate]
);
return {
environments,
refetchEnvironments,
mutateEnvironments,
loading: !error && !data,
error,
};
};
const fetcher = (): Promise<IEnvironmentResponse> => {
return fetch(PATH)
const fetcher = (path: string): Promise<IEnvironmentResponse> => {
return fetch(path)
.then(handleErrorResponses('Environments'))
.then(res => res.json());
};