Skip to content

Commit 62d2f4e

Browse files
debsmita1christoph-jerolimov
authored andcommitted
add customization forms for perspectives and developer catalog (#7)
1 parent 014b41f commit 62d2f4e

15 files changed

Lines changed: 419 additions & 47 deletions

File tree

frontend/packages/console-app/console-extensions.json

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,36 @@
263263
"readAccessReview": [
264264
{
265265
"group": "operator.openshift.io/v1",
266-
"resource": "consolesXXX",
266+
"resource": "consoles",
267+
"verb": "get",
268+
"name": "cluster"
269+
}
270+
],
271+
"writeAccessReview": [
272+
{
273+
"group": "operator.openshift.io/v1",
274+
"resource": "consoles",
275+
"verb": "patch",
276+
"name": "cluster"
277+
}
278+
]
279+
}
280+
},
281+
{
282+
"type": "console.cluster-configuration/item",
283+
"properties": {
284+
"id": "console-app.customization.perspectives",
285+
"groupId": "general",
286+
"label": "%console-app~Perspectives%",
287+
"description": "%console-app~Show or hide perspectives by enabling, disabling or adding access review check(s).%",
288+
"field": {
289+
"type": "custom",
290+
"component": { "$codeRef": "perspective.perspectiveConfiguration" }
291+
},
292+
"readAccessReview": [
293+
{
294+
"group": "operator.openshift.io/v1",
295+
"resource": "consoles",
267296
"verb": "get",
268297
"name": "cluster"
269298
}

frontend/packages/console-app/locales/en/console-app.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
"Developer": "Developer",
77
"Custom product name": "Custom product name",
88
"The name that will be displayed in page titles, logo alt text, and the about dialog instead of the normal OpenShift product name.": "The name that will be displayed in page titles, logo alt text, and the about dialog instead of the normal OpenShift product name.",
9+
"Perspectives": "Perspectives",
10+
"Show or hide perspectives by enabling, disabling or adding access review check(s).": "Show or hide perspectives by enabling, disabling or adding access review check(s).",
911
"Documentation URL": "Documentation URL",
1012
"Documentation links to external documentation are shown in various sections of the web console. Providing a base URL will override the default documentation URL. Invalid value will prevent a console rollout.": "Documentation links to external documentation are shown in various sections of the web console. Providing a base URL will override the default documentation URL. Invalid value will prevent a console rollout.",
1113
"LogLevel": "LogLevel",
@@ -245,6 +247,7 @@
245247
"Console plugins table": "Console plugins table",
246248
"console plugins": "console plugins",
247249
"Console plugins": "Console plugins",
250+
"Customize": "Customize",
248251
"Updating cluster to {{version}}": "Updating cluster to {{version}}",
249252
"API Servers": "API Servers",
250253
"Controller Managers": "Controller Managers",
@@ -260,6 +263,7 @@
260263
"{{enabledCount}}/{{totalCount}} enabled": "{{enabledCount}}/{{totalCount}} enabled",
261264
"View all": "View all",
262265
"Single master": "Single master",
266+
"Show or hide perspective(s).": "Show or hide perspective(s).",
263267
"Incompatible file type": "Incompatible file type",
264268
"{{fileName}} cannot be uploaded. Only {{fileExtensions}} files are supported currently. Try another file.": "{{fileName}} cannot be uploaded. Only {{fileExtensions}} files are supported currently. Try another file.",
265269
"Clone": "Clone",
@@ -522,6 +526,7 @@
522526
"Select a perspective": "Select a perspective",
523527
"Select an option": "Select an option",
524528
"User Preferences": "User Preferences",
529+
"Set your individual preferences for the console experience. Any changes will be autosaved.": "Set your individual preferences for the console experience. Any changes will be autosaved.",
525530
"Only {{volumeMode}} volume mode is available for {{storageClass}} with {{accessMode}} access mode": "Only {{volumeMode}} volume mode is available for {{storageClass}} with {{accessMode}} access mode",
526531
"VolumeSnapshotClass with same provisioner as claim": "VolumeSnapshotClass with same provisioner as claim",
527532
"Select volume snapshot class": "Select volume snapshot class",

frontend/packages/console-app/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
"actions": "src/actions",
4343
"clusterConfiguration": "src/components/cluster-configuration",
4444
"userPreferences": "src/components/user-preferences",
45-
"perspective": "src/utils/perspective",
45+
"perspective": "src",
4646
"dynamicPluginsHealthResource": "src/components/dashboards-page/dynamic-plugins-health-resource",
4747
"storageProvisioners": "src/components/storage/StorageClassProviders",
4848
"storageProvisionerDocs": "src/components/storage/Documentation"

frontend/packages/console-app/src/components/console-operator/ConsoleOperatorConfig.tsx

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,18 @@ import {
1212
TableVariant,
1313
} from '@patternfly/react-table';
1414
import { useTranslation } from 'react-i18next';
15-
import { WatchK8sResource } from '@console/dynamic-plugin-sdk';
15+
import { useAccessReview, WatchK8sResource } from '@console/dynamic-plugin-sdk';
1616
import { breadcrumbsForGlobalConfig } from '@console/internal/components/cluster-settings/global-config';
1717
import { DetailsForKind } from '@console/internal/components/default-resource';
1818
import { DetailsPage } from '@console/internal/components/factory';
19-
import { EmptyBox, LoadingBox, navFactory, ResourceLink } from '@console/internal/components/utils';
19+
import {
20+
asAccessReview,
21+
EmptyBox,
22+
LoadingBox,
23+
navFactory,
24+
ResourceLink,
25+
} from '@console/internal/components/utils';
2026
import { useK8sWatchResource } from '@console/internal/components/utils/k8s-watch-hook';
21-
import { useAccessReview } from '@console/internal/components/utils/rbac';
2227
import { ConsoleOperatorConfigModel, ConsolePluginModel } from '@console/internal/models';
2328
import {
2429
ConsolePluginKind,
@@ -186,6 +191,7 @@ const ConsolePluginsList: React.FC<ConsolePluginsListType> = ({ obj }) => {
186191
export const ConsoleOperatorConfigDetailsPage: React.FC<React.ComponentProps<
187192
typeof DetailsPage
188193
>> = (props) => {
194+
const { t } = useTranslation();
189195
const pages = [
190196
navFactory.details(DetailsForKind(props.kind)),
191197
navFactory.editYaml(),
@@ -197,10 +203,25 @@ export const ConsoleOperatorConfigDetailsPage: React.FC<React.ComponentProps<
197203
},
198204
];
199205

206+
const menuActions = [
207+
() => ({
208+
labelKey: t('console-app~Customize'),
209+
labelKind: { kind: ConsoleOperatorConfigModel.kind },
210+
dataTest: `Customize`,
211+
href: '/cluster-configuration',
212+
accessReview: asAccessReview(
213+
ConsoleOperatorConfigModel,
214+
{ spec: { name: 'cluster' } },
215+
'patch',
216+
),
217+
}),
218+
];
219+
200220
return (
201221
<DetailsPage
202222
{...props}
203223
kind={consoleOperatorConfigReference}
224+
menuActions={menuActions}
204225
pages={pages}
205226
breadcrumbsFor={() =>
206227
breadcrumbsForGlobalConfig(ConsoleOperatorConfigModel.label, props.match.url)
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
import * as React from 'react';
2+
import { Checkbox, FormGroup } from '@patternfly/react-core';
3+
import { useTranslation } from 'react-i18next';
4+
import {
5+
isPerspective,
6+
Perspective as PerspectiveExtension,
7+
AccessReviewResourceAttributes,
8+
} from '@console/dynamic-plugin-sdk/src';
9+
import { LoadedExtension, useExtensions } from '@console/plugin-sdk/src';
10+
11+
export enum PerspectiveVisibilityState {
12+
Enabled = 'Enabled',
13+
Disabled = 'Disabled',
14+
AccessReview = 'AccessReview',
15+
}
16+
17+
type PerspectiveAccessReview = {
18+
required?: AccessReviewResourceAttributes[];
19+
missing?: AccessReviewResourceAttributes[];
20+
};
21+
22+
export type PerspectiveVisibility = {
23+
state: PerspectiveVisibilityState;
24+
accessReview?: PerspectiveAccessReview;
25+
};
26+
27+
export type Perspective = {
28+
id: string;
29+
visibility: PerspectiveVisibility;
30+
};
31+
32+
const PerspectiveConfiguration: React.FC = () => {
33+
const perspectiveExtensions = useExtensions<PerspectiveExtension>(isPerspective);
34+
const { t } = useTranslation();
35+
const [isChecked, setIsChecked] = React.useState<Record<string, string>>(() => {
36+
let obj: Record<string, string> = {};
37+
if (!window.SERVER_FLAGS.perspectives) {
38+
obj = perspectiveExtensions.reduce(
39+
(acc: Record<string, string>, ex: LoadedExtension<PerspectiveExtension>) => {
40+
acc[ex.properties.id] = null;
41+
return acc;
42+
},
43+
{},
44+
);
45+
} else {
46+
const perspectives: Perspective[] = JSON.parse(window.SERVER_FLAGS.perspectives);
47+
obj = perspectiveExtensions.reduce((acc, perspectiveExtension) => {
48+
const perspective = perspectives?.find((p) => p.id === perspectiveExtension.properties.id);
49+
50+
if (perspective?.visibility?.state === PerspectiveVisibilityState.Enabled) {
51+
acc[perspectiveExtension.properties.id] = 'Enabled';
52+
} else if (perspective?.visibility?.state === PerspectiveVisibilityState.Disabled) {
53+
acc[perspectiveExtension.properties.id] = 'Disabled';
54+
} else if (perspective?.visibility?.state === PerspectiveVisibilityState.AccessReview) {
55+
if (
56+
perspective.visibility.accessReview?.missing?.length > 0 &&
57+
perspective.visibility.accessReview.missing.find((ob) => ob.resource === 'namespaces')
58+
) {
59+
acc[perspectiveExtension.properties.id] = 'AccessReviewMissing';
60+
} else if (
61+
perspective.visibility.accessReview?.required?.length > 0 &&
62+
perspective.visibility.accessReview.required.find((ob) => ob.resource === 'namespaces')
63+
) {
64+
acc[perspectiveExtension.properties.id] = 'AccessReviewRequired';
65+
}
66+
}
67+
return acc;
68+
}, {});
69+
}
70+
return obj;
71+
});
72+
73+
const handleOnChange = React.useCallback(
74+
(id: string, value: string) => {
75+
setIsChecked((oldResults: Record<string, string>) => {
76+
if (oldResults[id] === value) {
77+
return oldResults;
78+
}
79+
return {
80+
...oldResults,
81+
[id]: value,
82+
};
83+
});
84+
},
85+
[setIsChecked],
86+
);
87+
return (
88+
<FormGroup fieldId="perspectives" label="Perspectives" data-test="perspectives field">
89+
<div className="pf-c-form__helper-text">{t('console-app~Show or hide perspective(s).')}</div>
90+
{perspectiveExtensions.map((ex) => (
91+
<>
92+
<h5>{ex.properties.name}</h5>
93+
<Checkbox
94+
className="nested"
95+
label="Enabled"
96+
name={ex.properties.name}
97+
id={`${ex.properties.id}-enabled`}
98+
isChecked={isChecked[ex.properties.id] === 'Enabled'}
99+
onChange={() => handleOnChange(ex.properties.id, 'Enabled')}
100+
/>
101+
<Checkbox
102+
id={`${ex.properties.id}-priviledged`}
103+
className="nested"
104+
label="Only visible for privileged users"
105+
name={ex.properties.name}
106+
isChecked={isChecked[ex.properties.id] === 'AccessReviewRequired'}
107+
onChange={() => handleOnChange(ex.properties.id, 'AccessReviewRequired')}
108+
/>
109+
<Checkbox
110+
id={`${ex.properties.id}-unpriviledged`}
111+
className="nested"
112+
label="Only visible for unprivileged users"
113+
name={ex.properties.name}
114+
isChecked={isChecked[ex.properties.id] === 'AccessReviewMissing'}
115+
onChange={() => handleOnChange(ex.properties.id, 'AccessReviewMissing')}
116+
/>
117+
<Checkbox
118+
id={`${ex.properties.id}-disabled`}
119+
className="nested"
120+
label="Disabled"
121+
name={ex.properties.name}
122+
isChecked={isChecked[ex.properties.id] === 'Disabled'}
123+
onChange={() => handleOnChange(ex.properties.id, 'Disabled')}
124+
/>
125+
</>
126+
))}
127+
</FormGroup>
128+
);
129+
};
130+
131+
export default PerspectiveConfiguration;

frontend/packages/console-app/src/components/user-preferences/UserPreferencePage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ const UserPreferencePage: React.FC<UserPreferencePageProps> = ({ match }) => {
121121
<PageLayout
122122
title={t('console-app~User Preferences')}
123123
hint={t(
124-
'Set your individual preferences for the console experience. Any changes will be autosaved.',
124+
'console-app~Set your individual preferences for the console experience. Any changes will be autosaved.',
125125
)}
126126
>
127127
{userPreferenceItemResolved ? (
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
11
import '@console/internal/i18n.js';
2+
3+
export { default as perspectiveConfiguration } from './components/detect-perspective/PerspectiveConfiguration';
4+
export * from './utils/perspective';

frontend/packages/dev-console/console-extensions.json

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,35 @@
8181
]
8282
}
8383
},
84-
84+
{
85+
"type": "console.cluster-configuration/item",
86+
"properties": {
87+
"id": "dev-console.DeveloperCatalogTypesConfiguration",
88+
"groupId": "developer",
89+
"label": "%devconsole~Developer Catalog Types%",
90+
"description": "%devconsole~Enable or Disable Catalog types%",
91+
"field": {
92+
"type": "custom",
93+
"component": { "$codeRef": "catalog.catalogTypesConfiguration" }
94+
},
95+
"readAccessReview": [
96+
{
97+
"group": "operator.openshift.io/v1",
98+
"resource": "consoles",
99+
"verb": "get",
100+
"name": "cluster"
101+
}
102+
],
103+
"writeAccessReview": [
104+
{
105+
"group": "operator.openshift.io/v1",
106+
"resource": "consoles",
107+
"verb": "patch",
108+
"name": "cluster"
109+
}
110+
]
111+
}
112+
},
85113
{
86114
"type": "dev-console.add/action-group",
87115
"properties": {

frontend/packages/dev-console/locales/en/devconsole.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
"Project access Cluster Roles": "Project access Cluster Roles",
44
"TODO": "TODO",
55
"Add page actions": "Add page actions",
6+
"Developer Catalog Types": "Developer Catalog Types",
7+
"Enable or Disable Catalog types": "Enable or Disable Catalog types",
68
"Developer Catalog": "Developer Catalog",
79
"Git Repository": "Git Repository",
810
"Container images": "Container images",
@@ -72,8 +74,8 @@
7274
"Add options failed to load. Check your connection and reload the page.": "Add options failed to load. Check your connection and reload the page.",
7375
"Add": "Add",
7476
"Select a Project to start adding to it or <2>create a Project</2>.": "Select a Project to start adding to it or <2>create a Project</2>.",
75-
"Enabled add page options": "Enabled add page options",
76-
"Disabled add page options": "Disabled add page options",
77+
"Enabled Add page options": "Enabled Add page options",
78+
"Disabled Add page options": "Disabled Add page options",
7779
"Details on": "Details on",
7880
"Details off": "Details off",
7981
"Show or hide details about each item": "Show or hide details about each item",
@@ -166,6 +168,8 @@
166168
"Select a Project to view the list of builds or <2>create a Project</2>.": "Select a Project to view the list of builds or <2>create a Project</2>.",
167169
"Add shared applications, services, event sources, or source-to-image builders to your Project from the developer catalog. Cluster administrators can customize the content made available in the catalog.": "Add shared applications, services, event sources, or source-to-image builders to your Project from the developer catalog. Cluster administrators can customize the content made available in the catalog.",
168170
"Select a Project to view the developer catalog or <2>create a Project</2>.": "Select a Project to view the developer catalog or <2>create a Project</2>.",
171+
"Enabled Catalog types": "Enabled Catalog types",
172+
"Disabled Catalog types": "Disabled Catalog types",
169173
"Bindable": "Bindable",
170174
"Create": "Create",
171175
"Sample repository": "Sample repository",

0 commit comments

Comments
 (0)