mirror of
https://github.com/Unleash/unleash.git
synced 2025-10-18 11:14:57 +02:00
fix: encode application name (#10671)
This commit is contained in:
parent
bcbe3eb0ba
commit
7d70f8fc55
@ -78,7 +78,7 @@ export const Application = () => {
|
||||
const { setToastData, setToastApiError } = useToast();
|
||||
const { pathname } = useLocation();
|
||||
|
||||
const basePath = `/applications/${name}`;
|
||||
const basePath = `/applications/${encodeURIComponent(name)}`;
|
||||
|
||||
const [showDialog, setShowDialog] = useState(false);
|
||||
|
||||
|
@ -109,7 +109,7 @@ export const PaginatedApplicationList = () => {
|
||||
}: any) => (
|
||||
<LinkCell
|
||||
title={appName}
|
||||
to={`/applications/${appName}`}
|
||||
to={`/applications/${encodeURIComponent(appName)}`}
|
||||
subtitle={description}
|
||||
/>
|
||||
),
|
||||
|
@ -1,111 +0,0 @@
|
||||
import { type ChangeEvent, useMemo, useState } from 'react';
|
||||
import { Grid, TextField, styled } from '@mui/material';
|
||||
import { useThemeStyles } from 'themes/themeStyles';
|
||||
import icons from 'component/application/iconNames';
|
||||
import GeneralSelect from 'component/common/GeneralSelect/GeneralSelect';
|
||||
import useApplicationsApi from 'hooks/api/actions/useApplicationsApi/useApplicationsApi';
|
||||
import useToast from 'hooks/useToast';
|
||||
import type { IApplication } from 'interfaces/application';
|
||||
import useApplication from 'hooks/api/getters/useApplication/useApplication';
|
||||
import { formatUnknownError } from 'utils/formatUnknownError';
|
||||
import { HelpIcon } from 'component/common/HelpIcon/HelpIcon';
|
||||
|
||||
interface IApplicationUpdateProps {
|
||||
application: IApplication;
|
||||
}
|
||||
|
||||
const StyledSelectContainer = styled('div')(({ theme }) => ({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: theme.spacing(1),
|
||||
}));
|
||||
|
||||
export const ApplicationUpdate = ({ application }: IApplicationUpdateProps) => {
|
||||
const { storeApplicationMetaData } = useApplicationsApi();
|
||||
const { appName, icon, url, description } = application;
|
||||
const { refetchApplication } = useApplication(appName);
|
||||
const [localUrl, setLocalUrl] = useState(url || '');
|
||||
const [localDescription, setLocalDescription] = useState(description || '');
|
||||
const { setToastData, setToastApiError } = useToast();
|
||||
const { classes: themeStyles } = useThemeStyles();
|
||||
|
||||
const onChange = async (
|
||||
field: string,
|
||||
value: string,
|
||||
event?: ChangeEvent,
|
||||
) => {
|
||||
event?.preventDefault();
|
||||
try {
|
||||
await storeApplicationMetaData(appName, field, value);
|
||||
refetchApplication();
|
||||
setToastData({
|
||||
type: 'success',
|
||||
text: 'Updated Successfully',
|
||||
});
|
||||
} catch (error: unknown) {
|
||||
setToastApiError(formatUnknownError(error));
|
||||
}
|
||||
};
|
||||
|
||||
const options = useMemo(() => icons.map((v) => ({ key: v, label: v })), []);
|
||||
|
||||
return (
|
||||
<Grid container style={{ marginTop: '1rem' }}>
|
||||
<Grid item sm={12} xs={12} className={themeStyles.contentSpacingY}>
|
||||
<Grid item>
|
||||
<StyledSelectContainer>
|
||||
<GeneralSelect
|
||||
name='iconSelect'
|
||||
id='selectIcon'
|
||||
label='Icon'
|
||||
options={options}
|
||||
value={icon || 'apps'}
|
||||
onChange={(key) => onChange('icon', key)}
|
||||
/>
|
||||
<HelpIcon
|
||||
htmlTooltip
|
||||
tooltip={
|
||||
<>
|
||||
<p>Unleash is using Material Icons</p>
|
||||
<br />
|
||||
<a
|
||||
href='https://mui.com/material-ui/material-icons/'
|
||||
target='_blank'
|
||||
rel='noreferrer'
|
||||
>
|
||||
Preview icons on MUI.com
|
||||
</a>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</StyledSelectContainer>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<TextField
|
||||
value={localUrl}
|
||||
onChange={(e) => setLocalUrl(e.target.value)}
|
||||
label='Application URL'
|
||||
placeholder='https://example.com'
|
||||
type='url'
|
||||
variant='outlined'
|
||||
size='small'
|
||||
onBlur={(e) => onChange('url', localUrl, e)}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<TextField
|
||||
value={localDescription}
|
||||
label='Description'
|
||||
variant='outlined'
|
||||
size='small'
|
||||
rows={2}
|
||||
onChange={(e) => setLocalDescription(e.target.value)}
|
||||
onBlur={(e) =>
|
||||
onChange('description', localDescription, e)
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
@ -99,7 +99,9 @@ export const ProjectApplications = () => {
|
||||
title={row.original.name}
|
||||
onClick={() => {
|
||||
trackProjectApplicationClick();
|
||||
navigate(`/applications/${row.original.name}`);
|
||||
navigate(
|
||||
`/applications/${encodeURIComponent(row.original.name)}`,
|
||||
);
|
||||
}}
|
||||
/>
|
||||
),
|
||||
|
@ -7,22 +7,6 @@ const useApplicationsApi = () => {
|
||||
|
||||
const URI = 'api/admin/metrics/applications';
|
||||
|
||||
const storeApplicationMetaData = async (
|
||||
appName: string,
|
||||
key: string,
|
||||
value: string,
|
||||
) => {
|
||||
const data: { [key: string]: any } = {};
|
||||
data[key] = value;
|
||||
const path = `${URI}/${appName}`;
|
||||
const req = createRequest(path, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
|
||||
return makeRequest(req.caller, req.id);
|
||||
};
|
||||
|
||||
const deleteApplication = async (appName: string) => {
|
||||
const path = `${URI}/${encodeURIComponent(appName)}`;
|
||||
const req = createRequest(path, { method: 'DELETE' });
|
||||
@ -31,7 +15,6 @@ const useApplicationsApi = () => {
|
||||
};
|
||||
|
||||
return {
|
||||
storeApplicationMetaData,
|
||||
deleteApplication,
|
||||
errors,
|
||||
loading,
|
||||
|
@ -16,7 +16,8 @@ const useApplication = (
|
||||
name: string,
|
||||
options: SWRConfiguration = {},
|
||||
): IUseApplicationOutput => {
|
||||
const path = formatApiPath(`api/admin/metrics/applications/${name}`);
|
||||
const encodedName = encodeURIComponent(name);
|
||||
const path = formatApiPath(`api/admin/metrics/applications/${encodedName}`);
|
||||
|
||||
const fetcher = async () => {
|
||||
return fetch(path, {
|
||||
@ -26,7 +27,7 @@ const useApplication = (
|
||||
.then((res) => res.json());
|
||||
};
|
||||
|
||||
const APPLICATION_CACHE_KEY = `api/admin/metrics/applications/${name}`;
|
||||
const APPLICATION_CACHE_KEY = `api/admin/metrics/applications/${encodedName}`;
|
||||
|
||||
const { data, error } = useSWR(APPLICATION_CACHE_KEY, fetcher, {
|
||||
...options,
|
||||
@ -44,7 +45,7 @@ const useApplication = (
|
||||
|
||||
return {
|
||||
application: data || {
|
||||
appName: name,
|
||||
appName: encodedName,
|
||||
color: '',
|
||||
createdAt: '2022-02-02T21:04:00.268Z',
|
||||
description: '',
|
||||
|
@ -15,8 +15,9 @@ export const useApplicationOverview = (
|
||||
application: string,
|
||||
options: SWRConfiguration = {},
|
||||
) => {
|
||||
const encodedApplication = encodeURIComponent(application);
|
||||
const path = formatApiPath(
|
||||
`api/admin/metrics/applications/${application}/overview`,
|
||||
`api/admin/metrics/applications/${encodedApplication}/overview`,
|
||||
);
|
||||
const { data, error } = useSWR<ApplicationOverviewSchema>(
|
||||
path,
|
||||
|
@ -17,8 +17,9 @@ export const useConnectedInstances = (
|
||||
environment?: string,
|
||||
options: SWRConfiguration = {},
|
||||
) => {
|
||||
const encodedApplication = encodeURIComponent(application);
|
||||
const path = formatApiPath(
|
||||
`api/admin/metrics/instances/${application}/environment/${environment}`,
|
||||
`api/admin/metrics/instances/${encodedApplication}/environment/${environment}`,
|
||||
);
|
||||
const { data, error } = useConditionalSWR<ConnectedInstancesSchema>(
|
||||
Boolean(environment),
|
||||
|
Loading…
Reference in New Issue
Block a user