diff --git a/src/components/Clusters/components/AddClusterDialog.js b/src/components/Clusters/components/AddClusterDialog.js index 19bf84562d..bf23a5f039 100644 --- a/src/components/Clusters/components/AddClusterDialog.js +++ b/src/components/Clusters/components/AddClusterDialog.js @@ -27,7 +27,7 @@ export function AddClusterDialog() { return ( setShowWizard(false)} > diff --git a/src/components/Clusters/components/AddClusterWizard.js b/src/components/Clusters/components/AddClusterWizard.js index 7d6578b69b..eac0818225 100644 --- a/src/components/Clusters/components/AddClusterWizard.js +++ b/src/components/Clusters/components/AddClusterWizard.js @@ -49,11 +49,13 @@ export function AddClusterWizard({ kubeconfig, setKubeconfig, config }) { const setIsFormOpen = useSetRecoilState(isFormOpenState); useEffect(() => { - const contentContainer = document - .getElementsByTagName('ui5-wizard')[0] - ?.shadowRoot?.querySelectorAll('.ui5-wiz-content-item-wrapper')[ - selected - 1 - ]; + const wizard = document.getElementsByTagName('ui5-wizard')[0]; + const wizardContent = wizard?.shadowRoot?.querySelector('.ui5-wiz-content'); + + const contentContainer = wizardContent?.querySelectorAll( + '.ui5-wiz-content-item-wrapper', + )[selected - 1]; + if (contentContainer) { contentContainer.style['background-color'] = 'transparent'; contentContainer.style['padding'] = '0'; @@ -166,7 +168,7 @@ export function AddClusterWizard({ kubeconfig, setKubeconfig, config }) { firstStep={true} onCancel={() => setShowWizard(false)} validation={!kubeconfig} - className="cluster-wizard__buttons" + className="cluster-wizard__buttons__sticky" /> @@ -197,7 +199,7 @@ export function AddClusterWizard({ kubeconfig, setKubeconfig, config }) { setSelected={setSelected} onCancel={() => setShowWizard(false)} validation={!authValid} - className="cluster-wizard__buttons" + className="cluster-wizard__buttons__absolute" /> )} @@ -217,14 +219,14 @@ export function AddClusterWizard({ kubeconfig, setKubeconfig, config }) { data-step={!hasAuth || !hasOneContext ? '3' : '2'} >
- + <Title level="H5" style={spacing.sapUiSmallMarginBottom}> {t('clusters.storage.choose-storage.label')} <> <Button id="storageDescriptionOpener" icon="hint" design="Transparent" - style={spacing.sapUiTinyMargin} + style={spacing.sapUiTinyMarginBegin} onClick={() => setShowTitleDescription(true)} /> {createPortal( @@ -248,7 +250,7 @@ export function AddClusterWizard({ kubeconfig, setKubeconfig, config }) { setSelected={setSelected} validation={!storage} onCancel={() => setShowWizard(false)} - className="cluster-wizard__buttons" + className="cluster-wizard__buttons__absolute" /> </div> </WizardStep> @@ -269,7 +271,6 @@ export function AddClusterWizard({ kubeconfig, setKubeconfig, config }) { <ClusterPreview storage={storage} kubeconfig={kubeconfig} - token={hasAuth ? hasKubeconfigAuth(kubeconfig) : null} setSelected={setSelected} hasAuth={hasAuth} /> @@ -284,7 +285,7 @@ export function AddClusterWizard({ kubeconfig, setKubeconfig, config }) { setIsFormOpen({ formOpen: false }); }} validation={!storage} - className="cluster-wizard__buttons" + className="cluster-wizard__buttons__sticky" /> </WizardStep> </Wizard> diff --git a/src/components/Clusters/components/AddClusterWizard.scss b/src/components/Clusters/components/AddClusterWizard.scss index 1a294f9337..5e5f0cc198 100644 --- a/src/components/Clusters/components/AddClusterWizard.scss +++ b/src/components/Clusters/components/AddClusterWizard.scss @@ -1,3 +1,7 @@ +.add-cluster-wizard-dialog::part(content) { + height: 90vh; +} + .add-cluster { &__content-container { background-color: var(--sapGroup_TitleBackground); @@ -11,20 +15,17 @@ } ui5-wizard { - height: 90vh; - min-width: 80vw; + height: 100%; + width: 75vw; .cluster-wizard { - &__buttons { - position: absolute; + @mixin cluster-wizard-buttons-style { + z-index: 100; bottom: 1rem; - left: 0; display: flex; justify-content: flex-end; box-sizing: border-box; - width: calc(100% - 20px); - margin: 0 10px; - padding: 7px; + padding: 0.5rem; border: 1px solid var(--sapGroup_TitleBorderColor); border-radius: var(--sapElement_BorderCornerRadius); background-color: var(--sapGroup_TitleBackground); @@ -34,6 +35,23 @@ ui5-wizard { color-mix(in srgb, var(--sapContent_ShadowColor) 16%, transparent); } + &__buttons { + &__sticky { + position: sticky; + width: calc(100% + 32px); + margin: 0 -16px; + @include cluster-wizard-buttons-style; + } + + &__absolute { + position: absolute; + left: 0; + width: calc(100% - 32px); + margin: 0 16px; + @include cluster-wizard-buttons-style; + } + } + &__token-info, &__storage-preference { color: var(--sapContent_LabelColor); @@ -44,7 +62,6 @@ ui5-wizard { display: flex; flex-flow: column; overflow: auto; - height: calc(90vh - 8rem); .cluster-wizard__auth-form { height: unset; @@ -53,7 +70,7 @@ ui5-wizard { } .resource-form { - padding: 1rem 0; + padding: 0; .form-field { justify-content: start; diff --git a/src/components/Clusters/components/AuthForm.js b/src/components/Clusters/components/AuthForm.js index dfa9a613b2..eebcecc9c8 100644 --- a/src/components/Clusters/components/AuthForm.js +++ b/src/components/Clusters/components/AuthForm.js @@ -9,10 +9,7 @@ import * as Inputs from 'shared/ResourceForm/inputs'; import { getUser, getUserIndex } from '../shared'; import { spacing } from '@ui5/webcomponents-react-base'; - -export const AUTH_FORM_TOKEN = 'Token'; -export const AUTH_FORM_OIDC = 'OIDC'; -export const DEFAULT_SCOPE_VALUE = 'openid'; +import { TextArrayInput } from 'shared/ResourceForm/fields'; const OIDCform = ({ resource, setResource, ...props }) => { const { t } = useTranslation(); @@ -57,11 +54,11 @@ const OIDCform = ({ resource, setResource, ...props }) => { input={Inputs.Text} aria-label="client-secret" /> - <ResourceForm.FormField + <TextArrayInput required - propertyPath="$.scope" - label={t('clusters.wizard.auth.scopes')} - input={Inputs.Text} + defaultOpen + propertyPath="$.scopes" + title={t('clusters.wizard.auth.scopes')} aria-label="scopes" /> </ResourceForm.Wrapper> @@ -147,7 +144,11 @@ export function AuthForm({ <ResourceForm.FormField label={t('clusters.wizard.auth.using-oidc')} input={() => ( - <Switch checked={useOidc} onChange={switchAuthVariant} /> + <Switch + style={spacing.sapUiTinyMarginTop} + checked={useOidc} + onChange={switchAuthVariant} + /> )} className="oidc-switch" /> diff --git a/src/components/Clusters/components/ChooseStorage.js b/src/components/Clusters/components/ChooseStorage.js index 9e6bf1874c..9c90938c68 100644 --- a/src/components/Clusters/components/ChooseStorage.js +++ b/src/components/Clusters/components/ChooseStorage.js @@ -1,5 +1,6 @@ import { FlexBox, RadioButton } from '@ui5/webcomponents-react'; import { useTranslation } from 'react-i18next'; +import { spacing } from '@ui5/webcomponents-react-base'; import './ChooseStorage.scss'; export function ChooseStorage({ storage, setStorage }) { @@ -7,7 +8,10 @@ export function ChooseStorage({ storage, setStorage }) { return ( <> - <p className="cluster-wizard__storage-preference"> + <p + className="cluster-wizard__storage-preference" + style={spacing.sapUiTinyMarginBottom} + > {`${t('clusters.storage.storage-preference')}:`} </p> <FlexBox direction="Column"> diff --git a/src/components/Clusters/components/ClusterPreview.js b/src/components/Clusters/components/ClusterPreview.js index 9e46293aec..6c60cad017 100644 --- a/src/components/Clusters/components/ClusterPreview.js +++ b/src/components/Clusters/components/ClusterPreview.js @@ -3,8 +3,12 @@ import { Button, FlexBox, RadioButton, Title } from '@ui5/webcomponents-react'; import { useTranslation } from 'react-i18next'; import './ClusterPreview.scss'; import { spacing } from '@ui5/webcomponents-react-base'; -import { findInitialValue } from '../views/EditCluster/EditCluster'; +import { + findInitialValue, + findInitialValues, +} from '../views/EditCluster/EditCluster'; import { getUserIndex } from '../shared'; +import { Tokens } from 'shared/components/Tokens'; export function ClusterPreview({ kubeconfig, storage, setSelected, hasAuth }) { const { t } = useTranslation(); @@ -25,7 +29,7 @@ export function ClusterPreview({ kubeconfig, storage, setSelected, hasAuth }) { 'oidc-client-secret', userIndex, ); - const extraScope = findInitialValue( + const extraScopes = findInitialValues( kubeconfig, 'oidc-extra-scope', userIndex, @@ -75,7 +79,7 @@ export function ClusterPreview({ kubeconfig, storage, setSelected, hasAuth }) { <div>{clientSecret}</div> </> )} - {extraScope && ( + {extraScopes && ( <> <p className="cluster-preview__data-header" @@ -86,7 +90,7 @@ export function ClusterPreview({ kubeconfig, storage, setSelected, hasAuth }) { > {t('clusters.labels.scopes')}: </p> - <div>{extraScope}</div> + {<Tokens tokens={extraScopes} />} </> )} </> @@ -112,123 +116,125 @@ export function ClusterPreview({ kubeconfig, storage, setSelected, hasAuth }) { }; return ( - <div className="cluster-preview add-cluster__content-container"> - <Title level="H5" style={spacing.sapUiMediumMarginBottom}> - {t('clusters.wizard.review')} - - {`1. ${t('configuration.title')}`} -

- {t('clusters.name_singular')}: -

-
-
{kubeconfig?.['current-context']}
- -
- {`2. ${t('clusters.wizard.authentication')}`} - -
-
- {authenticationType === 'token' ? : } + {t('clusters.name_singular')}: +

+
+
{kubeconfig?.['current-context']}
+
- -
- {`3. ${t('clusters.wizard.storage')}`} -

- {`${t('clusters.storage.storage-preference')}:`} -

-
- + {authenticationType === 'token' ? : } +
+ +
+ {`3. ${t('clusters.wizard.storage')}`} +

- - - - - + + + + + + +

); diff --git a/src/components/Clusters/components/ClusterPreview.scss b/src/components/Clusters/components/ClusterPreview.scss index 7711785972..f9adae7937 100644 --- a/src/components/Clusters/components/ClusterPreview.scss +++ b/src/components/Clusters/components/ClusterPreview.scss @@ -2,7 +2,8 @@ overflow-y: scroll; overflow-x: hidden; height: 100%; - max-height: calc(90vh - 12rem); + min-height: calc(90vh - 11.85rem); + margin-bottom: 1rem; &__subtitle { padding-bottom: 1rem; diff --git a/src/components/Clusters/components/KubeconfigUpload/KubeconfigFileUpload.js b/src/components/Clusters/components/KubeconfigUpload/KubeconfigFileUpload.js index 2b6a06d271..a844d462c5 100644 --- a/src/components/Clusters/components/KubeconfigUpload/KubeconfigFileUpload.js +++ b/src/components/Clusters/components/KubeconfigUpload/KubeconfigFileUpload.js @@ -24,14 +24,14 @@ export function KubeconfigFileUpload({ onKubeconfigTextAdded }) { return (
- + <Title level="H5" style={spacing.sapUiTinyMarginBottom}> {t('clusters.wizard.kubeconfig')} <> <Button id="descriptionOpener" icon="hint" design="Transparent" - style={spacing.sapUiTinyMargin} + style={spacing.sapUiTinyMarginBegin} onClick={() => { setShowTitleDescription(true); }} diff --git a/src/components/Clusters/components/KubeconfigUpload/KubeconfigUpload.js b/src/components/Clusters/components/KubeconfigUpload/KubeconfigUpload.js index 2a38e58c3f..6350ea2005 100644 --- a/src/components/Clusters/components/KubeconfigUpload/KubeconfigUpload.js +++ b/src/components/Clusters/components/KubeconfigUpload/KubeconfigUpload.js @@ -35,7 +35,10 @@ export function KubeconfigUpload({ kubeconfig, setKubeconfig, formRef }) { return ( <div className="kubeconfig-upload"> - <div className="add-cluster__content-container"> + <div + className="add-cluster__content-container" + style={spacing.sapUiSmallMarginBottom} + > <KubeconfigFileUpload onKubeconfigTextAdded={text => { updateKubeconfig(text); @@ -58,11 +61,7 @@ export function KubeconfigUpload({ kubeconfig, setKubeconfig, formRef }) { yamlHideDisabled /> {error && ( - <MessageStrip - design="Negative" - hideCloseButton - style={spacing.sapUiSmallMarginTop} - > + <MessageStrip design="Negative" hideCloseButton> {t('common.create-form.editor-error', { error })} </MessageStrip> )} diff --git a/src/components/Clusters/components/KubeconfigUpload/KubeconfigUpload.scss b/src/components/Clusters/components/KubeconfigUpload/KubeconfigUpload.scss index ff992e00cc..703b304d31 100644 --- a/src/components/Clusters/components/KubeconfigUpload/KubeconfigUpload.scss +++ b/src/components/Clusters/components/KubeconfigUpload/KubeconfigUpload.scss @@ -1,15 +1,23 @@ .kubeconfig-upload { + border-radius: 12px; display: flex; - flex-flow: column; - flex-grow: 1; - height: calc(90vh - 10rem); + flex-direction: column; + gap: 1rem; + min-height: calc(90vh - 11.85rem); + margin-bottom: 1rem; .editor-label { text-align: center; } .resource-form { - padding: 1rem 0 0 0; + padding: 0; + + .resource-form--panel, + .resource-form--panel::part(content) { + margin: 0 !important; + min-height: unset !important; + } &__wrapper { max-height: calc(90vh - 16rem - 290px); @@ -23,7 +31,6 @@ } &__form { - height: 100% !important; padding-bottom: 0 !important; } } diff --git a/src/components/Clusters/components/oidc-params.ts b/src/components/Clusters/components/oidc-params.ts index 6cf79aa571..087169beb8 100644 --- a/src/components/Clusters/components/oidc-params.ts +++ b/src/components/Clusters/components/oidc-params.ts @@ -4,7 +4,7 @@ const OIDC_PARAM_NAMES = new Map([ ['--oidc-issuer-url', 'issuerUrl'], ['--oidc-client-id', 'clientId'], ['--oidc-client-secret', 'clientSecret'], - ['--oidc-extra-scope', 'scope'], + ['--oidc-extra-scope', 'scopes'], ]); export function parseOIDCparams({ exec: commandData }: KubeconfigOIDCAuth) { @@ -40,8 +40,19 @@ export function parseOIDCparams({ exec: commandData }: KubeconfigOIDCAuth) { if (!OIDC_PARAM_NAMES.has(argKey)) return; const outputKey = OIDC_PARAM_NAMES.get(argKey)!; - if (output[outputKey]) output[outputKey] += ' ' + argValue; - else output[outputKey] = argValue; + if (output[outputKey]) { + if (outputKey === 'scopes') { + output[outputKey].push(argValue); + } else { + output[outputKey] += ' ' + argValue; + } + } else { + if (outputKey === 'scopes') { + output[outputKey] = [argValue]; + } else { + output[outputKey] = argValue; + } + } }); return output; @@ -60,7 +71,7 @@ export function createLoginCommand( issuerUrl: string; clientId: string; clientSecret?: string; - scope: string; + scopes: string[]; }, execRest: object, ): LoginCommand { @@ -74,9 +85,9 @@ export function createLoginCommand( `--oidc-issuer-url=${oidcConfig.issuerUrl || ''}`, `--oidc-client-id=${oidcConfig.clientId || ''}`, `--oidc-client-secret=${oidcConfig.clientSecret || ''}`, - oidcConfig.scope - ? `--oidc-extra-scope=${oidcConfig.scope || ''}` - : `--oidc-extra-scope=openid ${oidcConfig.scope || ''}`, + ...(oidcConfig.scopes?.length + ? oidcConfig.scopes.map(scope => `--oidc-extra-scope=${scope || ''}`) + : [`--oidc-extra-scope=openid`]), '--grant-type=auto', ], }; diff --git a/src/components/Clusters/components/test/oidc-params.test.js b/src/components/Clusters/components/test/oidc-params.test.js index 8ad7eb46e9..5d8d9f4c7d 100644 --- a/src/components/Clusters/components/test/oidc-params.test.js +++ b/src/components/Clusters/components/test/oidc-params.test.js @@ -21,7 +21,7 @@ describe('parseOIDCparams', () => { clientId: 'hasselhoff', clientSecret: 'hasselhoffsecret', issuerUrl: 'https://coastguard.gov.us', - scope: 'peach', + scopes: ['peach'], }); }); @@ -40,11 +40,11 @@ describe('parseOIDCparams', () => { clientId: 'hasselhoff', clientSecret: 'hasselhoff=secret', issuerUrl: 'https://coastguard.gov.us', - scope: 'peach', + scopes: ['peach'], }); }); - it('Concatinates params', () => { + it('Multiple scopes', () => { const input = { exec: { args: [ @@ -55,7 +55,7 @@ describe('parseOIDCparams', () => { }, }; expect(parseOIDCparams(input)).toMatchObject({ - scope: 'peach melon plum', + scopes: ['peach', 'melon', 'plum'], }); }); diff --git a/src/components/Clusters/shared.ts b/src/components/Clusters/shared.ts index bd6b5777e5..7286527314 100644 --- a/src/components/Clusters/shared.ts +++ b/src/components/Clusters/shared.ts @@ -128,7 +128,7 @@ export function hasKubeconfigAuth(kubeconfig: Kubeconfig) { } const oidcData = tryParseOIDCparams(user as KubeconfigOIDCAuth); - if (oidcData?.issuerUrl && oidcData?.clientId && oidcData?.scope) { + if (oidcData?.issuerUrl && oidcData?.clientId && oidcData?.scopes) { return oidcData; } } catch (e) { diff --git a/src/components/Clusters/views/EditCluster/AuthenticationDropdown.js b/src/components/Clusters/views/EditCluster/AuthenticationDropdown.js index 70f150d4fe..1f0fb9ae6c 100644 --- a/src/components/Clusters/views/EditCluster/AuthenticationDropdown.js +++ b/src/components/Clusters/views/EditCluster/AuthenticationDropdown.js @@ -14,7 +14,6 @@ export function AuthenticationTypeDropdown({ type, setType }) { options={options} selectedKey={type} onSelect={(_, selected) => setType(selected.key)} - fullWidth required /> ); diff --git a/src/components/Clusters/views/EditCluster/EditCluster.js b/src/components/Clusters/views/EditCluster/EditCluster.js index 5417ebc78a..cd362609e6 100644 --- a/src/components/Clusters/views/EditCluster/EditCluster.js +++ b/src/components/Clusters/views/EditCluster/EditCluster.js @@ -5,7 +5,7 @@ import { useTranslation } from 'react-i18next'; import { useSetRecoilState } from 'recoil'; import { ResourceForm } from 'shared/ResourceForm'; -import { K8sNameField } from 'shared/ResourceForm/fields'; +import { K8sNameField, TextArrayInput } from 'shared/ResourceForm/fields'; import { ChooseStorage } from 'components/Clusters/components/ChooseStorage'; import { ErrorBoundary } from 'shared/components/ErrorBoundary/ErrorBoundary'; import { useNotification } from 'shared/contexts/NotificationContext'; @@ -19,11 +19,29 @@ import { addCluster, getContext, deleteCluster } from '../../shared'; import { spacing } from '@ui5/webcomponents-react-base'; import { getUserIndex } from '../../shared'; +export const findInitialValues = (kubeconfig, id, userIndex = 0) => { + const elementsWithId = + kubeconfig?.users?.[userIndex]?.user?.exec?.args.filter(el => + el?.includes(id), + ) || []; + const regex = new RegExp(`${id}=(?<value>.*)`); + const values = []; + + for (const element of elementsWithId) { + const match = regex.exec(element); + if (match?.groups?.value) { + values.push(match.groups.value); + } + } + + return values; +}; + export const findInitialValue = (kubeconfig, id, userIndex = 0) => { if (kubeconfig?.users?.[userIndex]?.user?.exec?.args) { const elementWithId = kubeconfig?.users?.[ userIndex - ]?.user?.exec?.args.find(el => el.includes(id)); + ]?.user?.exec?.args.find(el => el?.includes(id)); const regex = new RegExp(`${id}=(?<value>.*)`); return regex.exec(elementWithId)?.groups?.value || ''; } @@ -56,7 +74,7 @@ export const ClusterDataForm = ({ 'oidc-client-secret', userIndex, ); - const scopes = findInitialValue(kubeconfig, 'oidc-extra-scope', userIndex); + const scopes = findInitialValues(kubeconfig, 'oidc-extra-scope', userIndex); useEffect(() => { setAuthenticationType( @@ -89,9 +107,9 @@ export const ClusterDataForm = ({ `--oidc-issuer-url=${config.issuerUrl}`, `--oidc-client-id=${config.clientId}`, `--oidc-client-secret=${config.clientSecret}`, - findInitialValue(kubeconfig, 'oidc-extra-scope', userIndex) - ? `--oidc-extra-scope=${config.scopes}` - : `--oidc-extra-scope=openid ${config.scopes}`, + ...(config.scopes?.length + ? config.scopes.map(scope => `--oidc-extra-scope=${scope || ''}`) + : [`--oidc-extra-scope=openid`]), '--grant-type=auto', ], }; @@ -127,10 +145,10 @@ export const ClusterDataForm = ({ createOIDC('clientSecret', val); }} /> - <ResourceForm.FormField - label={t('clusters.labels.scopes')} - input={Inputs.Text} + <TextArrayInput required + defaultOpen + title={t('clusters.labels.scopes')} value={scopes} setValue={val => { createOIDC('scopes', val); diff --git a/src/resources/RoleBindings/RoleForm.js b/src/resources/RoleBindings/RoleForm.js index 2325c27076..0aa5c0527a 100644 --- a/src/resources/RoleBindings/RoleForm.js +++ b/src/resources/RoleBindings/RoleForm.js @@ -61,31 +61,28 @@ export const RoleForm = ({ label={t('role-bindings.create-modal.role')} propertyPath="$.roleRef.name" input={props => ( - <div className="bsl-col-md--11"> - <ComboBox - id="role" - aria-label="Role Combobox" - disabled={props.disabled || !options?.length} - filter="Contains" - inputRef={props.inputRef} - placeholder={t('common.messages.type-to-select', { - value: t( - binding.roleRef?.kind === 'ClusterRole' - ? 'cluster-roles.name_singular' - : 'roles.name_singular', - ), - })} - value={ - options.find(o => o.key === props.value)?.text ?? props.value - } - onChange={event => onChange(event, props)} - onInput={event => onChange(event, props)} - > - {options.map(option => ( - <ComboBoxItem id={option.key} text={option.text} /> - ))} - </ComboBox> - </div> + <ComboBox + className="bsl-col-md--12" + id="role" + aria-label="Role Combobox" + disabled={props.disabled || !options?.length} + filter="Contains" + inputRef={props.inputRef} + placeholder={t('common.messages.type-to-select', { + value: t( + binding.roleRef?.kind === 'ClusterRole' + ? 'cluster-roles.name_singular' + : 'roles.name_singular', + ), + })} + value={options.find(o => o.key === props.value)?.text ?? props.value} + onChange={event => onChange(event, props)} + onInput={event => onChange(event, props)} + > + {options.map(option => ( + <ComboBoxItem id={option.key} text={option.text} /> + ))} + </ComboBox> )} /> ); diff --git a/src/resources/RoleBindings/SubjectForm.js b/src/resources/RoleBindings/SubjectForm.js index 87380e3158..463f252b9c 100644 --- a/src/resources/RoleBindings/SubjectForm.js +++ b/src/resources/RoleBindings/SubjectForm.js @@ -65,7 +65,7 @@ export function SingleSubjectForm({ tooltipContent={t('role-bindings.create-modal.tooltips.kind')} label={t('role-bindings.create-modal.kind')} input={() => ( - <Select onChange={onChange} className="bsl-col-md--11"> + <Select onChange={onChange} className="bsl-col-md--12"> {SUBJECT_KINDS.map(kind => ( <Option value={kind} selected={(subject.kind || '') === kind}> {kind} diff --git a/src/shared/ResourceForm/components/FormField.js b/src/shared/ResourceForm/components/FormField.js index b8ae44fbe4..97c49f4777 100644 --- a/src/shared/ResourceForm/components/FormField.js +++ b/src/shared/ResourceForm/components/FormField.js @@ -49,25 +49,23 @@ export function FormField({ )} </div> </FlexBox> - <FlexBox wrap="Wrap" alignItems="Center"> - <div className="bsl-col-md--12"> - <FlexBox wrap="Wrap" alignItems="Center"> - {messageStrip - ? messageStrip - : input({ - updatesOnInput, - required, - disabled, - className: 'full-width', - ...inputProps, - })} - {inputInfo && ( - <Label wrappingType="Normal" style={{ marginTop: '5px' }}> - {inputInfoLink} - </Label> - )} - </FlexBox> - </div> + <FlexBox wrap="Wrap" alignItems="Center" className="full-width"> + <FlexBox wrap="Wrap" alignItems="Center" className="bsl-col-md--12"> + {messageStrip + ? messageStrip + : input({ + updatesOnInput, + required, + disabled, + className: 'full-width', + ...inputProps, + })} + {inputInfo && ( + <Label wrappingType="Normal" style={{ marginTop: '5px' }}> + {inputInfoLink} + </Label> + )} + </FlexBox> </FlexBox> </FlexBox> ); diff --git a/src/shared/components/Dropdown/Dropdown.js b/src/shared/components/Dropdown/Dropdown.js index 7e3eca275c..e6de3522f4 100644 --- a/src/shared/components/Dropdown/Dropdown.js +++ b/src/shared/components/Dropdown/Dropdown.js @@ -60,7 +60,11 @@ export function Dropdown({ ); return ( - <FlexBox className="flexbox-gap" justifyContent="Center" direction="Column"> + <FlexBox + className="flexbox-gap full-width" + justifyContent="Center" + direction="Column" + > {label && <Label forElement={id}>{label}</Label>} {inlineHelp ? ( <Tooltip content={inlineHelp}>{combobox}</Tooltip> diff --git a/src/state/authDataAtom.ts b/src/state/authDataAtom.ts index 395f71f06f..81535a6a0f 100644 --- a/src/state/authDataAtom.ts +++ b/src/state/authDataAtom.ts @@ -40,9 +40,11 @@ export function createUserManager( userCredentials: KubeconfigOIDCAuth, redirectPath = '', ) { - const { issuerUrl, clientId, clientSecret, scope } = parseOIDCparams( + const { issuerUrl, clientId, clientSecret, scopes } = parseOIDCparams( userCredentials, ); + const uniqueScopes = new Set(scopes || []); + uniqueScopes.delete('openid'); return new UserManager({ redirect_uri: window.location.origin + redirectPath, @@ -51,7 +53,7 @@ export function createUserManager( client_id: clientId, authority: issuerUrl, client_secret: clientSecret, - scope: scope || 'openid', + scope: `openid ${[...uniqueScopes].join(' ')}`, response_type: 'code', response_mode: 'query', });