Skip to content

Commit

Permalink
EPMRPP-96981 || Server Settings page layout (#4100)
Browse files Browse the repository at this point in the history
* EPMRPP-96981 || Server Settings page layout

* EPMRPP-96981 || adjusted styles to match the Figma mockup

* EPMRPP-96981 || fetch app info on mount

* EPMRPP-96981 || refactor the hooks syntax

* EPMRPP-96981 || address PR comments and update component styles

* EPMRPP-96981 || Server Settings page layout

* EPMRPP-96981 || adjusted styles to match the Figma mockup

* EPMRPP-96981 || fetch app info on mount

* EPMRPP-96981 || refactor the hooks syntax

* EPMRPP-96981 || address PR comments and update component styles

* EPMRPP-96981 || remove an unused file and add a constant

* EPMRPP-96981 || refactor and update translations

* EPMRPP-96981 || refactor the code
  • Loading branch information
iso9000t authored Nov 21, 2024
1 parent fea1fc1 commit 239ba94
Show file tree
Hide file tree
Showing 14 changed files with 256 additions and 6 deletions.
7 changes: 6 additions & 1 deletion app/localization/translated/be.json
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,8 @@
"EditWidgetModal.editWidgetSuccess": "Віджэт абноўлены!",
"EditWidgetModal.headerText": "Рэдагаваць віджэт",
"EmailFormFields.authLabel": "Аўтарызацыя",
"EmailFormFields.fromLabel": "Імя адпраўніка па змаўчанні",
"EmailFormFields.fromEmailLabel": "From Email",
"EmailFormFields.fromNameLabel": "From name",
"EmailFormFields.hostLabel": "Хост",
"EmailFormFields.passwordLabel": "Пароль",
"EmailFormFields.portFieldHint": "Магчымы толькі лічбы ад '1' да '65535'",
Expand Down Expand Up @@ -1839,6 +1840,10 @@
"SortingControl.sortByFailedItems": "Няўдалыя пункты",
"SortingControl.sortByPassingRate": "Прахадны бал",
"SortingControl.sortByTotal": "Агульная колькасць",
"SsoUsersForm.formHeader": "Instance Invitations",
"SsoUsersForm.manualInvitesDescription": "Карыстальнікі могуць адпраўляць запрашэнні іншым карыстальнікам. Калі ўключана, новыя карыстальнікі могуць быць ствараны толькі праз SSO.",
"SsoUsersForm.ssoOnlyDescription": "Новыя карыстальнікі могуць быць створаны толькі праз SSO.",
"SsoUsersForm.switcherLabel": "Толькі SSO карыстальнікі",
"StackTrace.jumpTo": "Перайсці",
"StackTrace.linkText": "Адкрыць логі",
"StackTrace.loadLabel": "Загрузіць яшчэ",
Expand Down
7 changes: 6 additions & 1 deletion app/localization/translated/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,8 @@
"EditWidgetModal.editWidgetSuccess": "¡Widget actualizado!",
"EditWidgetModal.headerText": "Editar widget",
"EmailFormFields.authLabel": "Autorización",
"EmailFormFields.fromLabel": "Nombre del remitente predeterminado",
"EmailFormFields.fromEmailLabel": "From Email",
"EmailFormFields.fromNameLabel": "From name",
"EmailFormFields.hostLabel": "Host",
"EmailFormFields.passwordLabel": "Contraseña",
"EmailFormFields.portFieldHint": "Solo se permiten números del '1' al '65535'",
Expand Down Expand Up @@ -1839,6 +1840,10 @@
"SortingControl.sortByFailedItems": "Elementos fallidos",
"SortingControl.sortByPassingRate": "Porcentaje de aprobados",
"SortingControl.sortByTotal": "Cantidad total",
"SsoUsersForm.formHeader": "Instance Invitations",
"SsoUsersForm.manualInvitesDescription": "Users can manually send invitations for other users. If enabled new users can be created via SSO only.",
"SsoUsersForm.ssoOnlyDescription": "New users can be created via SSO only.",
"SsoUsersForm.switcherLabel": "SSO users only",
"StackTrace.jumpTo": "Ir a",
"StackTrace.linkText": "Abrir registros",
"StackTrace.loadLabel": "Cargar más",
Expand Down
7 changes: 6 additions & 1 deletion app/localization/translated/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,8 @@
"EditWidgetModal.editWidgetSuccess": "Виджет обновлен!",
"EditWidgetModal.headerText": "Редактировать виджет",
"EmailFormFields.authLabel": "Авторизация",
"EmailFormFields.fromLabel": "Имя отправителя по умолчанию",
"EmailFormFields.fromEmailLabel": "From Email",
"EmailFormFields.fromNameLabel": "From name",
"EmailFormFields.hostLabel": "Хост",
"EmailFormFields.passwordLabel": "Пароль",
"EmailFormFields.portFieldHint": "Возможны только цифры от '1' до '65535'",
Expand Down Expand Up @@ -1839,6 +1840,10 @@
"SortingControl.sortByFailedItems": "Неудачные пункты",
"SortingControl.sortByPassingRate": "Проходной балл",
"SortingControl.sortByTotal": "Общее количество",
"SsoUsersForm.formHeader": "Instance Invitations",
"SsoUsersForm.manualInvitesDescription": "Пользователи могут вручную отправлять приглашения другим пользователям. Если включено, новых пользователей можно создавать только через SSO.",
"SsoUsersForm.ssoOnlyDescription": "Новых пользователей можно создавать только через SSO.",
"SsoUsersForm.switcherLabel": "Только SSO пользователи",
"StackTrace.jumpTo": "Перейти",
"StackTrace.linkText": "Открыть логи",
"StackTrace.loadLabel": "Загрузить еще",
Expand Down
7 changes: 6 additions & 1 deletion app/localization/translated/uk.json
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,8 @@
"EditWidgetModal.editWidgetSuccess": "Оновлений Віджет!",
"EditWidgetModal.headerText": "Віджет Редагувати",
"EmailFormFields.authLabel": "Авторизація",
"EmailFormFields.fromLabel": "Ім’я відправника за замовчуванням",
"EmailFormFields.fromEmailLabel": "From Email",
"EmailFormFields.fromNameLabel": "From name",
"EmailFormFields.hostLabel": "Хост",
"EmailFormFields.passwordLabel": "Пароль",
"EmailFormFields.portFieldHint": "Можливі тільки цифри від '1' до '65535'",
Expand Down Expand Up @@ -1839,6 +1840,10 @@
"SortingControl.sortByFailedItems": "Невдалі пункти",
"SortingControl.sortByPassingRate": "Прохідний бал",
"SortingControl.sortByTotal": "Загальна кількість",
"SsoUsersForm.formHeader": "Instance Invitations",
"SsoUsersForm.manualInvitesDescription": "Користувачі можуть самостійно надсилати запрошення іншим користувачам. Якщо ввімкнено, нові користувачі створюються виключно через SSO.",
"SsoUsersForm.ssoOnlyDescription": "Користувачі створюються виключно через SSO.",
"SsoUsersForm.switcherLabel": "SSO users only",
"StackTrace.jumpTo": "Перейти",
"StackTrace.linkText": "Логи Відкрити",
"StackTrace.loadLabel": "Завантажити",
Expand Down
7 changes: 6 additions & 1 deletion app/localization/translated/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,8 @@
"EditWidgetModal.editWidgetSuccess": "小部件已更新",
"EditWidgetModal.headerText": "编辑小部件",
"EmailFormFields.authLabel": "授权",
"EmailFormFields.fromLabel": "默认发件人姓名",
"EmailFormFields.fromEmailLabel": "From Email",
"EmailFormFields.fromNameLabel": "From name",
"EmailFormFields.hostLabel": "服务器(Host)",
"EmailFormFields.passwordLabel": "密码",
"EmailFormFields.portFieldHint": "只允许输入从“1”到“65535”的数字",
Expand Down Expand Up @@ -1839,6 +1840,10 @@
"SortingControl.sortByFailedItems": "失败的测试项",
"SortingControl.sortByPassingRate": "通过率",
"SortingControl.sortByTotal": "全部",
"SsoUsersForm.formHeader": "Instance Invitations",
"SsoUsersForm.manualInvitesDescription": "Users can manually send invitations for other users. If enabled new users can be created via SSO only.",
"SsoUsersForm.ssoOnlyDescription": "New users can be created via SSO only.",
"SsoUsersForm.switcherLabel": "SSO users only",
"StackTrace.jumpTo": "跳转至",
"StackTrace.linkText": "在日志视图中打开",
"StackTrace.loadLabel": "加载更多",
Expand Down
1 change: 1 addition & 0 deletions app/src/controllers/appInfo/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
export const APP_INFO_NAMESPACE = 'appInfo';
export const ANALYTICS_INSTANCE_KEY = 'server.details.instance';
export const ANALYTICS_ALL_KEY = 'server.analytics.all';
export const SSO_USERS_ONLY_KEY = 'server.users.sso';
export const OLD_HISTORY_KEY = 'history_old';
export const GA_MEASUREMENT_ID = 'ga_measurement_id';
export const INSTANCE_TYPE = 'instance_type';
Expand Down
1 change: 1 addition & 0 deletions app/src/controllers/appInfo/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@ export {
isDemoInstanceSelector,
areUserSuggestionsAllowedSelector,
baseEventParametersSelector,
ssoUsersOnlySelector,
} from './selectors';
export { ANALYTICS_ALL_KEY } from './constants';
3 changes: 3 additions & 0 deletions app/src/controllers/appInfo/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
NOT_PROVIDED,
ALLOW_DELETE_ACCOUNT,
USER_SUGGESTIONS,
SSO_USERS_ONLY_KEY,
} from './constants';

export const appInfoSelector = (state) => state.appInfo || {};
Expand All @@ -57,6 +58,8 @@ export const analyticsEnabledSelector = (state) =>
extensionsConfigSelector(state)[ANALYTICS_ALL_KEY] === 'true';
export const analyzerExtensionsSelector = (state) => extensionsSelector(state).analyzers || [];
export const authExtensionsSelector = (state) => uatInfoSelector(state).authExtensions || {};
export const ssoUsersOnlySelector = (state) =>
extensionsConfigSelector(state)[SSO_USERS_ONLY_KEY] === 'true';
export const isOldHistorySelector = (state) =>
environmentSelector(state)[OLD_HISTORY_KEY] === 'true';
export const isDemoInstanceSelector = (state) => !!apiJobsSelector(state).flushingDataTrigger;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@

import classNames from 'classnames/bind';
import { GithubAuthForm } from './forms';
import { SsoUsersForm } from './forms/ssoUsersForm';
import styles from './authConfigurationTab.scss';

const cx = classNames.bind(styles);

export const AuthConfigurationTab = () => (
<div className={cx('auth-configuration-tab')}>
<GithubAuthForm />
<SsoUsersForm />
</div>
);
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@

.github-auth-form {
position: relative;
margin-bottom: 20px;
margin-bottom: 30px;
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@
*/

export { GithubAuthForm } from './githubAuthForm';
export { SsoUsersForm } from './ssoUsersForm';
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Copyright 2024 EPAM Systems
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

export { SsoUsersForm } from './ssoUsersForm';
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*
* Copyright 2024 EPAM Systems
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { defineMessages, useIntl } from 'react-intl';
import classNames from 'classnames/bind';
import { connect } from 'react-redux';
import { InputBigSwitcher } from 'components/inputs/inputBigSwitcher';
import { SectionHeader } from 'components/main/sectionHeader';
import { ADMIN_SERVER_SETTINGS_PAGE_EVENTS } from 'components/main/analytics/events';
import { ssoUsersOnlySelector, fetchAppInfoAction } from 'controllers/appInfo';
import formStyles from 'pages/admin/serverSettingsPage/common/formController/formController.scss';
import styles from './ssoUsersForm.scss';

const formCx = classNames.bind(formStyles);
const cx = classNames.bind(styles);

const messages = defineMessages({
switcherLabel: {
id: 'SsoUsersForm.switcherLabel',
defaultMessage: 'SSO users only',
},
formHeader: {
id: 'SsoUsersForm.formHeader',
defaultMessage: 'Instance Invitations',
},
ssoOnlyDescription: {
id: 'SsoUsersForm.ssoOnlyDescription',
defaultMessage: 'New users can be created via SSO only.',
},
manualInvitesDescription: {
id: 'SsoUsersForm.manualInvitesDescription',
defaultMessage:
'Users can manually send invitations for other users. If enabled new users can be created via SSO only.',
},
});

const SsoUsersFormComponent = ({ enabled: enabledFromStore, fetchAppInfo }) => {
const { formatMessage } = useIntl();
const [enabled, setEnabled] = useState(enabledFromStore);
const inputId = 'ssoUsersToggle';

useEffect(() => {
fetchAppInfo();
}, [fetchAppInfo]);

useEffect(() => {
setEnabled(enabledFromStore);
}, [enabledFromStore]);

const getDescription = () =>
formatMessage(enabled ? messages.ssoOnlyDescription : messages.manualInvitesDescription);

const handleToggle = (value) => {
setEnabled(value);
};

return (
<div className={formCx('form-controller')}>
<div className={formCx('heading-wrapper')}>
<SectionHeader text={formatMessage(messages.formHeader)} />
</div>
<div className={formCx('form')}>
<div className={cx('form-group')}>
<label htmlFor={inputId} className={cx('form-group-label')}>
{formatMessage(messages.switcherLabel)}
</label>
<div className={cx('form-group-content')}>
<div className={cx('input-container')}>
<InputBigSwitcher
id={inputId}
value={enabled}
onChange={handleToggle}
mobileDisabled
onChangeEventInfo={ADMIN_SERVER_SETTINGS_PAGE_EVENTS.SSO_USERS_SWITCHER}
/>
<div className={cx('description')} aria-live="polite">
{getDescription()}
</div>
</div>
</div>
</div>
</div>
</div>
);
};

SsoUsersFormComponent.propTypes = {
enabled: PropTypes.bool,
fetchAppInfo: PropTypes.func.isRequired,
};

SsoUsersFormComponent.defaultProps = {
enabled: false,
};

const mapStateToProps = (state) => ({
enabled: ssoUsersOnlySelector(state),
});

const mapDispatchToProps = {
fetchAppInfo: fetchAppInfoAction,
};

export const SsoUsersForm = connect(mapStateToProps, mapDispatchToProps)(SsoUsersFormComponent);
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright 2024 EPAM Systems
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/


.form-group {
display: flex;
justify-content: flex-start;
align-items: center;
width: 100%;
margin-bottom: 25px;

@media (max-width: $SCREEN_XS_MAX) {
flex-direction: column;
align-items: flex-start;
margin-bottom: 15px;
}
}

.form-group-label {
min-width: 210px;
width: 210px;
padding-right: 4px;
text-align: right;
font-size: 13px;
line-height: 13px;
color: $COLOR--charcoal-grey;
box-sizing: border-box;

@media (max-width: $SCREEN_SM_MAX) {
min-width: 150px;
width: 150px;
}
@media (max-width: $SCREEN_XS_MAX) {
width: 100%;
margin-bottom: 8px;
padding: 0;
text-align: left;
}
}

.form-group-content {
flex: 1;
padding: 0 15px;

@media (max-width: $SCREEN_XS_MAX) {
padding: 0;
width: 100%;
}
}

.input-container {
display: flex;
align-items: center;
gap: 15px;
min-height: 36px;

@media (max-width: $SCREEN_XS_MAX) {
flex-direction: column;
align-items: flex-start;
}
}

.description {
width: 300px;
font-size: 12px;
line-height: 1.5;
color: $COLOR--gray-60;
}

0 comments on commit 239ba94

Please sign in to comment.