Skip to content
This repository has been archived by the owner on Dec 13, 2022. It is now read-only.

Commit

Permalink
[Backport/need review] fix(UI): Fix layout for Safari and form valida…
Browse files Browse the repository at this point in the history
…tion (#11440)

* fix(UI): Fix layout for Safari and form validation (#11373)

* Fix form validation

* Fix padlock layout for safari

* Update centreon-frontend

* Remove debug variable

* Fix test

* Fix page respsoniveness

* Rename variable

* update deps

* Fix package-lock

* Fix package-lock

* Add debug statement for debian

* Install nodejs rather npm

* Attempt fix

* Attempt to fix nodejs installation

* add sudo

* Fix redoc-cli usage

* Try to fix permission on npm

* Fix

* Fix permission

* Fix permission (please work)

* Fix source

* Stop using npx because.....

* Allow legacy-peer-deps

* Remove nodejs installation

* Fix image to pull for debian 11
  • Loading branch information
Thebarda authored Jul 29, 2022
1 parent 9b61eb7 commit 8d64b02
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 98 deletions.
2 changes: 1 addition & 1 deletion Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ try {
checkout scm
}
sh 'rm -rf *.deb'
sh 'docker run -i --entrypoint /src/centreon/ci/scripts/centreon-deb-package.sh -w "/src" -v "$PWD:/src" -e DISTRIB="bullseye" -e VERSION=$VERSION -e RELEASE=$RELEASE registry.centreon.com/centreon-debian11-dependencies:22.04'
sh 'docker run -i --entrypoint /src/centreon/ci/scripts/centreon-deb-package.sh -w "/src" -v "$PWD:/src" -e DISTRIB="bullseye" -e VERSION=$VERSION -e RELEASE=$RELEASE registry.centreon.com/mon-build-dependencies-22.04:debian11'
stash name: 'Debian11', includes: '*.deb'
archiveArtifacts artifacts: "*"
sh 'rm -rf *.deb'
Expand Down
2 changes: 1 addition & 1 deletion ci/debian/rules
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ override_dh_clean:

override_dh_auto_build:
composer install --no-dev --optimize-autoloader -n
npm ci
npm ci --legacy-peer-deps
npm run build
find . -type f | \
grep -v debian/extra/centreon-web/centreon-macroreplacement.txt | \
Expand Down
6 changes: 3 additions & 3 deletions ci/scripts/centreon-deb-package.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ for i in lang/* ; do
done
rm -rf lang

# Install npm dependency
apt-get update
apt install -y npm
# Generate API documentation.
npm i -g redoc-cli
redoc-cli build --options.hideDownloadButton=true doc/API/centreon-api-v${MAJOR_VERSION}.yaml -o ../centreon-api-v${MAJOR_VERSION}.html

# Make tar with original content
cd ..
Expand Down
18 changes: 2 additions & 16 deletions www/front_src/src/Authentication/Openid/Form/inputs.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { equals, isEmpty, isNil, not, path, prop } from 'ramda';
import { equals, isEmpty, not, prop } from 'ramda';
import { FormikValues } from 'formik';

import {
Expand Down Expand Up @@ -32,7 +32,7 @@ import {
labelDeleteRelation,
labelAuthorizationKey,
} from '../translatedLabels';
import { AuthenticationType, AuthorizationRule } from '../models';
import { AuthenticationType } from '../models';
import { InputProps, InputType } from '../../FormInputs/models';
import {
labelActivation,
Expand Down Expand Up @@ -249,20 +249,6 @@ export const inputs: Array<InputProps> = [
claimValue: '',
},
deleteLabel: labelDeleteRelation,
getRequired: ({ values, index }): boolean => {
const tableValues = prop('authorizationRules', values);

const rowValues = path<AuthorizationRule>(
['authorizationRules', index],
values,
);

return isNil(prop('contactGroup', values))
? not(isNil(rowValues))
: isNil(tableValues) ||
isEmpty(rowValues?.claimValue) ||
isNil(rowValues?.accessGroup);
},
},
label: labelDefineRelationAuthorizationValueAndAccessGroup,
type: InputType.FieldsTable,
Expand Down
41 changes: 2 additions & 39 deletions www/front_src/src/Authentication/Openid/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -445,11 +445,10 @@ describe('Openid configuration form', () => {
accessGroupsEndpoint,
labelAccessGroup,
'Access Group 2',
1,
],
])(
'updates the %p field when an option is selected from the retrieved options',
async (_, retrievedOptions, endpoint, label, value, index = 0) => {
async (_, retrievedOptions, endpoint, label, value) => {
mockGetRequestsWithNoAuthorizationConfiguration();
renderOpenidConfigurationForm();

Expand Down Expand Up @@ -484,7 +483,7 @@ describe('Openid configuration form', () => {
userEvent.click(screen.getByText(value));

await waitFor(() => {
expect(screen.getAllByLabelText(label)[index]).toHaveValue(value);
expect(screen.getAllByLabelText(label)[0]).toHaveValue(value);
});
},
);
Expand All @@ -508,40 +507,4 @@ describe('Openid configuration form', () => {
);
});
});

it('displays the "Authorization value" and "Access group" fields as required when the "Contact group" field is filled', async () => {
mockGetRequestsWithNoAuthorizationConfiguration();
mockedAxios.get.mockResolvedValueOnce({
data: retrievedContactGroups,
});

renderOpenidConfigurationForm();

await waitFor(() => {
expect(screen.getByLabelText(labelContactGroup)).toBeInTheDocument();
});

userEvent.click(screen.getByLabelText(labelContactGroup));

await waitFor(() => {
expect(mockedAxios.get).toHaveBeenCalledWith(
`${contactGroupsEndpoint}?page=1&sort_by=${encodeURIComponent(
'{"name":"ASC"}',
)}`,
cancelTokenRequestParam,
);
});

await waitFor(() => {
expect(screen.getByText('Contact Group 1')).toBeInTheDocument();
});

userEvent.click(screen.getByText('Contact Group 1'));

await waitFor(() => {
expect(screen.getByLabelText(labelAuthorizationValue)).toHaveAttribute(
'required',
);
});
});
});
11 changes: 1 addition & 10 deletions www/front_src/src/Authentication/Openid/useValidationSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
labelRequired,
labelInvalidURL,
labelInvalidIPAddress,
labelAtLeastOneAuthorizationIsRequired,
} from './translatedLabels';

const IPAddressRegexp = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(\/\d{1,3})?$/;
Expand All @@ -29,15 +28,7 @@ const useValidationSchema = (): Yup.SchemaOf<OpenidConfiguration> => {
return Yup.object({
authenticationType: Yup.string().required(t(labelRequired)),
authorizationEndpoint: Yup.string().nullable().required(t(labelRequired)),
authorizationRules: Yup.array()
.of(authorizationSchema)
.when('contactGroup', (contactGroup, schema) => {
return contactGroup
? schema
.min(1, t(labelAtLeastOneAuthorizationIsRequired))
.required(t(labelRequired))
: schema.nullable();
}),
authorizationRules: Yup.array().of(authorizationSchema),
autoImport: Yup.boolean().required(t(labelRequired)),
baseUrl: Yup.string()
.matches(urlRegexp, t(labelInvalidURL))
Expand Down
74 changes: 46 additions & 28 deletions www/front_src/src/Authentication/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { useMemo } from 'react';
import { useEffect, useMemo, useRef, useState } from 'react';

import { useTranslation } from 'react-i18next';
import { useAtomValue } from 'jotai';
import { useUpdateAtom } from 'jotai/utils';
import { Responsive } from '@visx/visx';

import { Box, Container, Paper, Tab } from '@mui/material';
import { TabContext, TabList, TabPanel } from '@mui/lab';
Expand Down Expand Up @@ -90,35 +89,39 @@ const useStyles = makeStyles((theme) => ({
formContainer: {
display: 'grid',
gridTemplateColumns: '1.2fr 0.6fr',
height: '100%',
overflowY: 'auto',
justifyItems: 'center',
padding: theme.spacing(3),
},
image: {
height: '200px',
opacity: 0.5,
padding: theme.spacing(0, 5),
position: 'sticky',
top: 0,
width: '200px',
},
panel: {
height: '80%',
padding: 0,
},
paper: {
boxShadow: theme.shadows[3],
height: '100%',
},
tabList: {
boxShadow: theme.shadows[2],
},
}));

const marginBottomHeight = 88;
const scrollMargin = 8;

const Authentication = (): JSX.Element => {
const classes = useStyles();
const { t } = useTranslation();

const formContainerRef = useRef<HTMLDivElement | null>(null);

const [windowHeight, setWindowHeight] = useState(window.innerHeight);
const [clientRect, setClientRect] = useState<DOMRect | null>(null);

const appliedTab = useAtomValue(appliedTabAtom);
const { themeMode } = useAtomValue(userAtom);
const setTab = useUpdateAtom(tabAtom);
Expand All @@ -127,6 +130,23 @@ const Authentication = (): JSX.Element => {
setTab(newTab);
};

const resize = (): void => {
setWindowHeight(window.innerHeight);
};

useEffect(() => {
window.addEventListener('resize', resize);

setClientRect(formContainerRef.current?.getBoundingClientRect() ?? null);

return () => {
window.removeEventListener('resize', resize);
};
}, []);

const formContainerHeight =
windowHeight - (clientRect?.top || 0) - scrollMargin;

const tabs = useMemo(
() =>
panels.map(({ title, value }) => (
Expand All @@ -136,33 +156,31 @@ const Authentication = (): JSX.Element => {
);

const tabPanels = useMemo(
() => (
<Responsive.ParentSize>
{({ height }): Array<JSX.Element> =>
panels.map(({ Component, value, image }) => (
<TabPanel
className={classes.panel}
key={value}
style={{ height: height - marginBottomHeight }}
value={value}
>
<div className={classes.formContainer}>
<Component />
<img alt="padlock" className={classes.image} src={image} />
</div>
</TabPanel>
))
}
</Responsive.ParentSize>
),
[themeMode],
() =>
panels.map(({ Component, value, image }) => (
<TabPanel className={classes.panel} key={value} value={value}>
<Box
ref={formContainerRef}
sx={{
height: `${formContainerHeight}px`,
overflowY: 'auto',
}}
>
<div className={classes.formContainer}>
<Component />
<img alt="padlock" className={classes.image} src={image} />
</div>
</Box>
</TabPanel>
)),
[themeMode, formContainerHeight],
);

return (
<Box className={classes.box}>
<TabContext value={appliedTab}>
<Container className={classes.container}>
<Paper className={classes.paper}>
<Paper square className={classes.paper}>
<TabList
className={classes.tabList}
variant="fullWidth"
Expand Down

0 comments on commit 8d64b02

Please sign in to comment.