mirror of
https://github.com/Unleash/unleash.git
synced 2025-03-27 00:19:39 +01:00
feat: show outdated sdks banner (#6541)
This commit is contained in:
parent
d5a084256e
commit
c6fd558da4
@ -0,0 +1,36 @@
|
|||||||
|
import { screen } from '@testing-library/react';
|
||||||
|
import { render } from 'utils/testRenderer';
|
||||||
|
import { testServerRoute, testServerSetup } from 'utils/testServer';
|
||||||
|
import { OutdatedSdksSchema } from 'openapi';
|
||||||
|
import { OutdatedSdksBanner } from './OutdatedSdksBanner';
|
||||||
|
|
||||||
|
const server = testServerSetup();
|
||||||
|
|
||||||
|
const setupApi = (outdatedSdks: OutdatedSdksSchema) => {
|
||||||
|
testServerRoute(server, '/api/admin/metrics/sdks/outdated', outdatedSdks);
|
||||||
|
testServerRoute(server, '/api/admin/ui-config', {
|
||||||
|
flags: {
|
||||||
|
outdatedSdksBanner: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
test('Show outdated SDKs and apps using them', async () => {
|
||||||
|
setupApi({
|
||||||
|
sdks: [
|
||||||
|
{
|
||||||
|
sdkVersion: 'unleash-node-client:3.2.1',
|
||||||
|
applications: ['application1', 'application2'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
render(<OutdatedSdksBanner />);
|
||||||
|
|
||||||
|
const link = await screen.findByText('Please update those versions');
|
||||||
|
|
||||||
|
link.click();
|
||||||
|
|
||||||
|
await screen.findByText('unleash-node-client:3.2.1');
|
||||||
|
await screen.findByText('application1');
|
||||||
|
await screen.findByText('application2');
|
||||||
|
});
|
@ -1,21 +1,48 @@
|
|||||||
import { ConditionallyRender } from '../../common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from '../../common/ConditionallyRender/ConditionallyRender';
|
||||||
import { Banner } from '../Banner/Banner';
|
import { Banner } from '../Banner/Banner';
|
||||||
import { IBanner } from '../../../interfaces/banner';
|
import { IBanner } from 'interfaces/banner';
|
||||||
|
import { useOutdatedSdks } from 'hooks/api/getters/useOutdatedSdks/useOutdatedSdks';
|
||||||
|
import { useUiFlag } from 'hooks/useUiFlag';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import { styled } from '@mui/material';
|
||||||
|
|
||||||
|
const StyledList = styled('ul')({ margin: 0 });
|
||||||
|
|
||||||
export const OutdatedSdksBanner = () => {
|
export const OutdatedSdksBanner = () => {
|
||||||
const displayOutdatedSdksBanner = false;
|
const {
|
||||||
|
data: { sdks },
|
||||||
|
} = useOutdatedSdks();
|
||||||
|
const flagEnabled = useUiFlag('outdatedSdksBanner');
|
||||||
|
|
||||||
const outdatedSdksBanner: IBanner = {
|
const outdatedSdksBanner: IBanner = {
|
||||||
message: `We noticed that you're using outdated SDKs. `,
|
message: `We noticed that you're using outdated SDKs. `,
|
||||||
variant: 'warning',
|
variant: 'warning',
|
||||||
link: 'dialog',
|
link: 'dialog',
|
||||||
linkText: 'Please update those versions',
|
linkText: 'Please update those versions',
|
||||||
dialogTitle: 'Outdated SDKs',
|
dialogTitle: 'Outdated SDKs',
|
||||||
dialog: <h1>Outdated SDKs</h1>,
|
dialog: (
|
||||||
|
<>
|
||||||
|
{sdks.map((item) => (
|
||||||
|
<div key={item.sdkVersion}>
|
||||||
|
<span>{item.sdkVersion}</span>
|
||||||
|
<StyledList>
|
||||||
|
{item.applications.map((application) => (
|
||||||
|
<li key={application}>
|
||||||
|
<Link to={`/applications/${application}`}>
|
||||||
|
{application}
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</StyledList>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
),
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={displayOutdatedSdksBanner}
|
condition={flagEnabled && sdks.length > 0}
|
||||||
show={<Banner banner={outdatedSdksBanner} />}
|
show={<Banner banner={outdatedSdksBanner} />}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import useSWR, { SWRConfiguration, Key } from 'swr';
|
import useSWR, { SWRConfiguration, Key } from 'swr';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
|
import handleErrorResponses from '../httpErrorResponseHandler';
|
||||||
|
|
||||||
interface IUseApiGetterOutput<T> {
|
interface IUseApiGetterOutput<T> {
|
||||||
data?: T;
|
data?: T;
|
||||||
@ -26,3 +27,9 @@ export const useApiGetter = <T>(
|
|||||||
loading: !error && !data,
|
loading: !error && !data,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const fetcher = (path: string, errorTarget: string) => {
|
||||||
|
return fetch(path)
|
||||||
|
.then(handleErrorResponses(errorTarget))
|
||||||
|
.then((res) => res.json());
|
||||||
|
};
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
import { fetcher, useApiGetter } from '../useApiGetter/useApiGetter';
|
||||||
|
import { OutdatedSdksSchema } from '../../../../openapi';
|
||||||
|
|
||||||
|
const PATH = 'api/admin/metrics/sdks/outdated';
|
||||||
|
|
||||||
|
export const useOutdatedSdks = () => {
|
||||||
|
const { data, refetch, loading, error } = useApiGetter<OutdatedSdksSchema>(
|
||||||
|
PATH,
|
||||||
|
() => fetcher(PATH, 'Outdated SDKs'),
|
||||||
|
{ refreshInterval: 60 * 1000 },
|
||||||
|
);
|
||||||
|
|
||||||
|
return { data: data || { sdks: [] }, refetch, error };
|
||||||
|
};
|
@ -79,6 +79,7 @@ export type UiFlags = {
|
|||||||
featureSearchFeedbackPosting?: boolean;
|
featureSearchFeedbackPosting?: boolean;
|
||||||
userAccessUIEnabled?: boolean;
|
userAccessUIEnabled?: boolean;
|
||||||
sdkReporting?: boolean;
|
sdkReporting?: boolean;
|
||||||
|
outdatedSdksBanner?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface IVersionInfo {
|
export interface IVersionInfo {
|
||||||
|
14
frontend/src/openapi/models/getOutdatedSdks404.ts
Normal file
14
frontend/src/openapi/models/getOutdatedSdks404.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* Generated by Orval
|
||||||
|
* Do not edit manually.
|
||||||
|
* See `gen:api` script in package.json
|
||||||
|
*/
|
||||||
|
|
||||||
|
export type GetOutdatedSdks404 = {
|
||||||
|
/** The ID of the error instance */
|
||||||
|
id?: string;
|
||||||
|
/** A description of what went wrong. */
|
||||||
|
message?: string;
|
||||||
|
/** The name of the error kind */
|
||||||
|
name?: string;
|
||||||
|
};
|
@ -648,6 +648,7 @@ export * from './getMe401';
|
|||||||
export * from './getOidcSettings400';
|
export * from './getOidcSettings400';
|
||||||
export * from './getOidcSettings401';
|
export * from './getOidcSettings401';
|
||||||
export * from './getOidcSettings403';
|
export * from './getOidcSettings403';
|
||||||
|
export * from './getOutdatedSdks404';
|
||||||
export * from './getPats401';
|
export * from './getPats401';
|
||||||
export * from './getPats403';
|
export * from './getPats403';
|
||||||
export * from './getPats404';
|
export * from './getPats404';
|
||||||
@ -789,6 +790,8 @@ export * from './notificationsSchemaItemNotificationType';
|
|||||||
export * from './oidcSettingsSchema';
|
export * from './oidcSettingsSchema';
|
||||||
export * from './oidcSettingsSchemaDefaultRootRole';
|
export * from './oidcSettingsSchemaDefaultRootRole';
|
||||||
export * from './oidcSettingsSchemaIdTokenSigningAlgorithm';
|
export * from './oidcSettingsSchemaIdTokenSigningAlgorithm';
|
||||||
|
export * from './outdatedSdksSchema';
|
||||||
|
export * from './outdatedSdksSchemaSdksItem';
|
||||||
export * from './overrideSchema';
|
export * from './overrideSchema';
|
||||||
export * from './overwriteEnvironmentFeatureVariants400';
|
export * from './overwriteEnvironmentFeatureVariants400';
|
||||||
export * from './overwriteEnvironmentFeatureVariants401';
|
export * from './overwriteEnvironmentFeatureVariants401';
|
||||||
@ -1044,6 +1047,7 @@ export * from './toggleEnvironmentOff404';
|
|||||||
export * from './toggleEnvironmentOn401';
|
export * from './toggleEnvironmentOn401';
|
||||||
export * from './toggleEnvironmentOn403';
|
export * from './toggleEnvironmentOn403';
|
||||||
export * from './toggleEnvironmentOn404';
|
export * from './toggleEnvironmentOn404';
|
||||||
|
export * from './toggleFeatureActionSchema';
|
||||||
export * from './toggleFeatureEnvironmentOff400';
|
export * from './toggleFeatureEnvironmentOff400';
|
||||||
export * from './toggleFeatureEnvironmentOff401';
|
export * from './toggleFeatureEnvironmentOff401';
|
||||||
export * from './toggleFeatureEnvironmentOff403';
|
export * from './toggleFeatureEnvironmentOff403';
|
||||||
|
14
frontend/src/openapi/models/outdatedSdksSchema.ts
Normal file
14
frontend/src/openapi/models/outdatedSdksSchema.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* Generated by Orval
|
||||||
|
* Do not edit manually.
|
||||||
|
* See `gen:api` script in package.json
|
||||||
|
*/
|
||||||
|
import type { OutdatedSdksSchemaSdksItem } from './outdatedSdksSchemaSdksItem';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data about outdated SDKs that should be upgraded.
|
||||||
|
*/
|
||||||
|
export interface OutdatedSdksSchema {
|
||||||
|
/** A list of SDKs */
|
||||||
|
sdks: OutdatedSdksSchemaSdksItem[];
|
||||||
|
}
|
12
frontend/src/openapi/models/outdatedSdksSchemaSdksItem.ts
Normal file
12
frontend/src/openapi/models/outdatedSdksSchemaSdksItem.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* Generated by Orval
|
||||||
|
* Do not edit manually.
|
||||||
|
* See `gen:api` script in package.json
|
||||||
|
*/
|
||||||
|
|
||||||
|
export type OutdatedSdksSchemaSdksItem = {
|
||||||
|
/** A list of applications using the SDK version */
|
||||||
|
applications: string[];
|
||||||
|
/** An outdated SDK version identifier. Usually formatted as "unleash-client-<language>:<version>" */
|
||||||
|
sdkVersion: string;
|
||||||
|
};
|
17
frontend/src/openapi/models/toggleFeatureActionSchema.ts
Normal file
17
frontend/src/openapi/models/toggleFeatureActionSchema.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* Generated by Orval
|
||||||
|
* Do not edit manually.
|
||||||
|
* See `gen:api` script in package.json
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Input data required for the action
|
||||||
|
*/
|
||||||
|
export interface ToggleFeatureActionSchema {
|
||||||
|
/** The environment we want to target */
|
||||||
|
environment: string;
|
||||||
|
/** The name of the feature we want to target */
|
||||||
|
featureName: string;
|
||||||
|
/** The project where the feature is located */
|
||||||
|
project: string;
|
||||||
|
}
|
@ -130,6 +130,7 @@ exports[`should create default config 1`] = `
|
|||||||
},
|
},
|
||||||
"migrationLock": true,
|
"migrationLock": true,
|
||||||
"newStrategyConfigurationFeedback": false,
|
"newStrategyConfigurationFeedback": false,
|
||||||
|
"outdatedSdksBanner": false,
|
||||||
"personalAccessTokensKillSwitch": false,
|
"personalAccessTokensKillSwitch": false,
|
||||||
"proPlanAutoCharge": false,
|
"proPlanAutoCharge": false,
|
||||||
"queryMissingTokens": false,
|
"queryMissingTokens": false,
|
||||||
|
@ -51,6 +51,7 @@ export type IFlagKey =
|
|||||||
| 'disableUpdateMaxRevisionId'
|
| 'disableUpdateMaxRevisionId'
|
||||||
| 'disablePublishUnannouncedEvents'
|
| 'disablePublishUnannouncedEvents'
|
||||||
| 'sdkReporting'
|
| 'sdkReporting'
|
||||||
|
| 'outdatedSdksBanner'
|
||||||
| 'responseTimeMetricsFix'
|
| 'responseTimeMetricsFix'
|
||||||
| 'scimApi'
|
| 'scimApi'
|
||||||
| 'displayEdgeBanner'
|
| 'displayEdgeBanner'
|
||||||
@ -203,6 +204,10 @@ const flags: IFlags = {
|
|||||||
process.env.UNLEASH_EXPERIMENTAL_SDK_REPORTING,
|
process.env.UNLEASH_EXPERIMENTAL_SDK_REPORTING,
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
|
outdatedSdksBanner: parseEnvVarBoolean(
|
||||||
|
process.env.UNLEASH_EXPERIMENTAL_OUTDATED_SDKS_BANNER,
|
||||||
|
false,
|
||||||
|
),
|
||||||
feedbackComments: {
|
feedbackComments: {
|
||||||
name: 'feedbackComments',
|
name: 'feedbackComments',
|
||||||
enabled: parseEnvVarBoolean(
|
enabled: parseEnvVarBoolean(
|
||||||
|
Loading…
Reference in New Issue
Block a user