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

feat: remove newApplicationsList feature flag (#4653)

This commit is contained in:
Jaanus Sellin 2023-09-11 13:28:43 +03:00 committed by GitHub
parent a9ac81a089
commit 77fbac01e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 25 additions and 181 deletions

View File

@ -1,99 +0,0 @@
import { useEffect, useMemo, useState } from 'react';
import { CircularProgress, Link } from '@mui/material';
import { Warning } from '@mui/icons-material';
import { AppsLinkList, styles as themeStyles } from 'component/common';
import { PageContent } from 'component/common/PageContent/PageContent';
import { PageHeader } from 'component/common/PageHeader/PageHeader';
import useApplications from 'hooks/api/getters/useApplications/useApplications';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { useSearchParams } from 'react-router-dom';
import { Search } from 'component/common/Search/Search';
import { safeRegExp } from '@server/util/escape-regex';
type PageQueryType = Partial<Record<'search', string>>;
export const OldApplicationList = () => {
const { applications, loading } = useApplications();
const [searchParams, setSearchParams] = useSearchParams();
const [searchValue, setSearchValue] = useState(
searchParams.get('search') || ''
);
useEffect(() => {
const tableState: PageQueryType = {};
if (searchValue) {
tableState.search = searchValue;
}
setSearchParams(tableState, {
replace: true,
});
}, [searchValue, setSearchParams]);
const filteredApplications = useMemo(() => {
const regExp = safeRegExp(searchValue, 'i');
return searchValue
? applications?.filter(a => regExp.test(a.appName))
: applications;
}, [applications, searchValue]);
const renderNoApplications = () => (
<>
<section style={{ textAlign: 'center' }}>
<Warning titleAccess="Warning" /> <br />
<br />
Oh snap, it does not seem like you have connected any
applications. To connect your application to Unleash you will
require a Client SDK.
<br />
<br />
You can read more about how to use Unleash in your application
in the{' '}
<Link href="https://docs.getunleash.io/docs/sdks/">
documentation.
</Link>
</section>
</>
);
if (!filteredApplications) {
return <CircularProgress variant="indeterminate" />;
}
let applicationCount =
filteredApplications.length < applications.length
? `${filteredApplications.length} of ${applications.length}`
: applications.length;
return (
<>
<PageContent
header={
<PageHeader
title={`Applications (${applicationCount})`}
actions={
<Search
initialValue={searchValue}
onChange={setSearchValue}
/>
}
/>
}
>
<div className={themeStyles.fullwidth}>
<ConditionallyRender
condition={filteredApplications.length > 0}
show={<AppsLinkList apps={filteredApplications} />}
elseShow={
<ConditionallyRender
condition={loading}
show={<div>...loading</div>}
elseShow={renderNoApplications()}
/>
}
/>
</div>
</PageContent>
</>
);
};

View File

@ -1,16 +0,0 @@
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import useUiConfig from '../../../hooks/api/getters/useUiConfig/useUiConfig';
import { ApplicationList } from './ApplicationList';
import { OldApplicationList } from './OldApplicationList';
export const TemporaryApplicationListWrapper = () => {
const { uiConfig } = useUiConfig();
return (
<ConditionallyRender
condition={Boolean(uiConfig.flags.newApplicationList)}
show={<ApplicationList />}
elseShow={<OldApplicationList />}
/>
);
};

View File

@ -44,8 +44,8 @@ import { LazyProject } from 'component/project/Project/LazyProject';
import { LoginHistory } from 'component/loginHistory/LoginHistory'; import { LoginHistory } from 'component/loginHistory/LoginHistory';
import { FeatureTypesList } from 'component/featureTypes/FeatureTypesList'; import { FeatureTypesList } from 'component/featureTypes/FeatureTypesList';
import { AddonsList } from 'component/integrations/IntegrationList/AddonsList'; import { AddonsList } from 'component/integrations/IntegrationList/AddonsList';
import { TemporaryApplicationListWrapper } from 'component/application/ApplicationList/TemporaryApplicationListWrapper';
import { ViewIntegration } from 'component/integrations/ViewIntegration/ViewIntegration'; import { ViewIntegration } from 'component/integrations/ViewIntegration/ViewIntegration';
import { ApplicationList } from '../application/ApplicationList/ApplicationList';
export const routes: IRoute[] = [ export const routes: IRoute[] = [
// Splash // Splash
@ -181,7 +181,7 @@ export const routes: IRoute[] = [
{ {
path: '/applications', path: '/applications',
title: 'Applications', title: 'Applications',
component: TemporaryApplicationListWrapper, component: ApplicationList,
type: 'protected', type: 'protected',
menu: { mobile: true, advanced: true }, menu: { mobile: true, advanced: true },
}, },
@ -502,14 +502,13 @@ const computeRoutes = () => {
export const getCondensedRoutes = (routes: IRoute[]): INavigationMenuItem[] => { export const getCondensedRoutes = (routes: IRoute[]): INavigationMenuItem[] => {
return routes.map(route => { return routes.map(route => {
const condensedRoute = { return {
path: route.path, path: route.path,
flag: route.flag, flag: route.flag,
title: route.title, title: route.title,
menu: route.menu, menu: route.menu,
configFlag: route.configFlag, configFlag: route.configFlag,
}; };
return condensedRoute;
}); });
}; };

View File

@ -60,7 +60,6 @@ export type UiFlags = {
customRootRolesKillSwitch?: boolean; customRootRolesKillSwitch?: boolean;
strategyVariant?: boolean; strategyVariant?: boolean;
lastSeenByEnvironment?: boolean; lastSeenByEnvironment?: boolean;
newApplicationList?: boolean;
integrationsRework?: boolean; integrationsRework?: boolean;
multipleRoles?: boolean; multipleRoles?: boolean;
featureNamingPattern?: boolean; featureNamingPattern?: boolean;

View File

@ -94,7 +94,6 @@ exports[`should create default config 1`] = `
}, },
"migrationLock": true, "migrationLock": true,
"multipleRoles": false, "multipleRoles": false,
"newApplicationList": false,
"personalAccessTokensKillSwitch": false, "personalAccessTokensKillSwitch": false,
"proPlanAutoCharge": false, "proPlanAutoCharge": false,
"responseTimeWithAppNameKillSwitch": false, "responseTimeWithAppNameKillSwitch": false,
@ -130,7 +129,6 @@ exports[`should create default config 1`] = `
}, },
"migrationLock": true, "migrationLock": true,
"multipleRoles": false, "multipleRoles": false,
"newApplicationList": false,
"personalAccessTokensKillSwitch": false, "personalAccessTokensKillSwitch": false,
"proPlanAutoCharge": false, "proPlanAutoCharge": false,
"responseTimeWithAppNameKillSwitch": false, "responseTimeWithAppNameKillSwitch": false,

View File

@ -7,7 +7,6 @@ import {
import { Logger, LogProvider } from '../logger'; import { Logger, LogProvider } from '../logger';
import { IApplicationQuery } from '../types/query'; import { IApplicationQuery } from '../types/query';
import { Db } from './db'; import { Db } from './db';
import { IFlagResolver } from '../types';
const COLUMNS = [ const COLUMNS = [
'app_name', 'app_name',
@ -110,18 +109,10 @@ export default class ClientApplicationsStore
{ {
private db: Db; private db: Db;
private flagResolver: IFlagResolver;
private logger: Logger; private logger: Logger;
constructor( constructor(db: Db, eventBus: EventEmitter, getLogger: LogProvider) {
db: Db,
eventBus: EventEmitter,
getLogger: LogProvider,
flagResolver: IFlagResolver,
) {
this.db = db; this.db = db;
this.flagResolver = flagResolver;
this.logger = getLogger('client-applications-store.ts'); this.logger = getLogger('client-applications-store.ts');
} }
@ -193,38 +184,26 @@ export default class ClientApplicationsStore
async getAppsForStrategy( async getAppsForStrategy(
query: IApplicationQuery, query: IApplicationQuery,
): Promise<IClientApplication[]> { ): Promise<IClientApplication[]> {
if (this.flagResolver.isEnabled('newApplicationList')) { const rows = await this.db
const rows = await this.db .select([
.select([ ...COLUMNS.map((column) => `${TABLE}.${column}`),
...COLUMNS.map((column) => `${TABLE}.${column}`), 'project',
'project', 'environment',
'environment', ])
]) .from(TABLE)
.from(TABLE) .leftJoin(
.leftJoin( TABLE_USAGE,
TABLE_USAGE, `${TABLE_USAGE}.app_name`,
`${TABLE_USAGE}.app_name`, `${TABLE}.app_name`,
`${TABLE}.app_name`, );
); const apps = reduceRows(rows);
const apps = reduceRows(rows);
if (query.strategyName) { if (query.strategyName) {
return apps.filter((app) => return apps.filter((app) =>
app.strategies.includes(query.strategyName), app.strategies.includes(query.strategyName),
); );
}
return apps;
} else {
const rows = await this.db.select(COLUMNS).from(TABLE);
const apps = rows.map(mapRow);
if (query.strategyName) {
return apps.filter((app) =>
app.strategies.includes(query.strategyName),
);
}
return apps;
} }
return apps;
} }
async getUnannounced(): Promise<IClientApplication[]> { async getUnannounced(): Promise<IClientApplication[]> {

View File

@ -1,5 +1,4 @@
import { IUnleashConfig } from '../types/option'; import { IUnleashConfig, IUnleashStores } from '../types';
import { IUnleashStores } from '../types/stores';
import EventStore from './event-store'; import EventStore from './event-store';
import FeatureToggleStore from './feature-toggle-store'; import FeatureToggleStore from './feature-toggle-store';
@ -54,7 +53,6 @@ export const createStores = (
db, db,
eventBus, eventBus,
getLogger, getLogger,
config.flagResolver,
), ),
clientInstanceStore: new ClientInstanceStore(db, eventBus, getLogger), clientInstanceStore: new ClientInstanceStore(db, eventBus, getLogger),
clientMetricsStoreV2: new ClientMetricsStoreV2( clientMetricsStoreV2: new ClientMetricsStoreV2(

View File

@ -24,7 +24,6 @@ export type IFlagKey =
| 'filterInvalidClientMetrics' | 'filterInvalidClientMetrics'
| 'lastSeenByEnvironment' | 'lastSeenByEnvironment'
| 'customRootRolesKillSwitch' | 'customRootRolesKillSwitch'
| 'newApplicationList'
| 'integrationsRework' | 'integrationsRework'
| 'multipleRoles' | 'multipleRoles'
| 'featureNamingPattern' | 'featureNamingPattern'
@ -120,10 +119,6 @@ const flags: IFlags = {
process.env.UNLEASH_EXPERIMENTAL_MULTIPLE_ROLES, process.env.UNLEASH_EXPERIMENTAL_MULTIPLE_ROLES,
false, false,
), ),
newApplicationList: parseEnvVarBoolean(
process.env.UNLEASH_EXPERIMENTAL_NEW_APPLICATION_LIST,
false,
),
featureNamingPattern: parseEnvVarBoolean( featureNamingPattern: parseEnvVarBoolean(
process.env.UNLEASH_EXPERIMENTAL_FEATURE_NAMING_PATTERN, process.env.UNLEASH_EXPERIMENTAL_FEATURE_NAMING_PATTERN,
false, false,

View File

@ -40,7 +40,6 @@ process.nextTick(async () => {
slackAppAddon: true, slackAppAddon: true,
lastSeenByEnvironment: true, lastSeenByEnvironment: true,
integrationsRework: true, integrationsRework: true,
newApplicationList: true,
featureNamingPattern: true, featureNamingPattern: true,
doraMetrics: true, doraMetrics: true,
}, },

View File

@ -9,16 +9,8 @@ let app: IUnleashTest;
let db: ITestDb; let db: ITestDb;
beforeAll(async () => { beforeAll(async () => {
db = await dbInit('metrics_serial', getLogger, { db = await dbInit('metrics_serial', getLogger, {});
experimental: { flags: { newApplicationList: true } }, app = await setupAppWithCustomConfig(db.stores, {});
});
app = await setupAppWithCustomConfig(db.stores, {
experimental: {
flags: {
newApplicationList: true,
},
},
});
}); });
beforeEach(async () => { beforeEach(async () => {