Skip to content

Commit

Permalink
remove static perspective extension
Browse files Browse the repository at this point in the history
  • Loading branch information
christianvogt committed Aug 19, 2021
1 parent 0d6cf83 commit b0fac5d
Show file tree
Hide file tree
Showing 26 changed files with 275 additions and 152 deletions.
@@ -1,5 +1,4 @@
import { isNavItem } from '@console/dynamic-plugin-sdk';
import { isPerspective } from '@console/plugin-sdk';
import { isNavItem, isPerspective } from '@console/dynamic-plugin-sdk';
import { testedExtensions } from '../plugin-test-utils';

describe('NavItem', () => {
Expand Down
@@ -1,9 +1,10 @@
import * as _ from 'lodash';
import { isPerspective } from '@console/plugin-sdk';
import { isPerspective } from '@console/dynamic-plugin-sdk';
import { testedExtensions } from '../plugin-test-utils';

describe('Perspective', () => {
it('duplicate ids are not allowed', () => {
// TODO need to load console-extensions.json for tests to function
xit('duplicate ids are not allowed', () => {
const perspectives = testedExtensions.toArray().filter(isPerspective);
const dedupedPerspectives = _.uniqWith(
perspectives,
Expand All @@ -14,7 +15,7 @@ describe('Perspective', () => {
expect(duplicatePerspectives).toEqual([]);
});

it('exactly one default perspective is allowed', () => {
xit('exactly one default perspective is allowed', () => {
const perspectives = testedExtensions.toArray().filter(isPerspective);
const defaultPerspectives = perspectives.filter((p) => p.properties.default);

Expand Down
@@ -1,5 +1,6 @@
import * as React from 'react';
import { isPerspective, Perspective, useExtensions } from '@console/plugin-sdk';
import { isPerspective, Perspective } from '@console/dynamic-plugin-sdk';
import { useExtensions } from '@console/plugin-sdk';
import { PerpsectiveContext } from './perspective-context';
import PerspectiveDetector from './PerspectiveDetector';
import { useValuesForPerspectiveContext } from './useValuesForPerspectiveContext';
Expand Down
@@ -1,30 +1,43 @@
import * as React from 'react';
import { useExtensions, Perspective, isPerspective } from '@console/plugin-sdk';
import { Perspective, isPerspective, ResolvedExtension } from '@console/dynamic-plugin-sdk';
import { useExtensions } from '@console/plugin-sdk';

type PerspectiveDetectorProps = {
type DetectorProps = {
setActivePerspective: (perspective: string) => void;
perspectiveExtensions: Perspective[];
detectors: (
| undefined
| ResolvedExtension<Perspective>['properties']['usePerspectiveDetection']
)[];
};

const PerspectiveDetector: React.FC<PerspectiveDetectorProps> = ({ setActivePerspective }) => {
const Detector: React.FC<DetectorProps> = ({
setActivePerspective,
perspectiveExtensions,
detectors,
}) => {
let detectedPerspective: string;
const perspectiveExtensions = useExtensions<Perspective>(isPerspective);
const defaultPerspective = perspectiveExtensions.find((p) => p.properties.default);
const detectors = perspectiveExtensions.filter((p) => p.properties.usePerspectiveDetection);
const detectionResults = detectors.map((p) => p.properties.usePerspectiveDetection());
const defaultPerspective =
perspectiveExtensions.find((p) => p.properties.default) || perspectiveExtensions[0];
const detectionResults = detectors.map((detector) => detector?.());

const detectionComplete = detectionResults.every((result, index) => {
const [enablePerspective, loading] = result;
if (!detectedPerspective && !loading && enablePerspective) {
detectedPerspective = detectors[index].properties.id;
if (result) {
const [enablePerspective, loading] = result;
if (!detectedPerspective && !loading && enablePerspective) {
detectedPerspective = perspectiveExtensions[index].properties.id;
}
return loading === false;
}
return loading === false;
return true;
});

React.useEffect(() => {
if (detectedPerspective) {
setActivePerspective(detectedPerspective);
} else if (detectors.length < 1 || detectionComplete) {
setActivePerspective(defaultPerspective.properties.id); // set default perspective if there are no detectors or none of the detections were successfull
} else if (defaultPerspective && (detectors.length < 1 || detectionComplete)) {
// set default perspective if there are no detectors or none of the detections were successfull
setActivePerspective(defaultPerspective.properties.id);
}
}, [
defaultPerspective,
Expand All @@ -37,4 +50,52 @@ const PerspectiveDetector: React.FC<PerspectiveDetectorProps> = ({ setActivePers
return null;
};

type PerspectiveDetectorProps = {
setActivePerspective: (perspective: string) => void;
};

const PerspectiveDetector: React.FC<PerspectiveDetectorProps> = ({ setActivePerspective }) => {
const perspectiveExtensions = useExtensions<Perspective>(isPerspective);
const [detectors, setDetectors] = React.useState<
(undefined | ResolvedExtension<Perspective>['properties']['usePerspectiveDetection'])[]
>();
React.useEffect(() => {
let resolveCount = 0;
const resolvedDetectors: ResolvedExtension<
Perspective
>['properties']['usePerspectiveDetection'][] = [];
perspectiveExtensions.forEach((p, i) => {
if (p.properties.usePerspectiveDetection) {
p.properties
.usePerspectiveDetection()
.then((detector) => {
resolvedDetectors[i] = detector;
})
.finally(() => {
resolveCount++;
if (resolveCount === perspectiveExtensions.length) {
setDetectors(resolvedDetectors);
}
})
.catch((e) => {
// eslint-disable-next-line no-console
console.error(e);
});
} else {
resolveCount++;
if (resolveCount === perspectiveExtensions.length) {
setDetectors(resolvedDetectors);
}
}
});
}, [perspectiveExtensions]);
return Array.isArray(detectors) ? (
<Detector
setActivePerspective={setActivePerspective}
perspectiveExtensions={perspectiveExtensions}
detectors={detectors}
/>
) : null;
};

export default PerspectiveDetector;
@@ -1,6 +1,8 @@
import * as React from 'react';
import { mount } from 'enzyme';
import { Perspective, useExtensions } from '@console/plugin-sdk';
import { act } from 'react-dom/test-utils';
import { Perspective } from '@console/dynamic-plugin-sdk';
import { useExtensions, LoadedExtension } from '@console/plugin-sdk';
import PerspectiveDetector from '../PerspectiveDetector';

jest.mock('@console/plugin-sdk', () => ({
Expand All @@ -9,48 +11,68 @@ jest.mock('@console/plugin-sdk', () => ({

const mockPerspectives = [
{
type: 'Perspective',
type: 'console.perspective',
properties: {
id: 'admin',
name: 'Admin Perspective',
default: true,
},
},
{
type: 'Perspective',
type: 'console.perspective',
properties: {
id: 'dev',
name: 'Dev Perspective',
usePerspectiveDetection: undefined,
},
},
] as Perspective[];
] as LoadedExtension<Perspective>[];

const setActivePerspective = jest.fn();

describe('PerspectiveDetector', () => {
it('should set default perspective if there are no perspective detectors available', () => {
it('should set default perspective if there are no perspective detectors available', async () => {
(useExtensions as jest.Mock).mockImplementation(() => mockPerspectives);

const wrapper = mount(<PerspectiveDetector setActivePerspective={setActivePerspective} />);
expect(wrapper.isEmptyRender()).toBe(true);
expect(setActivePerspective).toHaveBeenCalledWith('admin');
});

it('should set detected perspective if detection is successful', () => {
mockPerspectives[1].properties.usePerspectiveDetection = () => [true, false];
it('should set detected perspective if detection is successful', async () => {
// create a promise and capture the resolver such that we can use act later on to ensure
// the test waits for this promise to resolve before continuing
let promiseResolver: (value: () => [boolean, boolean]) => void;
const testPromise = new Promise<() => [boolean, boolean]>(
(resolver) => (promiseResolver = resolver),
);
mockPerspectives[1].properties.usePerspectiveDetection = () => testPromise;

(useExtensions as jest.Mock).mockImplementation(() => mockPerspectives);

const wrapper = mount(<PerspectiveDetector setActivePerspective={setActivePerspective} />);
await act(async () => {
promiseResolver(() => [true, false]);
});
expect(wrapper.isEmptyRender()).toBe(true);
expect(setActivePerspective).toHaveBeenCalledWith('dev');
});

it('should set default perspective if detection fails', () => {
mockPerspectives[1].properties.usePerspectiveDetection = () => [false, false];
it('should set default perspective if detection fails', async () => {
// create a promise and capture the resolver such that we can use act later on to ensure
// the test waits for this promise to resolve before continuing
let promiseResolver: (value: () => [boolean, boolean]) => void;
const testPromise = new Promise<() => [boolean, boolean]>(
(resolver) => (promiseResolver = resolver),
);
mockPerspectives[1].properties.usePerspectiveDetection = () => testPromise;

(useExtensions as jest.Mock).mockImplementation(() => mockPerspectives);

const wrapper = mount(<PerspectiveDetector setActivePerspective={setActivePerspective} />);
await act(async () => {
promiseResolver(() => [false, false]);
});
expect(wrapper.isEmptyRender()).toBe(true);
expect(setActivePerspective).toHaveBeenCalledWith('admin');
});
Expand Down
@@ -1,5 +1,6 @@
import * as React from 'react';
import { isPerspective, Perspective, useExtensions } from '@console/plugin-sdk';
import { isPerspective, Perspective } from '@console/dynamic-plugin-sdk';
import { useExtensions } from '@console/plugin-sdk';
import { useUserSettingsCompatibility } from '@console/shared';
import { PerspectiveType } from './perspective-context';

Expand Down
1 change: 0 additions & 1 deletion frontend/packages/console-plugin-sdk/src/typings/index.ts
Expand Up @@ -8,7 +8,6 @@ export * from './models';
export * from './nav-section';
export * from './overview';
export * from './pages';
export * from './perspectives';
export * from './global-configs';
export * from './clusterserviceversions';
export * from './horizontal-nav';
Expand Down
36 changes: 0 additions & 36 deletions frontend/packages/console-plugin-sdk/src/typings/perspectives.ts

This file was deleted.

Expand Up @@ -75,7 +75,7 @@ describe('usePinnedResources', () => {

// Expect default pins
expect(result.current).toEqual([
[{ kind: 'ConfigMap' }, { kind: 'Secret' }],
['core~~ConfigMap', 'core~~Secret'],
expect.any(Function),
true,
]);
Expand Down
11 changes: 9 additions & 2 deletions frontend/packages/console-shared/src/hooks/usePinnedResources.ts
@@ -1,6 +1,8 @@
import { useMemo, useCallback } from 'react';
import * as _ from 'lodash';
import { isPerspective, Perspective, useExtensions } from '@console/plugin-sdk';
import { isPerspective, Perspective } from '@console/dynamic-plugin-sdk';
import { referenceForExtensionModel } from '@console/internal/module/k8s';
import { useExtensions } from '@console/plugin-sdk';
import { PINNED_RESOURCES_LOCAL_STORAGE_KEY } from '../constants';
import { useActivePerspective } from './useActivePerspective';
import { useTelemetry } from './useTelemetry';
Expand All @@ -19,7 +21,12 @@ export const usePinnedResources = (): [string[], (pinnedResources: string[]) =>
const defaultPins = useMemo(
() =>
perspectiveExtensions.reduce(
(acc, e) => ({ ...acc, [e.properties.id]: e.properties.defaultPins || [] }),
(acc, e) => ({
...acc,
[e.properties.id]: (e.properties.defaultPins || []).map((gvk) =>
referenceForExtensionModel(gvk),
),
}),
{},
),
[perspectiveExtensions],
Expand Down
23 changes: 23 additions & 0 deletions frontend/packages/dev-console/console-extensions.json
@@ -1,4 +1,27 @@
[
{
"type": "console.perspective",
"properties": {
"id": "dev",
"name": "%devconsole~Developer%",
"icon": { "$codeRef": "perspective.icon" },
"defaultPins": [
{
"group": "",
"version": "v1",
"kind": "ConfigMap"
},
{
"group": "",
"version": "v1",
"kind": "Secret"
}
],
"landingPageURL": { "$codeRef": "perspective.getLandingPageURL" },
"importRedirectURL": { "$codeRef": "perspective.getImportRedirectURL" },
"usePerspectiveDetection": { "$codeRef": "perspective.usePerspectiveDetection" }
}
},
{
"type": "dev-console.add/action-group",
"properties": {
Expand Down
Expand Up @@ -2,10 +2,11 @@ import * as React from 'react';
import { Formik, FormikProps } from 'formik';
import * as _ from 'lodash';
import { useTranslation } from 'react-i18next';
import { Perspective, isPerspective } from '@console/dynamic-plugin-sdk';
import { history } from '@console/internal/components/utils';
import { ImageStreamModel } from '@console/internal/models';
import { k8sGet, K8sResourceKind } from '@console/internal/module/k8s';
import { useExtensions, Perspective, isPerspective } from '@console/plugin-sdk';
import { useExtensions } from '@console/plugin-sdk';
import { useActivePerspective } from '@console/shared';
import { NormalizedBuilderImages, normalizeBuilderImages } from '../../utils/imagestream-utils';
import { createOrUpdateDeployImageResources } from '../import/deployImage-submit-utils';
Expand Down
Expand Up @@ -2,10 +2,11 @@ import * as React from 'react';
import { FormikBag, Formik } from 'formik';
import { safeLoad } from 'js-yaml';
import { useTranslation } from 'react-i18next';
import { Perspective, isPerspective } from '@console/dynamic-plugin-sdk';
import { history } from '@console/internal/components/utils';
import { DeploymentConfigModel, DeploymentModel } from '@console/internal/models';
import { K8sResourceKind, k8sUpdate } from '@console/internal/module/k8s';
import { useExtensions, Perspective, isPerspective } from '@console/plugin-sdk';
import { useExtensions } from '@console/plugin-sdk';
import { useActivePerspective } from '@console/shared';
import { EditorType } from '@console/shared/src/components/synced-editor/editor-toggle';
import { getResourcesType } from '../edit-application/edit-application-utils';
Expand Down
Expand Up @@ -3,10 +3,11 @@ import { Formik, FormikProps } from 'formik';
import * as _ from 'lodash';
import { useTranslation } from 'react-i18next';
import { connect } from 'react-redux';
import { Perspective, isPerspective } from '@console/dynamic-plugin-sdk';
import { history, AsyncComponent } from '@console/internal/components/utils';
import { getActiveApplication } from '@console/internal/reducers/ui';
import { RootState } from '@console/internal/redux';
import { useExtensions, Perspective, isPerspective } from '@console/plugin-sdk';
import { useExtensions } from '@console/plugin-sdk';
import {
ALL_APPLICATIONS_KEY,
useActivePerspective,
Expand Down

0 comments on commit b0fac5d

Please sign in to comment.