Skip to content

Commit b5a510b

Browse files
committed
Expose NamespaceBar in the core API
1 parent fcf4705 commit b5a510b

File tree

17 files changed

+306
-110
lines changed

17 files changed

+306
-110
lines changed

dynamic-demo-plugin/console-extensions.json

+20
Original file line numberDiff line numberDiff line change
@@ -349,5 +349,25 @@
349349
"name": "Modal Launchers",
350350
"href": "/test-modal"
351351
}
352+
},
353+
{
354+
"type": "console.page/route",
355+
"properties": {
356+
"exact": false,
357+
"path": ["/example-namespaced-page/ns/:ns", "/example-namespaced-page/all-namespaces"],
358+
"component": {
359+
"$codeRef": "exampleNamespacedPage.ExampleNamespacedPage"
360+
}
361+
}
362+
},
363+
{
364+
"type": "console.navigation/href",
365+
"properties": {
366+
"namespaced": true,
367+
"id": "demo-example-namespaced-page",
368+
"perspective": "demo",
369+
"name": "%plugin__console-demo-plugin~Example Namespaced Page%",
370+
"href": "/example-namespaced-page"
371+
}
352372
}
353373
]

dynamic-demo-plugin/locales/en/plugin__console-demo-plugin.json

+10-4
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,17 @@
22
"{{count}} Worker Node": "{{count}} Worker Node",
33
"{{count}} Worker Node_plural": "{{count}} Worker Nodes",
44
"Worker Nodes": "Worker Nodes",
5+
"Example page with a namespace bar": "Example page with a namespace bar",
6+
"Currently selected namespace": "Currently selected namespace",
57
"Example info alert": "Example info alert",
68
"Example warning alert": "Example warning alert",
79
"Example hint": "Example hint",
810
"This page shows an example gallery view with cards": "This page shows an example gallery view with cards",
911
"Example card": "Example card",
1012
"Card content goes here.": "Card content goes here.",
13+
"Prometheus error": "Prometheus error",
14+
"Prometheus loading": "Prometheus loading",
15+
"Prometheus data": "Prometheus data",
1116
"Dynamic Plugin Proxy Services example": "Dynamic Plugin Proxy Services example",
1217
"Proxy: consoleFetchJSON": "Proxy: consoleFetchJSON",
1318
"Extensions of type Console.flag/Model": "Extensions of type Console.flag/Model",
@@ -25,6 +30,9 @@
2530
"My value": "My value",
2631
"Added title - error": "Added title - error",
2732
"Error text": "Error text",
33+
"{{count}} Cron Job": "{{count}} Cron Job",
34+
"{{count}} Cron Job_plural": "{{count}} Cron Jobs",
35+
"Cron Jobs": "Cron Jobs",
2836
"Utilities from Dynamic Plugin SDK": "Utilities from Dynamic Plugin SDK",
2937
"Utility: consoleFetchJSON": "Utility: consoleFetchJSON",
3038
"Demo": "Demo",
@@ -35,9 +43,7 @@
3543
"Test Utilities": "Test Utilities",
3644
"Foo item": "Foo item",
3745
"Bar item": "Bar item",
46+
"Example Namespaced Page": "Example Namespaced Page",
3847
"Dynamic Page 1": "Dynamic Page 1",
39-
"Dynamic Page 2": "Dynamic Page 2",
40-
"Prometheus error": "Prometheus error",
41-
"Prometheus loading": "Prometheus loading",
42-
"Prometheus data": "Prometheus data"
48+
"Dynamic Page 2": "Dynamic Page 2"
4349
}

dynamic-demo-plugin/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
"utilityConsumer": "./components/UtilityConsumer",
5757
"exampleProxyPage": "./components/ExampleProxyPage",
5858
"K8sAPIConsumer": "./components/k8sConsumer/K8sAPIConsumer",
59+
"exampleNamespacedPage": "./components/ExampleNamespacedPage",
5960
"navPage": "./components/Nav",
6061
"listPage": "./components/ListPage",
6162
"projectTabContent": "./components/ProjectTabExtensionContent",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import * as React from 'react';
2+
import { useTranslation } from 'react-i18next';
3+
import { match as RMatch } from 'react-router-dom';
4+
import {
5+
Card,
6+
CardBody,
7+
Flex,
8+
Page,
9+
PageSection,
10+
PageSectionVariants,
11+
Title,
12+
} from '@patternfly/react-core';
13+
import { NamespaceBar } from '@openshift-console/dynamic-plugin-sdk';
14+
15+
const NamespacePageContent = ({ namespace }: { namespace?: string }) => {
16+
const { t } = useTranslation('plugin__console-demo-plugin');
17+
18+
return (
19+
<Page>
20+
<PageSection variant={PageSectionVariants.light}>
21+
<Title headingLevel="h1">{t('Example page with a namespace bar')}</Title>
22+
</PageSection>
23+
<PageSection>
24+
<Card>
25+
<CardBody>
26+
<Flex
27+
alignItems={{ default: 'alignItemsCenter' }}
28+
justifyContent={{ default: 'justifyContentCenter' }}
29+
grow={{ default: 'grow' }}
30+
direction={{ default: 'column' }}
31+
>
32+
<h1>{t('Currently selected namespace')}</h1>
33+
<h2>{namespace}</h2>
34+
</Flex>
35+
</CardBody>
36+
</Card>
37+
</PageSection>
38+
</Page>
39+
);
40+
};
41+
42+
export const ExampleNamespacedPage: React.FC<ExampleNamespacedPageProps> = ({ match }) => {
43+
const { ns } = match?.params;
44+
const activeNamespace = ns || 'all-namespaces';
45+
46+
return (
47+
<>
48+
<NamespaceBar />
49+
<NamespacePageContent namespace={activeNamespace} />
50+
</>
51+
);
52+
};
53+
54+
type ExampleNamespacedPageProps = {
55+
match: RMatch<{
56+
ns?: string;
57+
}>;
58+
};

dynamic-demo-plugin/src/i18n.ts

+1
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@
1212
// t('plugin__console-demo-plugin~Test Utilities')
1313
// t('plugin__console-demo-plugin~Foo item')
1414
// t('plugin__console-demo-plugin~Bar item')
15+
// t('plugin__console-demo-plugin~Example Namespaced Page')

dynamic-demo-plugin/yarn.lock

+19-7
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,11 @@
162162
tippy.js "5.1.2"
163163
tslib "^2.0.0"
164164

165+
"@patternfly/react-icons@^4.13.0":
166+
version "4.19.8"
167+
resolved "https://registry.yarnpkg.com/@patternfly/react-icons/-/react-icons-4.19.8.tgz#376cfe136b3acef86fa28081c99e4e88bd13457c"
168+
integrity sha512-JBBcVntRLspe857JnGo8lFaZfy+WOR/IYe2E9W3Rknqm1T8WO6oXpeEnrr5r9bpYDFUa4ttcb/acuQXc1xypxg==
169+
165170
"@patternfly/react-icons@^4.72.3":
166171
version "4.72.3"
167172
resolved "https://registry.yarnpkg.com/@patternfly/react-icons/-/react-icons-4.72.3.tgz#5886755a2b516d49d97ed3bdc88609d9b3c4fc2a"
@@ -177,7 +182,7 @@
177182
resolved "https://registry.yarnpkg.com/@patternfly/react-styles/-/react-styles-4.71.3.tgz#4f1cf4624a675751f035dc3bfa4cb3c6ca48e43b"
178183
integrity sha512-JpMBIrJfco3JwK9KbJvjr+tKZidVhbkGrQT7GyWbYAwZ2bOmCmeCPJYc0xhAWcvNumn9a7AhYzAWPJVlQQue3g==
179184

180-
"@patternfly/react-styles@^4.85.7":
185+
"@patternfly/react-styles@^4.12.4", "@patternfly/react-styles@^4.85.7":
181186
version "4.85.7"
182187
resolved "https://registry.yarnpkg.com/@patternfly/react-styles/-/react-styles-4.85.7.tgz#93afa64c81cf74f7fa050fb787f02348113d62a6"
183188
integrity sha512-XSa8Loaouj1XEmbJmEeURXxKu5ub1VCRV0yN5YOnRo7j7XI4Yw9QarSHODzhkquI3AhkD0dPyMOaefz4P6lJKw==
@@ -194,16 +199,16 @@
194199
lodash "^4.17.19"
195200
tslib "^2.0.0"
196201

202+
"@patternfly/react-tokens@^4.14.0", "@patternfly/react-tokens@^4.87.7":
203+
version "4.87.7"
204+
resolved "https://registry.yarnpkg.com/@patternfly/react-tokens/-/react-tokens-4.87.7.tgz#f96de3d2469b23ba86ead36bf8bac4ae9e7e0559"
205+
integrity sha512-07A7Ya4zIAYyYn3mOCG82wMC3/Y8mtTw95a//Onu/H0oDPMJ5oT7Vd14YN7pHexCAtWvc36Mp46iZ1osIQ7yVQ==
206+
197207
"@patternfly/react-tokens@^4.73.3":
198208
version "4.73.3"
199209
resolved "https://registry.yarnpkg.com/@patternfly/react-tokens/-/react-tokens-4.73.3.tgz#dae690220c25c242d2c45ec571e46d8cdcc7de13"
200210
integrity sha512-WyEcV9jiMZzscQMBhlDkypHw9qg0wbX7r/fe8HcWws+jnYWGVjwUdnr18ktI9aw/h/oQS46sirf8xbNTlIiQFg==
201211

202-
"@patternfly/react-tokens@^4.87.7":
203-
version "4.87.7"
204-
resolved "https://registry.yarnpkg.com/@patternfly/react-tokens/-/react-tokens-4.87.7.tgz#f96de3d2469b23ba86ead36bf8bac4ae9e7e0559"
205-
integrity sha512-07A7Ya4zIAYyYn3mOCG82wMC3/Y8mtTw95a//Onu/H0oDPMJ5oT7Vd14YN7pHexCAtWvc36Mp46iZ1osIQ7yVQ==
206-
207212
"@types/eslint-scope@^3.7.3":
208213
version "3.7.3"
209214
resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.3.tgz#125b88504b61e3c8bc6f870882003253005c3224"
@@ -1408,6 +1413,13 @@ flush-write-stream@^1.0.2:
14081413
inherits "^2.0.3"
14091414
readable-stream "^2.3.6"
14101415

1416+
1417+
version "6.2.2"
1418+
resolved "https://registry.yarnpkg.com/focus-trap/-/focus-trap-6.2.2.tgz#0e6f391415b0697c99da932702dedd13084fa131"
1419+
integrity sha512-qWovH9+LGoKqREvJaTCzJyO0hphQYGz+ap5Hc4NqXHNhZBdxCi5uBPPcaOUw66fHmzXLVwvETLvFgpwPILqKpg==
1420+
dependencies:
1421+
tabbable "^5.1.4"
1422+
14111423
14121424
version "6.9.2"
14131425
resolved "https://registry.yarnpkg.com/focus-trap/-/focus-trap-6.9.2.tgz#a9ef72847869bd2cbf62cb930aaf8e138fef1ca9"
@@ -3437,7 +3449,7 @@ symlink-or-copy@^1.1.8, symlink-or-copy@^1.2.0, symlink-or-copy@^1.3.1:
34373449
version "1.3.1"
34383450
resolved "https://registry.yarnpkg.com/symlink-or-copy/-/symlink-or-copy-1.3.1.tgz#9506dd64d8e98fa21dcbf4018d1eab23e77f71fe"
34393451

3440-
tabbable@^5.3.2:
3452+
tabbable@^5.1.4, tabbable@^5.3.2:
34413453
version "5.3.3"
34423454
resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-5.3.3.tgz#aac0ff88c73b22d6c3c5a50b1586310006b47fbf"
34433455
integrity sha512-QD9qKY3StfbZqWOPLp0++pOrAVb/HbUi5xCc8cUo4XjP19808oaMiDzn0leBY5mCespIBM0CIZePzZjgzR83kA==

frontend/packages/console-dynamic-plugin-sdk/docs/api.md

+44-3
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,10 @@
6060
58. [`Timestamp`](#timestamp)
6161
59. [`useModal`](#usemodal)
6262
60. [`ActionServiceProvider`](#actionserviceprovider)
63-
61. [DEPRECATED] [`PerspectiveContext`](#perspectivecontext)
64-
62. [DEPRECATED] [`useAccessReviewAllowed`](#useaccessreviewallowed)
65-
63. [DEPRECATED] [`useSafetyFirst`](#usesafetyfirst)
63+
61. [`NamespaceBar`](#namespacebar)
64+
62. [DEPRECATED] [`PerspectiveContext`](#perspectivecontext)
65+
63. [DEPRECATED] [`useAccessReviewAllowed`](#useaccessreviewallowed)
66+
64. [DEPRECATED] [`useSafetyFirst`](#usesafetyfirst)
6667

6768
---
6869

@@ -2077,6 +2078,46 @@ Component that allows to receive contributions from other plugins for the `conso
20772078

20782079

20792080

2081+
---
2082+
2083+
## `NamespaceBar`
2084+
2085+
### Summary
2086+
2087+
A component that renders a horizontal toolbar with a namespace dropdown menu in the leftmost position. Additional components can be passed in as children and will be rendered to the right of the namespace dropdown. This component is designed to be used at the top of the page. It should be used on pages where the user needs to be able to change the active namespace, such as on pages with k8s resources.
2088+
2089+
2090+
2091+
### Example
2092+
2093+
2094+
```tsx
2095+
const logNamespaceChange = (namespace) => console.log(`New namespace: ${namespace}`);
2096+
2097+
...
2098+
2099+
<NamespaceBar onNamespaceChange={logNamespaceChange}>
2100+
<NamespaceBarApplicationSelector />
2101+
</NamespaceBar>
2102+
<Page>
2103+
2104+
...
2105+
```
2106+
2107+
2108+
2109+
2110+
2111+
### Parameters
2112+
2113+
| Parameter Name | Description |
2114+
| -------------- | ----------- |
2115+
| `onNamespaceChange` | (optional) A function that is executed when a namespace option is selected. It accepts the new namespace in the form of a string as its only argument. The active namespace is updated automatically when an option is selected, but additional logic can be applied via this function. When the namespace is changed, the namespace parameter in the URL will be changed from the previous namespace to the newly selected namespace. |
2116+
| `isDisabled` | (optional) A boolean flag that disables the namespace dropdown if set to true. This option only applies to the namespace dropdown and has no effect on child components. |
2117+
| `children` | (optional) Additional elements to be rendered inside the toolbar to the right of the namespace dropdown. |
2118+
2119+
2120+
20802121
---
20812122

20822123
## `PerspectiveContext`

frontend/packages/console-dynamic-plugin-sdk/src/api/dynamic-core-api.ts

+23
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
ResourceEventStreamProps,
2727
UsePrometheusPoll,
2828
TimestampProps,
29+
NamespaceBarProps,
2930
} from '../extensions/console-types';
3031
import { StatusPopupSectionProps, StatusPopupItemProps } from '../extensions/dashboard-types';
3132

@@ -669,3 +670,25 @@ export { useModal } from '../app/modal-support/useModal';
669670
*/
670671
export const ActionServiceProvider: React.FC<ActionServiceProviderProps> = require('@console/shared/src/components/actions/ActionServiceProvider')
671672
.default;
673+
674+
/**
675+
* A component that renders a horizontal toolbar with a namespace dropdown menu in the leftmost position. Additional components can be passed in as children and will be rendered to the right of the namespace dropdown. This component is designed to be used at the top of the page. It should be used on pages where the user needs to be able to change the active namespace, such as on pages with k8s resources.
676+
* @param {function} onNamespaceChange - (optional) A function that is executed when a namespace option is selected. It accepts the new namespace in the form of a string as its only argument. The active namespace is updated automatically when an option is selected, but additional logic can be applied via this function. When the namespace is changed, the namespace parameter in the URL will be changed from the previous namespace to the newly selected namespace.
677+
* @param {boolean} isDisabled - (optional) A boolean flag that disables the namespace dropdown if set to true. This option only applies to the namespace dropdown and has no effect on child components.
678+
* @param {React.ReactNode} children - (optional) Additional elements to be rendered inside the toolbar to the right of the namespace dropdown.
679+
* @example
680+
* ```tsx
681+
* const logNamespaceChange = (namespace) => console.log(`New namespace: ${namespace}`);
682+
*
683+
* ...
684+
*
685+
* <NamespaceBar onNamespaceChange={logNamespaceChange}>
686+
* <NamespaceBarApplicationSelector />
687+
* </NamespaceBar>
688+
* <Page>
689+
*
690+
* ...
691+
* ```
692+
*/
693+
export const NamespaceBar: React.FC<NamespaceBarProps> = require('@console/internal/components/namespace-bar')
694+
.NamespaceBar;

frontend/packages/console-dynamic-plugin-sdk/src/extensions/console-types.ts

+6
Original file line numberDiff line numberDiff line change
@@ -643,3 +643,9 @@ export type TimestampProps = {
643643
omitSuffix?: boolean;
644644
className?: string;
645645
};
646+
647+
export type NamespaceBarProps = {
648+
onNamespaceChange?: (namespace: string) => void;
649+
isDisabled?: boolean;
650+
children?: React.ReactNode;
651+
};

frontend/packages/dev-console/src/components/NamespacedPage.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as React from 'react';
22
import * as cx from 'classnames';
3-
import { NamespaceBar } from '@console/internal/components/namespace';
3+
import { NamespaceBar } from '@console/internal/components/namespace-bar';
44
import NamespaceBarApplicationSelector from '@console/topology/src/components/dropdowns/NamespaceBarApplicationSelector';
55

66
import './NamespacedPage.scss';
@@ -30,7 +30,7 @@ const NamespacedPage: React.FC<NamespacedPageProps> = ({
3030
}) => (
3131
<div className="odc-namespaced-page">
3232
<NamespaceBar
33-
disabled={disabled}
33+
isDisabled={disabled}
3434
onNamespaceChange={onNamespaceChange}
3535
hideProjects={hideProjects}
3636
>

frontend/packages/knative-plugin/src/components/eventing/EventingListPage.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as React from 'react';
22
import { useTranslation } from 'react-i18next';
33
import { match as Rmatch } from 'react-router-dom';
4-
import { NamespaceBar } from '@console/internal/components/namespace';
4+
import { NamespaceBar } from '@console/internal/components/namespace-bar';
55
import { Page } from '@console/internal/components/utils';
66
import { MenuActions, MultiTabListPage } from '@console/shared';
77
import { EventingBrokerModel } from '../../models';

frontend/packages/knative-plugin/src/components/eventing/__tests__/EventingListPage.spec.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as React from 'react';
22
import { shallow, ShallowWrapper } from 'enzyme';
3-
import { NamespaceBar } from '@console/internal/components/namespace';
3+
import { NamespaceBar } from '@console/internal/components/namespace-bar';
44
import { MultiTabListPage } from '@console/shared';
55
import EventingListPage from '../EventingListPage';
66

frontend/packages/knative-plugin/src/components/overview/serving-list/ServingListsPage.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as React from 'react';
22
import { useTranslation } from 'react-i18next';
33
import { match as Rmatch } from 'react-router-dom';
4-
import { NamespaceBar } from '@console/internal/components/namespace';
4+
import { NamespaceBar } from '@console/internal/components/namespace-bar';
55
import { Page } from '@console/internal/components/utils';
66
import { referenceForModel } from '@console/internal/module/k8s';
77
import { MenuActions, MultiTabListPage } from '@console/shared';

frontend/packages/knative-plugin/src/components/overview/serving-list/__tests__/ServingListPage.spec.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as React from 'react';
22
import { shallow, ShallowWrapper } from 'enzyme';
3-
import { NamespaceBar } from '@console/internal/components/namespace';
3+
import { NamespaceBar } from '@console/internal/components/namespace-bar';
44
import { MultiTabListPage } from '@console/shared';
55
import { RevisionModel } from '../../../../models';
66
import ServingListPage from '../ServingListsPage';

frontend/public/components/app-contents.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { ErrorBoundaryPage } from '@console/shared/src/components/error';
1515
import { connectToFlags } from '../reducers/connectToFlags';
1616
import { flagPending, FlagsObject } from '../reducers/features';
1717
import { GlobalNotifications } from './global-notifications';
18-
import { NamespaceBar } from './namespace';
18+
import { NamespaceBar } from './namespace-bar';
1919
import { SearchPage } from './search';
2020
import { ResourceDetailsPage, ResourceListPage } from './resource-list';
2121
import { AsyncComponent, LoadingBox } from './utils';

0 commit comments

Comments
 (0)