@openshift-assisted/ui-lib 2.39.4 → 2.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/@types/cim/components/InfraEnv/InfraTableToolbar.d.ts.map +1 -1
- package/build/@types/cim/components/helpers/toAssisted.d.ts.map +1 -1
- package/build/@types/cim/index.d.ts +1 -0
- package/build/@types/cim/index.d.ts.map +1 -1
- package/build/@types/common/api/assisted-service/ClustersAPI.d.ts +1 -0
- package/build/@types/common/api/assisted-service/ClustersAPI.d.ts.map +1 -1
- package/build/@types/common/components/clusterDetail/ClusterCredentials.d.ts.map +1 -1
- package/build/@types/common/components/clusterWizard/ClusterWizardStep.d.ts.map +1 -1
- package/build/@types/common/components/operators/operatorSpecs.d.ts.map +1 -1
- package/build/@types/common/components/ui/ClusterEventsToolbar.d.ts.map +1 -1
- package/build/@types/common/components/ui/WizardFooter.d.ts +1 -0
- package/build/@types/common/components/ui/WizardFooter.d.ts.map +1 -1
- package/build/@types/common/components/ui/WizardNavItem.d.ts +1 -1
- package/build/@types/common/components/ui/WizardNavItem.d.ts.map +1 -1
- package/build/@types/common/components/ui/formik/MultiSelectField.d.ts.map +1 -1
- package/build/@types/common/components/ui/formik/types.d.ts +2 -2
- package/build/@types/common/components/ui/formik/types.d.ts.map +1 -1
- package/build/@types/common/components/ui/utils.d.ts +1 -1
- package/build/@types/common/components/ui/utils.d.ts.map +1 -1
- package/build/@types/common/config/constants.d.ts.map +1 -1
- package/build/@types/common/config/docs_links.d.ts +1 -0
- package/build/@types/common/config/docs_links.d.ts.map +1 -1
- package/build/@types/common/index.d.ts +0 -3
- package/build/@types/common/index.d.ts.map +1 -1
- package/build/@types/ocm/components/clusterConfiguration/networkConfiguration/NetworkConfigurationForm.d.ts.map +1 -1
- package/build/@types/ocm/components/clusterConfiguration/operators/bundleSpecs.d.ts.map +1 -1
- package/build/@types/ocm/components/clusterDetail/ClusterDetailStatusMessages.d.ts.map +1 -1
- package/build/@types/ocm/components/clusterDetail/ClusterDetailsButtonGroup.d.ts +1 -0
- package/build/@types/ocm/components/clusterDetail/ClusterDetailsButtonGroup.d.ts.map +1 -1
- package/build/@types/ocm/components/clusterWizard/CredentialsDownload.d.ts +7 -0
- package/build/@types/ocm/components/clusterWizard/CredentialsDownload.d.ts.map +1 -0
- package/build/@types/ocm/components/clusterWizard/OperatorsBundle.d.ts.map +1 -1
- package/build/@types/ocm/components/clusterWizard/wizardTransition.d.ts +1 -1
- package/build/@types/ocm/components/clusterWizard/wizardTransition.d.ts.map +1 -1
- package/build/@types/ocm/components/clusters/ClustersListToolbar.d.ts.map +1 -1
- package/build/cjs/cim/components/InfraEnv/InfraTableToolbar.js +12 -12
- package/build/cjs/cim/components/InfraEnv/InfraTableToolbar.js.map +1 -1
- package/build/cjs/cim/components/helpers/toAssisted.js +3 -5
- package/build/cjs/cim/components/helpers/toAssisted.js.map +1 -1
- package/build/cjs/cim/components/helpers/versions.js +1 -1
- package/build/cjs/cim/components/helpers/versions.js.map +1 -1
- package/build/cjs/cim/index.js +1 -0
- package/build/cjs/cim/index.js.map +1 -1
- package/build/cjs/common/api/assisted-service/ClustersAPI.js +5 -0
- package/build/cjs/common/api/assisted-service/ClustersAPI.js.map +1 -1
- package/build/cjs/common/components/clusterDetail/ClusterCredentials.js +1 -1
- package/build/cjs/common/components/clusterDetail/ClusterCredentials.js.map +1 -1
- package/build/cjs/common/components/clusterWizard/ClusterWizardStep.js +2 -4
- package/build/cjs/common/components/clusterWizard/ClusterWizardStep.js.map +1 -1
- package/build/cjs/common/components/operators/operatorSpecs.js +2 -2
- package/build/cjs/common/components/operators/operatorSpecs.js.map +1 -1
- package/build/cjs/common/components/ui/ClusterEventsToolbar.js +18 -10
- package/build/cjs/common/components/ui/ClusterEventsToolbar.js.map +1 -1
- package/build/cjs/common/components/ui/WizardFooter.js +2 -2
- package/build/cjs/common/components/ui/WizardFooter.js.map +1 -1
- package/build/cjs/common/components/ui/WizardNavItem.js +2 -2
- package/build/cjs/common/components/ui/WizardNavItem.js.map +1 -1
- package/build/cjs/common/components/ui/formik/MultiSelectField.js +26 -28
- package/build/cjs/common/components/ui/formik/MultiSelectField.js.map +1 -1
- package/build/cjs/common/components/ui/utils.js +1 -1
- package/build/cjs/common/components/ui/utils.js.map +1 -1
- package/build/cjs/common/config/constants.js +1 -0
- package/build/cjs/common/config/constants.js.map +1 -1
- package/build/cjs/common/config/docs_links.js +2 -1
- package/build/cjs/common/config/docs_links.js.map +1 -1
- package/build/cjs/common/index.js +0 -3
- package/build/cjs/common/index.js.map +1 -1
- package/build/cjs/ocm/components/AddHosts/day2Wizard/Day2Wizard.js +2 -2
- package/build/cjs/ocm/components/AddHosts/day2Wizard/Day2Wizard.js.map +1 -1
- package/build/cjs/ocm/components/AddHosts/day2Wizard/Day2WizardNav.js +5 -5
- package/build/cjs/ocm/components/AddHosts/day2Wizard/Day2WizardNav.js.map +1 -1
- package/build/cjs/ocm/components/clusterConfiguration/networkConfiguration/NetworkConfigurationForm.js +23 -1
- package/build/cjs/ocm/components/clusterConfiguration/networkConfiguration/NetworkConfigurationForm.js.map +1 -1
- package/build/cjs/ocm/components/clusterConfiguration/operators/bundleSpecs.js +4 -18
- package/build/cjs/ocm/components/clusterConfiguration/operators/bundleSpecs.js.map +1 -1
- package/build/cjs/ocm/components/clusterDetail/ClusterDetailStatusMessages.js +16 -14
- package/build/cjs/ocm/components/clusterDetail/ClusterDetailStatusMessages.js.map +1 -1
- package/build/cjs/ocm/components/clusterDetail/ClusterDetailsButtonGroup.js +1 -0
- package/build/cjs/ocm/components/clusterDetail/ClusterDetailsButtonGroup.js.map +1 -1
- package/build/cjs/ocm/components/clusterWizard/ClusterWizard.js +3 -3
- package/build/cjs/ocm/components/clusterWizard/ClusterWizard.js.map +1 -1
- package/build/cjs/ocm/components/clusterWizard/ClusterWizardContextProvider.js +1 -1
- package/build/cjs/ocm/components/clusterWizard/ClusterWizardContextProvider.js.map +1 -1
- package/build/cjs/ocm/components/clusterWizard/ClusterWizardNavigation.js +5 -5
- package/build/cjs/ocm/components/clusterWizard/ClusterWizardNavigation.js.map +1 -1
- package/build/cjs/ocm/components/clusterWizard/CredentialsDownload.js +62 -0
- package/build/cjs/ocm/components/clusterWizard/CredentialsDownload.js.map +1 -0
- package/build/cjs/ocm/components/clusterWizard/OperatorsBundle.js +1 -1
- package/build/cjs/ocm/components/clusterWizard/OperatorsBundle.js.map +1 -1
- package/build/cjs/ocm/components/clusterWizard/constants.js +1 -1
- package/build/cjs/ocm/components/clusterWizard/constants.js.map +1 -1
- package/build/cjs/ocm/components/clusterWizard/wizardTransition.js +3 -3
- package/build/cjs/ocm/components/clusterWizard/wizardTransition.js.map +1 -1
- package/build/cjs/ocm/components/clusters/ClustersListToolbar.js +3 -3
- package/build/cjs/ocm/components/clusters/ClustersListToolbar.js.map +1 -1
- package/lib/cim/components/InfraEnv/InfraTableToolbar.tsx +40 -28
- package/lib/cim/components/helpers/toAssisted.ts +3 -4
- package/lib/cim/components/helpers/versions.ts +1 -1
- package/lib/cim/index.ts +1 -0
- package/lib/common/api/assisted-service/ClustersAPI.ts +6 -0
- package/lib/common/components/clusterDetail/ClusterCredentials.tsx +12 -2
- package/lib/common/components/clusterWizard/ClusterWizardStep.tsx +2 -4
- package/lib/common/components/operators/operatorSpecs.tsx +3 -2
- package/lib/common/components/ui/ClusterEventsToolbar.tsx +78 -45
- package/lib/common/components/ui/WizardFooter.tsx +3 -0
- package/lib/common/components/ui/WizardNavItem.tsx +1 -1
- package/lib/common/components/ui/formik/MultiSelectField.tsx +98 -58
- package/lib/common/components/ui/formik/types.ts +2 -2
- package/lib/common/components/ui/utils.ts +4 -2
- package/lib/common/config/constants.ts +1 -0
- package/lib/common/config/docs_links.ts +3 -0
- package/lib/common/index.ts +0 -4
- package/lib/ocm/components/AddHosts/day2Wizard/Day2Wizard.tsx +1 -1
- package/lib/ocm/components/AddHosts/day2Wizard/Day2WizardNav.tsx +5 -5
- package/lib/ocm/components/clusterConfiguration/networkConfiguration/NetworkConfigurationForm.tsx +29 -1
- package/lib/ocm/components/clusterConfiguration/operators/bundleSpecs.tsx +5 -25
- package/lib/ocm/components/clusterDetail/ClusterDetailStatusMessages.tsx +18 -19
- package/lib/ocm/components/clusterDetail/ClusterDetailsButtonGroup.tsx +2 -0
- package/lib/ocm/components/clusterWizard/ClusterWizard.tsx +3 -3
- package/lib/ocm/components/clusterWizard/ClusterWizardContextProvider.tsx +1 -1
- package/lib/ocm/components/clusterWizard/ClusterWizardNavigation.tsx +5 -5
- package/lib/ocm/components/clusterWizard/CredentialsDownload.tsx +105 -0
- package/lib/ocm/components/clusterWizard/OperatorsBundle.tsx +1 -0
- package/lib/ocm/components/clusterWizard/constants.ts +1 -1
- package/lib/ocm/components/clusterWizard/wizardTransition.ts +4 -4
- package/lib/ocm/components/clusters/ClustersListToolbar.tsx +39 -19
- package/package.json +3 -3
- /package/build/cjs/{common/styles.css → ocm/components/clusterDetail/ClusterDetailsButtonGroup.css} +0 -0
- /package/lib/{common/styles.css → ocm/components/clusterDetail/ClusterDetailsButtonGroup.css} +0 -0
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Badge,
|
|
3
|
+
Dropdown,
|
|
4
|
+
DropdownGroup,
|
|
5
|
+
DropdownItem,
|
|
3
6
|
Grid,
|
|
4
7
|
GridItem,
|
|
8
|
+
MenuToggle,
|
|
9
|
+
MenuToggleElement,
|
|
5
10
|
SearchInput,
|
|
6
11
|
Split,
|
|
7
12
|
SplitItem,
|
|
8
13
|
ToolbarFilter,
|
|
9
14
|
ToolbarItem,
|
|
10
15
|
} from '@patternfly/react-core';
|
|
11
|
-
import {
|
|
12
|
-
Select,
|
|
13
|
-
SelectGroup,
|
|
14
|
-
SelectOption,
|
|
15
|
-
SelectVariant,
|
|
16
|
-
} from '@patternfly/react-core/deprecated';
|
|
17
16
|
import { FilterIcon } from '@patternfly/react-icons/dist/js/icons/filter-icon';
|
|
18
17
|
import * as React from 'react';
|
|
19
18
|
import { HostStatus, HostStatusDef } from '../../../common/components/hosts/types';
|
|
@@ -94,6 +93,19 @@ const InfraTableToolbar: React.FC<InfraTableToolbarProps> = ({
|
|
|
94
93
|
const filterStatuses = React.useMemo(() => getStatusesForFilter(agentStatuses), [agentStatuses]);
|
|
95
94
|
const categoryLabels = getCategoryLabels(t);
|
|
96
95
|
|
|
96
|
+
const onStatusFilterToggle = () => setStatusFilterOpen(!statusFilterOpen);
|
|
97
|
+
const onStatusFilterSelect = (
|
|
98
|
+
e?: React.MouseEvent<Element, MouseEvent>,
|
|
99
|
+
value?: string | number,
|
|
100
|
+
) => {
|
|
101
|
+
if (!statusFilter?.includes(value as string)) {
|
|
102
|
+
const newItems = (statusFilter ? [...statusFilter, value] : [value]) as string[];
|
|
103
|
+
setStatusFilter(newItems);
|
|
104
|
+
} else {
|
|
105
|
+
setStatusFilter(statusFilter?.filter((f) => f !== value));
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
97
109
|
return (
|
|
98
110
|
<TableToolbar
|
|
99
111
|
selectedIDs={selectedHostIDs || []}
|
|
@@ -118,34 +130,34 @@ const InfraTableToolbar: React.FC<InfraTableToolbarProps> = ({
|
|
|
118
130
|
deleteChipGroup={() => setStatusFilter([])}
|
|
119
131
|
categoryName="Status"
|
|
120
132
|
>
|
|
121
|
-
<
|
|
122
|
-
variant={SelectVariant.checkbox}
|
|
123
|
-
aria-label={t('ai:Status')}
|
|
124
|
-
onToggle={(_event, value) => setStatusFilterOpen(value)}
|
|
125
|
-
onSelect={(e, value) => {
|
|
126
|
-
// eslint-disable-next-line
|
|
127
|
-
if ((e.target as any).checked) {
|
|
128
|
-
const newItems = (statusFilter ? [...statusFilter, value] : [value]) as string[];
|
|
129
|
-
setStatusFilter(newItems);
|
|
130
|
-
} else {
|
|
131
|
-
setStatusFilter(statusFilter?.filter((f) => f !== value));
|
|
132
|
-
}
|
|
133
|
-
}}
|
|
134
|
-
selections={statusFilter}
|
|
133
|
+
<Dropdown
|
|
135
134
|
isOpen={statusFilterOpen}
|
|
136
|
-
|
|
137
|
-
|
|
135
|
+
onSelect={onStatusFilterSelect}
|
|
136
|
+
onOpenChange={onStatusFilterToggle}
|
|
137
|
+
toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
|
|
138
|
+
<MenuToggle
|
|
139
|
+
ref={toggleRef}
|
|
140
|
+
isFullWidth
|
|
141
|
+
onClick={onStatusFilterToggle}
|
|
142
|
+
isExpanded={statusFilterOpen}
|
|
143
|
+
icon={<FilterIcon />}
|
|
144
|
+
>
|
|
145
|
+
{t('ai:Status')}
|
|
146
|
+
</MenuToggle>
|
|
147
|
+
)}
|
|
148
|
+
shouldFocusToggleOnSelect
|
|
138
149
|
>
|
|
139
150
|
{[
|
|
140
151
|
<Grid key="statuses" hasGutter className="table-toolbar__dropdown">
|
|
141
152
|
{Object.keys(filterStatuses).map((category) => (
|
|
142
153
|
<GridItem key={category} span={4}>
|
|
143
|
-
<
|
|
154
|
+
<DropdownGroup label={categoryLabels[category as HostStatusDef['category']]}>
|
|
144
155
|
{Object.keys(filterStatuses[category]).map((label) => (
|
|
145
|
-
<
|
|
156
|
+
<DropdownItem
|
|
157
|
+
hasCheckbox
|
|
146
158
|
key={label}
|
|
147
159
|
value={label}
|
|
148
|
-
|
|
160
|
+
isSelected={statusFilter?.includes(label)}
|
|
149
161
|
>
|
|
150
162
|
<Split hasGutter>
|
|
151
163
|
<SplitItem>{label}</SplitItem>
|
|
@@ -153,14 +165,14 @@ const InfraTableToolbar: React.FC<InfraTableToolbarProps> = ({
|
|
|
153
165
|
<Badge isRead>{statusCount[label] || 0}</Badge>
|
|
154
166
|
</SplitItem>
|
|
155
167
|
</Split>
|
|
156
|
-
</
|
|
168
|
+
</DropdownItem>
|
|
157
169
|
))}
|
|
158
|
-
</
|
|
170
|
+
</DropdownGroup>
|
|
159
171
|
</GridItem>
|
|
160
172
|
))}
|
|
161
173
|
</Grid>,
|
|
162
174
|
]}
|
|
163
|
-
</
|
|
175
|
+
</Dropdown>
|
|
164
176
|
</ToolbarFilter>
|
|
165
177
|
</ToolbarItem>
|
|
166
178
|
</TableToolbar>
|
|
@@ -76,10 +76,9 @@ export const getAIHosts = (
|
|
|
76
76
|
const restBmhs =
|
|
77
77
|
infraEnv && bmhs
|
|
78
78
|
? bmhs
|
|
79
|
-
?.filter((h) =>
|
|
80
|
-
|
|
81
|
-
getInfraEnvNameOfAgent(h) === infraEnv.metadata?.name &&
|
|
82
|
-
h.metadata?.name
|
|
79
|
+
?.filter((h) => h.metadata?.namespace === infraEnv.metadata?.namespace)
|
|
80
|
+
.filter((h) =>
|
|
81
|
+
getInfraEnvNameOfAgent(h) === infraEnv.metadata?.name && h.metadata?.name
|
|
83
82
|
? !bmhAgents.includes(h.metadata.name)
|
|
84
83
|
: true,
|
|
85
84
|
)
|
|
@@ -11,7 +11,7 @@ import { OpenshiftVersion } from '@openshift-assisted/types/assisted-installer-s
|
|
|
11
11
|
import { getMajorMinorVersion } from '../../../common/utils';
|
|
12
12
|
|
|
13
13
|
export const getVersionFromReleaseImage = (releaseImage = '') => {
|
|
14
|
-
const match = /.+:(
|
|
14
|
+
const match = /.+:(\d+\.\d+(?:\.\d+)?(?:-\w+)?)/gm.exec(releaseImage);
|
|
15
15
|
if (match && match.length > 1 && match[1]) {
|
|
16
16
|
return match[1];
|
|
17
17
|
}
|
package/lib/cim/index.ts
CHANGED
|
@@ -239,6 +239,12 @@ const ClustersAPI = {
|
|
|
239
239
|
params,
|
|
240
240
|
);
|
|
241
241
|
},
|
|
242
|
+
|
|
243
|
+
updateInstallConfig(clusterId: Cluster['id'], config: string) {
|
|
244
|
+
return client.patch(`${ClustersAPI.makeBaseURI(clusterId)}/install-config`, config, {
|
|
245
|
+
headers: { 'Content-Type': 'application/json' },
|
|
246
|
+
});
|
|
247
|
+
},
|
|
242
248
|
};
|
|
243
249
|
|
|
244
250
|
export default ClustersAPI;
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
GridItem,
|
|
4
|
+
ClipboardCopy,
|
|
5
|
+
clipboardCopyFunc,
|
|
6
|
+
Button,
|
|
7
|
+
Alert,
|
|
8
|
+
TextInput,
|
|
9
|
+
} from '@patternfly/react-core';
|
|
3
10
|
import { Credentials, Cluster } from '@openshift-assisted/types/assisted-installer-service';
|
|
4
11
|
import { LoadingState, ErrorState } from '../../components/ui/uiState';
|
|
5
12
|
import { DetailList, DetailItem } from '../../components/ui/DetailList';
|
|
@@ -98,7 +105,10 @@ const ClusterCredentials: React.FC<ClusterCredentialsProps> = ({
|
|
|
98
105
|
)}
|
|
99
106
|
{credentials.username && (
|
|
100
107
|
<>
|
|
101
|
-
<DetailItem
|
|
108
|
+
<DetailItem
|
|
109
|
+
title={t('ai:Username')}
|
|
110
|
+
value={<TextInput value={credentials.username} readOnlyVariant="default" />}
|
|
111
|
+
/>
|
|
102
112
|
<DetailItem
|
|
103
113
|
title={t('ai:Password')}
|
|
104
114
|
value={
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { WizardBody
|
|
2
|
+
import { WizardBody } from '@patternfly/react-core';
|
|
3
3
|
import { css } from '@patternfly/react-styles';
|
|
4
4
|
|
|
5
5
|
import './ClusterWizardStep.css';
|
|
@@ -14,13 +14,11 @@ export const ClusterWizardStep = ({
|
|
|
14
14
|
footer,
|
|
15
15
|
children,
|
|
16
16
|
}: React.PropsWithChildren<ClusterWizardStepProps>) => {
|
|
17
|
-
// activeStep is required, but we're not passing it. Using the cast to avoid TS error
|
|
18
|
-
const activeStep = undefined as unknown as WizardBodyProps['activeStep'];
|
|
19
17
|
return (
|
|
20
18
|
<div className={css('pf-v5-c-wizard__outer-wrap', 'cluster-wizard-step')}>
|
|
21
19
|
<div className={css('pf-v5-c-wizard__inner-wrap')}>
|
|
22
20
|
{navigation}
|
|
23
|
-
<WizardBody aria-labelledby="step-id"
|
|
21
|
+
<WizardBody aria-labelledby="step-id" hasNoPadding={false}>
|
|
24
22
|
{children}
|
|
25
23
|
</WizardBody>
|
|
26
24
|
</div>
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
AUTHORINO_OPERATOR_LINK,
|
|
31
31
|
CNV_LINK,
|
|
32
32
|
FENCE_AGENTS_REMEDIATION_LINK,
|
|
33
|
+
getKubeDeschedulerLink,
|
|
33
34
|
getLsoLink,
|
|
34
35
|
getLvmsDocsLink,
|
|
35
36
|
getMceDocsLink,
|
|
@@ -154,10 +155,10 @@ export const getOperatorSpecs = (useLVMS?: boolean): { [key: string]: OperatorSp
|
|
|
154
155
|
[OPERATOR_NAME_KUBE_DESCHEDULER]: {
|
|
155
156
|
title: 'Kube Descheduler',
|
|
156
157
|
featureId: 'KUBE_DESCHEDULER',
|
|
157
|
-
Description: () => (
|
|
158
|
+
Description: ({ openshiftVersion }) => (
|
|
158
159
|
<>
|
|
159
160
|
Evicts pods to reschedule them onto more suitable nodes.{' '}
|
|
160
|
-
<ExternalLink href={
|
|
161
|
+
<ExternalLink href={getKubeDeschedulerLink(openshiftVersion)}>Learn more</ExternalLink>
|
|
161
162
|
</>
|
|
162
163
|
),
|
|
163
164
|
notStandalone: true,
|
|
@@ -16,8 +16,12 @@ import {
|
|
|
16
16
|
Badge,
|
|
17
17
|
TextInputTypes,
|
|
18
18
|
InputGroupItem,
|
|
19
|
+
Dropdown,
|
|
20
|
+
DropdownItem,
|
|
21
|
+
DropdownList,
|
|
22
|
+
MenuToggle,
|
|
23
|
+
MenuToggleElement,
|
|
19
24
|
} from '@patternfly/react-core';
|
|
20
|
-
import { Select, SelectOption, SelectProps } from '@patternfly/react-core/deprecated';
|
|
21
25
|
import { SearchIcon } from '@patternfly/react-icons/dist/js/icons/search-icon';
|
|
22
26
|
import { FilterIcon } from '@patternfly/react-icons/dist/js/icons/filter-icon';
|
|
23
27
|
import type { ClusterEventsFiltersType } from '../../types';
|
|
@@ -137,7 +141,7 @@ const ClusterEventsToolbar = ({
|
|
|
137
141
|
setFilters(nextFilters);
|
|
138
142
|
};
|
|
139
143
|
|
|
140
|
-
const onHostToggle
|
|
144
|
+
const onHostToggle = () => setHostExpanded(!isHostExpanded);
|
|
141
145
|
const onHostSelect = (value: string, isChecked: boolean) => {
|
|
142
146
|
switch (value) {
|
|
143
147
|
case DELETED_HOSTS:
|
|
@@ -157,7 +161,7 @@ const ClusterEventsToolbar = ({
|
|
|
157
161
|
}
|
|
158
162
|
};
|
|
159
163
|
|
|
160
|
-
const onSeverityToggle
|
|
164
|
+
const onSeverityToggle = () => setSeverityExpanded(!isSeverityExpanded);
|
|
161
165
|
const onSeveritySelect = (value: string, isChecked: boolean) => {
|
|
162
166
|
onSelect('severities', isChecked, value);
|
|
163
167
|
};
|
|
@@ -227,41 +231,56 @@ const ClusterEventsToolbar = ({
|
|
|
227
231
|
}
|
|
228
232
|
deleteChipGroup={onDeleteChipGroup}
|
|
229
233
|
>
|
|
230
|
-
<
|
|
231
|
-
variant="checkbox"
|
|
232
|
-
aria-label="hosts"
|
|
233
|
-
toggleId="cluster-events-hosts-dropdown-button"
|
|
234
|
-
onToggle={onHostToggle}
|
|
235
|
-
onSelect={(e, value) => onHostSelect(value as string, isSelectEventChecked(e))}
|
|
236
|
-
selections={getSelections()}
|
|
237
|
-
customBadgeText={hostChips.length}
|
|
234
|
+
<Dropdown
|
|
238
235
|
isOpen={isHostExpanded}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
236
|
+
onSelect={(e, value) => onHostSelect(value as string, isSelectEventChecked(e))}
|
|
237
|
+
onOpenChange={onHostToggle}
|
|
238
|
+
toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
|
|
239
|
+
<MenuToggle
|
|
240
|
+
id="cluster-events-hosts-dropdown-button"
|
|
241
|
+
ref={toggleRef}
|
|
242
|
+
isFullWidth
|
|
243
|
+
onClick={onHostToggle}
|
|
244
|
+
isExpanded={isHostExpanded}
|
|
245
|
+
badge={hostChips.length && <Badge isRead>{hostChips.length}</Badge>}
|
|
246
|
+
>
|
|
247
|
+
<Placeholder text="Hosts" />
|
|
248
|
+
</MenuToggle>
|
|
249
|
+
)}
|
|
250
|
+
shouldFocusToggleOnSelect
|
|
242
251
|
>
|
|
243
|
-
|
|
244
|
-
<
|
|
245
|
-
|
|
252
|
+
<DropdownList>
|
|
253
|
+
<DropdownItem
|
|
254
|
+
id={`checkbox-${CLUSTER_LEVEL}`}
|
|
255
|
+
hasCheckbox
|
|
256
|
+
isSelected={getSelections().includes(CLUSTER_LEVEL)}
|
|
246
257
|
key={CLUSTER_LEVEL}
|
|
247
258
|
value={CLUSTER_LEVEL}
|
|
248
259
|
>
|
|
249
260
|
{t('ai:Cluster-level events')}
|
|
250
|
-
</
|
|
251
|
-
<
|
|
252
|
-
|
|
261
|
+
</DropdownItem>
|
|
262
|
+
<DropdownItem
|
|
263
|
+
id={`checkbox-${DELETED_HOSTS}`}
|
|
264
|
+
hasCheckbox
|
|
265
|
+
isSelected={getSelections().includes(DELETED_HOSTS)}
|
|
253
266
|
key={DELETED_HOSTS}
|
|
254
267
|
value={DELETED_HOSTS}
|
|
255
268
|
>
|
|
256
269
|
{t('ai:Deleted hosts')}
|
|
257
|
-
</
|
|
258
|
-
...sortedHosts.map((host) => (
|
|
259
|
-
<
|
|
270
|
+
</DropdownItem>
|
|
271
|
+
{...sortedHosts.map((host) => (
|
|
272
|
+
<DropdownItem
|
|
273
|
+
id={`checkbox-${host.id}`}
|
|
274
|
+
hasCheckbox
|
|
275
|
+
isSelected={getSelections().includes(host.id)}
|
|
276
|
+
key={host.id}
|
|
277
|
+
value={host.id}
|
|
278
|
+
>
|
|
260
279
|
{host.hostname}
|
|
261
|
-
</
|
|
262
|
-
))
|
|
263
|
-
|
|
264
|
-
</
|
|
280
|
+
</DropdownItem>
|
|
281
|
+
))}
|
|
282
|
+
</DropdownList>
|
|
283
|
+
</Dropdown>
|
|
265
284
|
</CustomToolbarFilter>
|
|
266
285
|
)}
|
|
267
286
|
|
|
@@ -278,28 +297,42 @@ const ClusterEventsToolbar = ({
|
|
|
278
297
|
deleteChipGroup={onDeleteChipGroup}
|
|
279
298
|
categoryName="Severity"
|
|
280
299
|
>
|
|
281
|
-
<
|
|
282
|
-
|
|
283
|
-
aria-label="Severity"
|
|
284
|
-
toggleId="cluster-events-severity-dropdown-button"
|
|
285
|
-
onToggle={onSeverityToggle}
|
|
300
|
+
<Dropdown
|
|
301
|
+
isOpen={isSeverityExpanded}
|
|
286
302
|
onSelect={(event, value) =>
|
|
287
303
|
onSeveritySelect(value as string, isSelectEventChecked(event))
|
|
288
304
|
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
305
|
+
onOpenChange={onSeverityToggle}
|
|
306
|
+
toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
|
|
307
|
+
<MenuToggle
|
|
308
|
+
id="cluster-events-severity-dropdown-button"
|
|
309
|
+
ref={toggleRef}
|
|
310
|
+
isFullWidth
|
|
311
|
+
onClick={onSeverityToggle}
|
|
312
|
+
isExpanded={isSeverityExpanded}
|
|
313
|
+
badge={
|
|
314
|
+
filters.severities?.length && <Badge isRead>{filters.severities.length}</Badge>
|
|
315
|
+
}
|
|
298
316
|
>
|
|
299
|
-
|
|
300
|
-
</
|
|
301
|
-
)
|
|
302
|
-
|
|
317
|
+
<Placeholder text="Severity" />
|
|
318
|
+
</MenuToggle>
|
|
319
|
+
)}
|
|
320
|
+
shouldFocusToggleOnSelect
|
|
321
|
+
>
|
|
322
|
+
<DropdownList>
|
|
323
|
+
{EVENT_SEVERITIES.map((severity) => (
|
|
324
|
+
<DropdownItem
|
|
325
|
+
data-testid={`${severity}-filter-option`}
|
|
326
|
+
hasCheckbox
|
|
327
|
+
isSelected={filters.severities?.includes(severity)}
|
|
328
|
+
key={severity}
|
|
329
|
+
value={severity}
|
|
330
|
+
>
|
|
331
|
+
{capitalize(severity)} <Badge isRead>{severityCounts[severity]}</Badge>
|
|
332
|
+
</DropdownItem>
|
|
333
|
+
))}
|
|
334
|
+
</DropdownList>
|
|
335
|
+
</Dropdown>
|
|
303
336
|
</ToolbarFilter>
|
|
304
337
|
|
|
305
338
|
<ToolbarItem>
|
|
@@ -26,6 +26,7 @@ export type WizardFooterGenericProps = {
|
|
|
26
26
|
isSubmitting?: boolean;
|
|
27
27
|
submittingText?: string;
|
|
28
28
|
nextButtonText?: string;
|
|
29
|
+
isNextButtonLoading?: boolean;
|
|
29
30
|
};
|
|
30
31
|
|
|
31
32
|
type WizardFooterProps = WizardFooterGenericProps & {
|
|
@@ -51,6 +52,7 @@ export const WizardFooter: React.FC<WizardFooterProps> = ({
|
|
|
51
52
|
nextButtonText,
|
|
52
53
|
cluster,
|
|
53
54
|
onFetchEvents,
|
|
55
|
+
isNextButtonLoading,
|
|
54
56
|
}) => {
|
|
55
57
|
const { t } = useTranslation();
|
|
56
58
|
submittingText = submittingText || t('ai:Saving changes...');
|
|
@@ -68,6 +70,7 @@ export const WizardFooter: React.FC<WizardFooterProps> = ({
|
|
|
68
70
|
name="next"
|
|
69
71
|
onClick={onNext}
|
|
70
72
|
isDisabled={isNextDisabled}
|
|
73
|
+
isLoading={isNextButtonLoading}
|
|
71
74
|
>
|
|
72
75
|
{nextButtonText || t('ai:Next')}
|
|
73
76
|
</Button>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { PropsWithChildren, ReactNode } from 'react';
|
|
2
|
-
import { WizardNavItem, WizardNavItemProps } from '@patternfly/react-core
|
|
2
|
+
import { WizardNavItem, WizardNavItemProps } from '@patternfly/react-core';
|
|
3
3
|
import { ExclamationCircleIcon } from '@patternfly/react-icons/dist/js/icons/exclamation-circle-icon';
|
|
4
4
|
import UiIcon from './UiIcon';
|
|
5
5
|
|
|
@@ -1,19 +1,27 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { useField } from 'formik';
|
|
3
|
-
import Fuse from 'fuse.js';
|
|
4
|
-
import { FormGroup, FormHelperText, HelperText, HelperTextItem } from '@patternfly/react-core';
|
|
5
3
|
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
4
|
+
FormGroup,
|
|
5
|
+
FormHelperText,
|
|
6
|
+
HelperText,
|
|
7
|
+
HelperTextItem,
|
|
8
|
+
Dropdown,
|
|
9
|
+
DropdownItem,
|
|
10
|
+
DropdownList,
|
|
11
|
+
MenuToggle,
|
|
12
|
+
MenuToggleElement,
|
|
13
|
+
TextInputGroup,
|
|
14
|
+
TextInputGroupMain,
|
|
15
|
+
TextInputGroupUtilities,
|
|
16
|
+
Button,
|
|
17
|
+
LabelGroup,
|
|
18
|
+
Label,
|
|
19
|
+
} from '@patternfly/react-core';
|
|
20
|
+
import { MultiSelectFieldProps } from './types';
|
|
14
21
|
import { getFieldId } from './utils';
|
|
15
|
-
import { useTranslation } from '../../../hooks/use-translation-wrapper';
|
|
16
22
|
import ExclamationCircleIcon from '@patternfly/react-icons/dist/js/icons/exclamation-circle-icon';
|
|
23
|
+
import TimesIcon from '@patternfly/react-icons/dist/js/icons/times-icon';
|
|
24
|
+
import { useTranslation } from '../../../hooks/use-translation-wrapper';
|
|
17
25
|
|
|
18
26
|
// Field value is a string[]
|
|
19
27
|
const MultiSelectField: React.FC<MultiSelectFieldProps> = ({
|
|
@@ -29,21 +37,24 @@ const MultiSelectField: React.FC<MultiSelectFieldProps> = ({
|
|
|
29
37
|
...props
|
|
30
38
|
}) => {
|
|
31
39
|
const [isOpen, setOpen] = React.useState(false);
|
|
40
|
+
const [textValue, setTextValue] = React.useState('');
|
|
32
41
|
const [field, { touched, error }, { setValue }] = useField<string[]>(props.name);
|
|
33
42
|
const fieldId = getFieldId(props.name, 'multiinput', idPostfix);
|
|
34
43
|
const isValid = !(touched && error);
|
|
35
44
|
const errorMessage = !isValid ? error : '';
|
|
36
45
|
const hText = getHelperText ? getHelperText(field.value?.join(',') || '') : helperText;
|
|
46
|
+
const { t } = useTranslation();
|
|
37
47
|
|
|
38
48
|
const onToggle = (isOpen: boolean) => setOpen(isOpen);
|
|
39
49
|
const onClearSelection = () => {
|
|
40
50
|
// onChange && onChange(event);
|
|
41
51
|
setValue([]);
|
|
52
|
+
setTextValue('');
|
|
42
53
|
onChange && onChange([]);
|
|
43
54
|
setOpen(false);
|
|
44
55
|
};
|
|
45
56
|
|
|
46
|
-
const onSelect
|
|
57
|
+
const onSelect = (selection: string) => {
|
|
47
58
|
// already selected
|
|
48
59
|
const selected = field.value;
|
|
49
60
|
|
|
@@ -53,7 +64,7 @@ const MultiSelectField: React.FC<MultiSelectFieldProps> = ({
|
|
|
53
64
|
selection as {
|
|
54
65
|
/* TypeScript hack, debug hint: created as part of "selections" array below */ value?: string;
|
|
55
66
|
}
|
|
56
|
-
).value ||
|
|
67
|
+
).value || selection;
|
|
57
68
|
|
|
58
69
|
let newValue: string[];
|
|
59
70
|
if (selected.includes(selectionValue)) {
|
|
@@ -65,61 +76,90 @@ const MultiSelectField: React.FC<MultiSelectFieldProps> = ({
|
|
|
65
76
|
onChange && onChange(newValue);
|
|
66
77
|
};
|
|
67
78
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
79
|
+
const deleteChip = (chip: string) => {
|
|
80
|
+
const newValue = field.value.filter((val) => val !== chip);
|
|
81
|
+
setValue(newValue);
|
|
82
|
+
setTextValue('');
|
|
83
|
+
onChange && onChange(newValue);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const filteredOptions = options.filter((option) => {
|
|
87
|
+
const value = option.value as string;
|
|
88
|
+
return (
|
|
89
|
+
option.displayName.toLowerCase().includes(textValue.toLowerCase()) &&
|
|
90
|
+
!(field.value || []).includes(value.toString())
|
|
91
|
+
);
|
|
78
92
|
});
|
|
79
93
|
|
|
80
|
-
const children =
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
<
|
|
94
|
+
const children = filteredOptions.map((option) => {
|
|
95
|
+
const value = option.value as string;
|
|
96
|
+
return (
|
|
97
|
+
<DropdownItem key={option.id} id={option.id} value={value}>
|
|
84
98
|
{option.displayName}
|
|
85
|
-
</
|
|
86
|
-
)
|
|
87
|
-
|
|
88
|
-
const fuse = new Fuse(options, {
|
|
89
|
-
ignoreLocation: true,
|
|
90
|
-
keys: ['displayName'],
|
|
99
|
+
</DropdownItem>
|
|
100
|
+
);
|
|
91
101
|
});
|
|
92
|
-
const { t } = useTranslation();
|
|
93
102
|
|
|
94
103
|
return (
|
|
95
104
|
<FormGroup fieldId={fieldId} label={label} isRequired={isRequired} labelIcon={labelIcon}>
|
|
96
|
-
<
|
|
97
|
-
{...field}
|
|
98
|
-
{...props}
|
|
105
|
+
<Dropdown
|
|
99
106
|
id={fieldId}
|
|
100
|
-
variant={SelectVariant.typeaheadMulti}
|
|
101
|
-
typeAheadAriaLabel={t('ai:Select a state')}
|
|
102
|
-
validated={isValid ? 'default' : 'error'}
|
|
103
|
-
aria-describedby={`${fieldId}-helper`}
|
|
104
|
-
isCreatable={false}
|
|
105
|
-
placeholderText={placeholderText}
|
|
106
107
|
isOpen={isOpen}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
108
|
+
onSelect={(event, value) => onSelect(value as string)}
|
|
109
|
+
onOpenChange={onToggle}
|
|
110
|
+
toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
|
|
111
|
+
<MenuToggle
|
|
112
|
+
ref={toggleRef}
|
|
113
|
+
isFullWidth
|
|
114
|
+
onClick={() => onToggle(!isOpen)}
|
|
115
|
+
isExpanded={isOpen}
|
|
116
|
+
variant="typeahead"
|
|
117
|
+
>
|
|
118
|
+
<TextInputGroup>
|
|
119
|
+
<LabelGroup>
|
|
120
|
+
{field.value.map((currentChip) => (
|
|
121
|
+
<Label
|
|
122
|
+
key={currentChip}
|
|
123
|
+
variant="outline"
|
|
124
|
+
onClose={() => deleteChip(currentChip)}
|
|
125
|
+
>
|
|
126
|
+
{currentChip}
|
|
127
|
+
</Label>
|
|
128
|
+
))}
|
|
129
|
+
</LabelGroup>
|
|
130
|
+
<TextInputGroupMain
|
|
131
|
+
placeholder={placeholderText}
|
|
132
|
+
onClick={() => onToggle(!isOpen)}
|
|
133
|
+
value={textValue}
|
|
134
|
+
onChange={(event, value) => setTextValue(value)}
|
|
135
|
+
/>
|
|
136
|
+
<TextInputGroupUtilities>
|
|
137
|
+
<Button
|
|
138
|
+
variant="plain"
|
|
139
|
+
onClick={onClearSelection}
|
|
140
|
+
aria-label="Clear button and input"
|
|
141
|
+
icon={<TimesIcon />}
|
|
142
|
+
/>
|
|
143
|
+
</TextInputGroupUtilities>
|
|
144
|
+
</TextInputGroup>
|
|
145
|
+
</MenuToggle>
|
|
146
|
+
)}
|
|
147
|
+
shouldFocusToggleOnSelect
|
|
120
148
|
>
|
|
121
|
-
|
|
122
|
-
|
|
149
|
+
<DropdownList>
|
|
150
|
+
{children.length ? (
|
|
151
|
+
children
|
|
152
|
+
) : (
|
|
153
|
+
<DropdownItem
|
|
154
|
+
key="No options available"
|
|
155
|
+
id="No options available"
|
|
156
|
+
value="No options available"
|
|
157
|
+
>
|
|
158
|
+
{t('ai:No options available')}
|
|
159
|
+
</DropdownItem>
|
|
160
|
+
)}
|
|
161
|
+
</DropdownList>
|
|
162
|
+
</Dropdown>
|
|
123
163
|
{(errorMessage || hText) && (
|
|
124
164
|
<FormHelperText>
|
|
125
165
|
<HelperText>
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
FormSelectProps,
|
|
8
8
|
DropEvent,
|
|
9
9
|
} from '@patternfly/react-core';
|
|
10
|
-
import {
|
|
10
|
+
import { DropdownItemProps } from '@patternfly/react-core';
|
|
11
11
|
import { FieldValidator, FieldHelperProps } from 'formik';
|
|
12
12
|
import { DropzoneProps } from 'react-dropzone';
|
|
13
13
|
import { CodeEditorProps } from '@patternfly/react-code-editor';
|
|
@@ -44,7 +44,7 @@ export interface SelectFieldProps extends FieldProps {
|
|
|
44
44
|
// onBlur?: (event: React.FormEvent<HTMLSelectElement>) => void;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
export type MultiSelectOption =
|
|
47
|
+
export type MultiSelectOption = DropdownItemProps & { id: string; displayName: string };
|
|
48
48
|
|
|
49
49
|
export interface MultiSelectFieldProps extends FieldProps {
|
|
50
50
|
options: MultiSelectOption[];
|