1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-04-24 01:18:01 +02:00

chore: [Gitar] Cleaning up stale feature flag: sdkReporting with value true (#6717)

Co-authored-by: Gitar Bot <noreply@gitar.co>
Co-authored-by: sjaanus <sellinjaanus@gmail.com>
This commit is contained in:
gitar-bot[bot] 2024-03-28 09:19:11 +02:00 committed by GitHub
parent c1e37bf7d3
commit ca6946df86
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 0 additions and 446 deletions

View File

@ -28,8 +28,6 @@ import useToast from 'hooks/useToast';
import { formatDateYMD } from 'utils/formatDate';
import { formatUnknownError } from 'utils/formatUnknownError';
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
import { useUiFlag } from 'hooks/useUiFlag';
import { ApplicationEdit } from './ApplicationEdit/ApplicationEdit';
import ApplicationOverview from './ApplicationOverview';
import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton';
@ -70,7 +68,6 @@ const StyledTab = styled(Tab)(({ theme }) => ({
}));
export const Application = () => {
const useOldApplicationScreen = !useUiFlag('sdkReporting');
const navigate = useNavigate();
const name = useRequiredPathParam('name');
const { application, loading } = useApplication(name);
@ -89,10 +86,6 @@ export const Application = () => {
setShowDialog(!showDialog);
};
if (useOldApplicationScreen) {
return <ApplicationEdit />;
}
const formatDate = (v: string) => formatDateYMD(v, locationSettings.locale);
const onDeleteApplication = async (evt: React.SyntheticEvent) => {

View File

@ -1,197 +0,0 @@
/* eslint react/no-multi-comp:off */
import type React from 'react';
import { useContext, useState } from 'react';
import {
Box,
Avatar,
Icon,
IconButton,
LinearProgress,
Link,
Tab,
Tabs,
Typography,
} from '@mui/material';
import LinkIcon from '@mui/icons-material/Link';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { UPDATE_APPLICATION } from 'component/providers/AccessProvider/permissions';
import { ApplicationUpdate } from '../ApplicationUpdate/ApplicationUpdate';
import { Dialogue } from 'component/common/Dialogue/Dialogue';
import { PageContent } from 'component/common/PageContent/PageContent';
import { PageHeader } from 'component/common/PageHeader/PageHeader';
import AccessContext from 'contexts/AccessContext';
import useApplicationsApi from 'hooks/api/actions/useApplicationsApi/useApplicationsApi';
import useApplication from 'hooks/api/getters/useApplication/useApplication';
import { useNavigate } from 'react-router-dom';
import { useLocationSettings } from 'hooks/useLocationSettings';
import useToast from 'hooks/useToast';
import PermissionButton from 'component/common/PermissionButton/PermissionButton';
import { formatDateYMD } from 'utils/formatDate';
import { formatUnknownError } from 'utils/formatUnknownError';
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
import { TabPanel } from 'component/common/TabNav/TabPanel/TabPanel';
import { ApplicationView } from '../ApplicationView/ApplicationView';
export const ApplicationEdit = () => {
const navigate = useNavigate();
const name = useRequiredPathParam('name');
const { application, loading } = useApplication(name);
const { appName, url, description, icon = 'apps', createdAt } = application;
const { hasAccess } = useContext(AccessContext);
const { deleteApplication } = useApplicationsApi();
const { locationSettings } = useLocationSettings();
const { setToastData, setToastApiError } = useToast();
const [activeTab, setActiveTab] = useState(0);
const [showDialog, setShowDialog] = useState(false);
const toggleModal = () => {
setShowDialog(!showDialog);
};
const formatDate = (v: string) => formatDateYMD(v, locationSettings.locale);
const onDeleteApplication = async (evt: React.SyntheticEvent) => {
evt.preventDefault();
try {
await deleteApplication(appName);
setToastData({
title: 'Deleted Successfully',
text: 'Application deleted successfully',
type: 'success',
});
navigate('/applications');
} catch (error: unknown) {
setToastApiError(formatUnknownError(error));
}
};
const renderModal = () => (
<Dialogue
open={showDialog}
onClose={toggleModal}
onClick={onDeleteApplication}
title='Are you sure you want to delete this application?'
/>
);
const tabData = [
{
label: 'Application overview',
component: <ApplicationView />,
},
{
label: 'Edit application',
component: <ApplicationUpdate application={application} />,
},
];
if (loading) {
return (
<div>
<p>Loading...</p>
<LinearProgress />
</div>
);
} else if (!application) {
return <p>Application ({appName}) not found</p>;
}
return (
<>
<PageContent>
<PageHeader
titleElement={
<span
style={{
display: 'flex',
alignItems: 'center',
}}
>
<Avatar style={{ marginRight: '8px' }}>
<Icon>{icon || 'apps'}</Icon>
</Avatar>
{appName}
</span>
}
title={appName}
actions={
<>
<ConditionallyRender
condition={Boolean(url)}
show={
<IconButton
component={Link}
href={url}
size='large'
>
<LinkIcon titleAccess={url} />
</IconButton>
}
/>
<PermissionButton
tooltipProps={{ title: 'Delete application' }}
onClick={toggleModal}
permission={UPDATE_APPLICATION}
>
Delete
</PermissionButton>
</>
}
/>
<Box sx={(theme) => ({ marginTop: theme.spacing(1) })}>
<Typography variant='body1'>{description || ''}</Typography>
<Typography variant='body2'>
Created: <strong>{formatDate(createdAt)}</strong>
</Typography>
</Box>
</PageContent>
<br />
<PageContent
withTabs
header={
<Tabs
value={activeTab}
onChange={(_, tabId) => {
setActiveTab(tabId);
}}
indicatorColor='primary'
textColor='primary'
>
{tabData.map((tab, index) => (
<Tab
key={`${tab.label}_${index}`}
label={tab.label}
id={`tab-${index}`}
aria-controls={`tabpanel-${index}`}
sx={{
minWidth: {
lg: 160,
},
}}
/>
))}
</Tabs>
}
>
<ConditionallyRender
condition={hasAccess(UPDATE_APPLICATION)}
show={
<div>
{renderModal()}
{tabData.map((tab, index) => (
<TabPanel
key={index}
value={activeTab}
index={index}
>
{tab.component}
</TabPanel>
))}
</div>
}
/>
</PageContent>
</>
);
};

View File

@ -1,215 +0,0 @@
import { useContext } from 'react';
import { Link } from 'react-router-dom';
import {
Grid,
List,
ListItem,
ListItemAvatar,
ListItemText,
Typography,
Divider,
} from '@mui/material';
import Extension from '@mui/icons-material/Extension';
import FlagRounded from '@mui/icons-material/FlagRounded';
import Report from '@mui/icons-material/Report';
import Timeline from '@mui/icons-material/Timeline';
import {
CREATE_FEATURE,
CREATE_STRATEGY,
} from 'component/providers/AccessProvider/permissions';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { getTogglePath } from 'utils/routePathHelpers';
import useApplication from 'hooks/api/getters/useApplication/useApplication';
import AccessContext from 'contexts/AccessContext';
import { formatDateYMDHMS } from 'utils/formatDate';
import { useLocationSettings } from 'hooks/useLocationSettings';
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
export const ApplicationView = () => {
const { hasAccess } = useContext(AccessContext);
const name = useRequiredPathParam('name');
const { application } = useApplication(name);
const { locationSettings } = useLocationSettings();
const { instances, strategies, seenToggles } = application;
const notFoundListItem = ({
createUrl,
name,
permission,
}: {
createUrl: string;
name: string;
permission: string;
}) => (
<ConditionallyRender
key={`not_found_conditional_${name}`}
condition={hasAccess(permission)}
show={
<ListItem key={`not_found_${name}`}>
<ListItemAvatar>
<Report style={{ color: 'red' }} />
</ListItemAvatar>
<ListItemText
primary={<Link to={`${createUrl}`}>{name}</Link>}
secondary={'Missing, want to create?'}
/>
</ListItem>
}
elseShow={
<ListItem key={`not_found_${name}`}>
<ListItemAvatar>
<Report />
</ListItemAvatar>
<ListItemText
primary={name}
secondary={`Could not find feature toggle with name ${name}`}
/>
</ListItem>
}
/>
);
const foundListItem = ({
viewUrl,
name,
description,
Icon,
i,
}: {
viewUrl: string;
name: string;
description: string;
Icon: React.ElementType;
i: number;
}) => (
<ListItem key={`found_${name}-${i}`}>
<ListItemAvatar>
<Icon />
</ListItemAvatar>
<ListItemText
primary={
<Link
to={`${viewUrl}/${name}`}
style={{ wordBreak: 'break-all' }}
>
{name}
</Link>
}
secondary={description}
/>
</ListItem>
);
return (
<Grid container style={{ margin: 0 }}>
<Grid item xl={6} md={6} xs={12}>
<Typography variant='subtitle1' style={{ padding: '1rem 0' }}>
Toggles
</Typography>
<Divider />
<List>
{seenToggles.map(
({ name, description, notFound, project }, i) => (
<ConditionallyRender
key={`toggle_conditional_${name}`}
condition={notFound}
show={notFoundListItem({
createUrl: `/projects/default/create-toggle?name=${name}`,
name,
permission: CREATE_FEATURE,
})}
elseShow={foundListItem({
viewUrl: getTogglePath(project, name),
name,
description,
Icon: FlagRounded,
i,
})}
/>
),
)}
</List>
</Grid>
<Grid item xl={6} md={6} xs={12}>
<Typography variant='subtitle1' style={{ padding: '1rem 0' }}>
Implemented strategies
</Typography>
<Divider />
<List>
{strategies.map(
({ name, description, notFound }, i: number) => (
<ConditionallyRender
key={`strategies_conditional_${name}`}
condition={notFound}
show={notFoundListItem({
createUrl: '/strategies/create',
name,
permission: CREATE_STRATEGY,
})}
elseShow={foundListItem({
viewUrl: '/strategies',
name,
Icon: Extension,
description,
i,
})}
/>
),
)}
</List>
</Grid>
<Grid item xl={12} md={12}>
<Typography variant='subtitle1' style={{ padding: '1rem 0' }}>
{instances.length} Instances registered
</Typography>
<Divider />
<List>
{instances.map(
({
instanceId,
clientIp,
lastSeen,
sdkVersion,
}: {
instanceId: string;
clientIp: string;
lastSeen: string;
sdkVersion: string;
}) => (
<ListItem key={`${instanceId}`}>
<ListItemAvatar>
<Timeline />
</ListItemAvatar>
<ListItemText
primary={
<ConditionallyRender
key={`${instanceId}_conditional`}
condition={Boolean(sdkVersion)}
show={
<span>
{instanceId} {sdkVersion}
</span>
}
elseShow={<span>{instanceId}</span>}
/>
}
secondary={
<span>
{clientIp} last seen at{' '}
<small>
{formatDateYMDHMS(
lastSeen,
locationSettings.locale,
)}
</small>
</span>
}
/>
</ListItem>
),
)}
</List>
</Grid>
</Grid>
);
};

View File

@ -133,7 +133,6 @@ export const Project = () => {
title: 'Applications',
path: `${basePath}/applications`,
name: 'applications',
flag: 'sdkReporting',
},
{
title: 'Event log',

View File

@ -76,7 +76,6 @@ export type UiFlags = {
showInactiveUsers?: boolean;
featureSearchFeedbackPosting?: boolean;
userAccessUIEnabled?: boolean;
sdkReporting?: boolean;
outdatedSdksBanner?: boolean;
projectOverviewRefactor?: string;
collectTrafficDataUsage?: boolean;

View File

@ -138,7 +138,6 @@ exports[`should create default config 1`] = `
"responseTimeWithAppNameKillSwitch": false,
"returnGlobalFrontendApiCache": false,
"scimApi": false,
"sdkReporting": false,
"showInactiveUsers": false,
"signals": false,
"strictSchemaValidation": false,

View File

@ -38,7 +38,6 @@ beforeAll(async () => {
experimental: {
flags: {
strictSchemaValidation: true,
sdkReporting: true,
},
},
},

View File

@ -37,7 +37,6 @@ import {
projectApplicationsSchema,
type ProjectApplicationsSchema,
} from '../../openapi/spec/project-applications-schema';
import { NotFoundError } from '../../error';
import { projectApplicationsQueryParameters } from '../../openapi/spec/project-applications-query-parameters';
import { normalizeQueryParams } from '../feature-search/search-utils';
import ProjectInsightsController from '../project-insights/project-insights-controller';
@ -267,10 +266,6 @@ export default class ProjectController extends Controller {
req: IAuthRequest,
res: Response<ProjectApplicationsSchema>,
): Promise<void> {
if (!this.flagResolver.isEnabled('sdkReporting')) {
throw new NotFoundError();
}
const { projectId } = req.params;
const {

View File

@ -24,7 +24,6 @@ beforeAll(async () => {
experimental: {
flags: {
strictSchemaValidation: true,
sdkReporting: true,
},
},
},

View File

@ -17,7 +17,6 @@ import type { CreateApplicationSchema } from '../../openapi/spec/create-applicat
import type { IAuthRequest } from '../unleash-types';
import { extractUserIdFromUser } from '../../util';
import { type IFlagResolver, serializeDates } from '../../types';
import { NotFoundError } from '../../error';
import {
type ApplicationOverviewSchema,
applicationOverviewSchema,
@ -285,9 +284,6 @@ class MetricsController extends Controller {
req: Request<{ appName: string }>,
res: Response<ApplicationOverviewSchema>,
): Promise<void> {
if (!this.flagResolver.isEnabled('sdkReporting')) {
throw new NotFoundError();
}
const { appName } = req.params;
const overview =
await this.clientInstanceService.getApplicationOverview(appName);
@ -301,9 +297,6 @@ class MetricsController extends Controller {
}
async getOutdatedSdks(req: Request, res: Response<OutdatedSdksSchema>) {
if (!this.flagResolver.isEnabled('sdkReporting')) {
throw new NotFoundError();
}
const outdatedSdks = await this.clientInstanceService.getOutdatedSdks();
this.openApiService.respondWithValidation(
@ -318,9 +311,6 @@ class MetricsController extends Controller {
req: Request<{ appName: string; environment: string }>,
res: Response<ApplicationEnvironmentInstancesSchema>,
): Promise<void> {
if (!this.flagResolver.isEnabled('sdkReporting')) {
throw new NotFoundError();
}
const { appName, environment } = req.params;
const instances =
await this.clientInstanceService.getApplicationEnvironmentInstances(

View File

@ -49,7 +49,6 @@ export type IFlagKey =
| 'userAccessUIEnabled'
| 'disableUpdateMaxRevisionId'
| 'disablePublishUnannouncedEvents'
| 'sdkReporting'
| 'outdatedSdksBanner'
| 'responseTimeMetricsFix'
| 'scimApi'
@ -196,10 +195,6 @@ const flags: IFlags = {
process.env.UNLEASH_EXPERIMENTAL_EXECUTIVE_DASHBOARD_UI,
false,
),
sdkReporting: parseEnvVarBoolean(
process.env.UNLEASH_EXPERIMENTAL_SDK_REPORTING,
false,
),
outdatedSdksBanner: parseEnvVarBoolean(
process.env.UNLEASH_EXPERIMENTAL_OUTDATED_SDKS_BANNER,
false,

View File

@ -49,7 +49,6 @@ process.nextTick(async () => {
executiveDashboard: true,
executiveDashboardUI: true,
userAccessUIEnabled: true,
sdkReporting: true,
outdatedSdksBanner: true,
globalFrontendApiCache: true,
returnGlobalFrontendApiCache: false,

View File

@ -56,7 +56,6 @@ beforeAll(async () => {
experimental: {
flags: {
strictSchemaValidation: true,
sdkReporting: true,
},
},
},