Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EPMRPP-80177 || Tooltip reuse in project settings #3342

Merged
merged 5 commits into from
Nov 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion app/localization/translated/be.json
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@
"DefectTypesTab.automationBugsGroup": "Група Automation Bugs",
"DefectTypesTab.colorCol": "Колер",
"DefectTypesTab.createDefectHeader": "Стварыць Тып Дэфекту",
"DefectTypesTab.createDefectIcon": "Стварыце новы Тып Дэфекту",
"DefectTypesTab.createDefectIcon": "Стварыце новы Дэфект",
"DefectTypesTab.defectLongNameHint": "Назва Тыпу Дэфекту павінна мець памер ад '3' да '55' сімвалаў",
"DefectTypesTab.defectNameCol": "Імя Тыпу Дэфекту",
"DefectTypesTab.defectShortNameHint": "Абрэвіятура Тыпу Дэфекту павінна мець памер ад '1' да '4' сімвалаў",
Expand Down Expand Up @@ -943,6 +943,8 @@
"InputUserSearch.inviteNewUser": "Запрасіць {userEmail}",
"InputUserSearch.inviteNewUserInfo": "Адправіць запрашэнне на гэты адрас",
"InputUserSearch.isAssigned": "Карыстальнік ужо прызначаны на праект",
"InputWithEye.hideTooltip": "Схаваць",
"InputWithEye.showTooltip": "Паказаць",
"InstalledPluginsTab.installedPluginsBreadcrumbTitle": "Усталяваныя плагины",
"InstancesSection.addIntegrationButtonTitle": "Дадаць інтэграцыю",
"InstancesSection.addIntegrationSuccess": "Інтэграцыя паспяхова дададзена",
Expand Down
4 changes: 3 additions & 1 deletion app/localization/translated/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@
"DefectTypesTab.automationBugsGroup": "Группа ошибок тестов",
"DefectTypesTab.colorCol": "Цвет",
"DefectTypesTab.createDefectHeader": "Создать Тип Дефекта",
"DefectTypesTab.createDefectIcon": "Создать новый Тип Дефекта",
"DefectTypesTab.createDefectIcon": "Создать новый Дефект",
"DefectTypesTab.defectLongNameHint": "Имя Типа Дефекта должно иметь размер от '3' до '55' символов",
"DefectTypesTab.defectNameCol": "Имя Типа Дефекта",
"DefectTypesTab.defectShortNameHint": "Аббревиатура Типа Дефекта должна иметь размер от '1' до '4' символов",
Expand Down Expand Up @@ -943,6 +943,8 @@
"InputUserSearch.inviteNewUser": "Пригласить {userEmail}",
"InputUserSearch.inviteNewUserInfo": "Отправить приглашение на этот адрес",
"InputUserSearch.isAssigned": "Пользователь уже назначен на проект",
"InputWithEye.hideTooltip": "Скрыть",
"InputWithEye.showTooltip": "Показать",
"InstalledPluginsTab.installedPluginsBreadcrumbTitle": "Установленные плагины",
"InstancesSection.addIntegrationButtonTitle": "Добавить интеграцию",
"InstancesSection.addIntegrationSuccess": "Интеграция успешно добавлена",
Expand Down
4 changes: 3 additions & 1 deletion app/localization/translated/uk.json
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@
"DefectTypesTab.automationBugsGroup": "Група помилок тестів",
"DefectTypesTab.colorCol": "Колір",
"DefectTypesTab.createDefectHeader": "Створити Тип Дефекту",
"DefectTypesTab.createDefectIcon": "Створіть новий Тип Дефекту",
"DefectTypesTab.createDefectIcon": "Створіть новий Дефект",
"DefectTypesTab.defectLongNameHint": "Назва Типу Дефекту має мати розмір від '3' до '55' символів",
"DefectTypesTab.defectNameCol": "Ім’я Типу Дефекту",
"DefectTypesTab.defectShortNameHint": "Абревіатура Типу Дефекту повинна мати розмір від '1' до '4' символів",
Expand Down Expand Up @@ -943,6 +943,8 @@
"InputUserSearch.inviteNewUser": "Пригласить {userEmail}",
"InputUserSearch.inviteNewUserInfo": "Відправити запрошення на цю адресу",
"InputUserSearch.isAssigned": "Користувач вже призначений на проект",
"InputWithEye.hideTooltip": "Сховати",
"InputWithEye.showTooltip": "Показати",
"InstalledPluginsTab.installedPluginsBreadcrumbTitle": "Встановлені плагіни",
"InstancesSection.addIntegrationButtonTitle": "Інтеграцію Додати",
"InstancesSection.addIntegrationSuccess": "Інтеграція успішно додано",
Expand Down
81 changes: 72 additions & 9 deletions app/src/componentLibrary/breadcrumbs/breadcrumb/breadcrumb.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,37 @@
* limitations under the License.
*/

import React, { useEffect, useRef } from 'react';
import React, { useEffect, useRef, useState } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames/bind';
import { NavLink } from 'components/main/navLink';
import { withTooltip } from 'componentLibrary/tooltip';
import styles from './breadcrumb.scss';

const cx = classNames.bind(styles);

// todo remove title and add tooltip with {title} (EPMRPP-79184)
export const Breadcrumb = ({
const BreadcrumbTitleComponent = ({
descriptor: { link, title, onClick },
maxBreadcrumbWidth,
titleTailNumChars,
descriptor: { title, link, onClick },
tooltipDisabled,
setTooltipDisabled,
}) => {
const ref = useRef();

useEffect(() => {
const { offsetWidth, scrollWidth, dataset } = ref.current;
if (ref.current) {
const { offsetWidth, scrollWidth, dataset } = ref.current;

if (offsetWidth < scrollWidth) {
dataset.tail = title.slice(title.length - titleTailNumChars);
if (offsetWidth < scrollWidth) {
dataset.tail = title.slice(title.length - titleTailNumChars);
setTooltipDisabled(false);
}
}
}, [title, titleTailNumChars]);
}, [ref, title, titleTailNumChars]);

return (
<div className={cx('breadcrumb')} title={title}>
<div className={cx(tooltipDisabled ? 'breadcrumb' : 'breadcrumb-with-tooltip')}>
chivekrodis marked this conversation as resolved.
Show resolved Hide resolved
<NavLink className={cx('link')} to={link} onClick={onClick}>
<div ref={ref} className={cx('breadcrumb-text')} style={{ maxWidth: maxBreadcrumbWidth }}>
{title}
Expand All @@ -48,6 +53,64 @@ export const Breadcrumb = ({
</div>
);
};
BreadcrumbTitleComponent.propTypes = {
maxBreadcrumbWidth: PropTypes.number.isRequired,
titleTailNumChars: PropTypes.number,
descriptor: PropTypes.shape({
title: PropTypes.string.isRequired,
link: PropTypes.object.isRequired,
onClick: PropTypes.func,
}).isRequired,
tooltipDisabled: PropTypes.bool,
setTooltipDisabled: PropTypes.func,
};
BreadcrumbTitleComponent.defaultProps = {
tooltipDisabled: true,
setTooltipDisabled: () => {},
};

const BreadcrumbTitleTooltip = ({ descriptor: { title } }) => <span>{title}</span>;
BreadcrumbTitleTooltip.propTypes = {
descriptor: PropTypes.shape({
title: PropTypes.string.isRequired,
}).isRequired,
};

const BreadcrumbTitleComponentWithTooltip = withTooltip({
ContentComponent: BreadcrumbTitleTooltip,
side: 'bottom',
dynamicWidth: true,
tooltipWrapperClassName: cx('breadcrumb'),
})((props) => <BreadcrumbTitleComponent {...props} />);
BreadcrumbTitleComponentWithTooltip.propTypes = {
maxBreadcrumbWidth: PropTypes.number.isRequired,
titleTailNumChars: PropTypes.number,
descriptor: PropTypes.shape({
title: PropTypes.string.isRequired,
link: PropTypes.object.isRequired,
onClick: PropTypes.func,
}).isRequired,
};

export const Breadcrumb = ({ maxBreadcrumbWidth, titleTailNumChars, descriptor }) => {
const [tooltipDisabled, setTooltipDisabled] = useState(true);

return tooltipDisabled ? (
<BreadcrumbTitleComponent
descriptor={descriptor}
maxBreadcrumbWidth={maxBreadcrumbWidth}
titleTailNumChars={titleTailNumChars}
tooltipDisabled={tooltipDisabled}
setTooltipDisabled={setTooltipDisabled}
/>
) : (
<BreadcrumbTitleComponentWithTooltip
descriptor={descriptor}
maxBreadcrumbWidth={maxBreadcrumbWidth}
titleTailNumChars={titleTailNumChars}
/>
);
};

Breadcrumb.propTypes = {
maxBreadcrumbWidth: PropTypes.number,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
* limitations under the License.
*/

.breadcrumb {
.breadcrumb,
.breadcrumb-with-tooltip {
display: inline-block;
width: auto;
height: 100%;
Expand Down
2 changes: 1 addition & 1 deletion app/src/componentLibrary/tooltip/withTooltip.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export const withTooltip = ({
</Reference>
{isOpened &&
ReactDOM.createPortal(
<Popper placement={side} eventsEnabled={false}>
<Popper placement={side} eventsEnabled>
{({ placement, ref, style, arrowProps }) => (
<div
className={cx('tooltip')}
Expand Down
2 changes: 1 addition & 1 deletion app/src/componentLibrary/tooltip/withTooltip.scss
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ $triangle-color: rgba($COLOR--almost-black, 0.75);
padding: 16px;
border-radius: 8px;
background-color: rgba($COLOR--almost-black, 0.95);
font-family: $FONT-ROBOTO-MEDIUM;
font-family: $FONT-ROBOTO-REGULAR;
font-size: 11px;
color: $COLOR--white-two;
word-wrap: break-word;
Expand Down
71 changes: 53 additions & 18 deletions app/src/components/inputs/inputWithEye/inputWithEye.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,34 +13,69 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useIntl } from 'react-intl';
import PropTypes from 'prop-types';
import classNames from 'classnames/bind';
import Parser from 'html-react-parser';
import EyeIcon from 'common/img/newIcons/eye-inline.svg';
import CrossEyeIcon from 'common/img/newIcons/cross-eye-inline.svg';
import { withTooltip } from 'componentLibrary/tooltip';
import React from 'react';
import { messages } from './messages';
import styles from './inputWithEye.scss';

const cx = classNames.bind(styles);

export const InputWithEye = ({ value, disabled, onChange, onFocus, onBlur, className }) => (
// eslint-disable-next-line
<label className={cx('input-with-eye', className)} onFocus={onFocus} onBlur={onBlur} tabIndex="1">
<input
type="checkbox"
className={cx('input')}
checked={value}
disabled={disabled}
onChange={onChange}
/>
<div
className={cx('eye', {
disabled,
})}
>
{Parser(value ? EyeIcon : CrossEyeIcon)}
</div>
</label>
const EyeComponent = ({ value }) => Parser(value ? EyeIcon : CrossEyeIcon);
EyeComponent.propTypes = {
value: PropTypes.string.isRequired,
};

const EyeTooltip = ({ formatMessage, value }) => (
<span>{formatMessage(value ? messages.hideTooltip : messages.showTooltip)}</span>
);
EyeTooltip.propTypes = {
formatMessage: PropTypes.func.isRequired,
value: PropTypes.string.isRequired,
};

const EyeComponentWithTooltip = withTooltip({
ContentComponent: EyeTooltip,
side: 'bottom',
dynamicWidth: true,
})(({ value }) => <EyeComponent value={value} />);
EyeComponentWithTooltip.propTypes = {
formatMessage: PropTypes.func.isRequired,
value: PropTypes.string.isRequired,
};

export const InputWithEye = ({ value, disabled, onChange, onFocus, onBlur, className }) => {
const { formatMessage } = useIntl();

return (
// eslint-disable-next-line
<label className={cx('input-with-eye', className)} onFocus={onFocus} onBlur={onBlur} tabIndex="1">
<input
type="checkbox"
className={cx('input')}
checked={value}
disabled={disabled}
onChange={onChange}
/>
<div
className={cx('eye', {
disabled,
})}
>
{disabled ? (
<EyeComponent value={value} />
) : (
<EyeComponentWithTooltip formatMessage={formatMessage} value={value} />
)}
</div>
</label>
);
};
InputWithEye.propTypes = {
children: PropTypes.node,
value: PropTypes.bool,
Expand Down
28 changes: 28 additions & 0 deletions app/src/components/inputs/inputWithEye/messages.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright 2022 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 { defineMessages } from 'react-intl';

export const messages = defineMessages({
hideTooltip: {
id: 'InputWithEye.hideTooltip',
defaultMessage: 'Hide',
},
showTooltip: {
id: 'InputWithEye.showTooltip',
defaultMessage: 'Show',
},
});
17 changes: 16 additions & 1 deletion app/src/pages/common/settingsPage/generalTab/generalTab.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import { SpinningPreloader } from 'components/preloaders/spinningPreloader';
import { BubblesPreloader } from 'components/preloaders/bubblesPreloader';
import { Button } from 'componentLibrary/button';
import { Dropdown } from 'componentLibrary/dropdown';
import { withTooltip } from 'componentLibrary/tooltip';
import styles from './generalTab.scss';
import { Messages } from './generalTabMessages';

Expand All @@ -53,6 +54,20 @@ const hoursToSeconds = (hours) => moment.duration(hours, 'hours').asSeconds();
const daysToSeconds = (days) => moment.duration(days, 'days').asSeconds();
const selector = formValueSelector('generalForm');

const NameTooltip = ({ projectId }) => <span>{projectId}</span>;
NameTooltip.propTypes = {
projectId: PropTypes.string.isRequired,
};

const NameInput = withTooltip({
ContentComponent: NameTooltip,
side: 'bottom',
dynamicWidth: true,
})(({ projectId }) => <div className={cx('fake-input')}>{projectId}</div>);
NameInput.propTypes = {
projectId: PropTypes.string.isRequired,
};

@reduxForm({
form: 'generalForm',
})
Expand Down Expand Up @@ -302,7 +317,7 @@ export class GeneralTab extends Component {
<form onSubmit={this.props.handleSubmit(this.onFormSubmit)}>
<div>
<div className={cx('fake-input-label')}>Name</div>
<div className={cx('fake-input')}>{this.props.projectId}</div>
<NameInput projectId={this.props.projectId} />
</div>
<FormField
name="interruptJobTime"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import {
Divider,
TabDescription,
} from 'pages/inside/projectSettingsPageContainer/content/elements';
import { withHoverableTooltip } from 'components/main/tooltips/hoverableTooltip';
import { withTooltip } from 'componentLibrary/tooltip';
import { showModalAction } from 'controllers/modal';
import {
MAX_DEFECT_TYPES_COUNT,
Expand All @@ -54,12 +54,10 @@ CreateDefectTooltip.propTypes = {
formatMessage: PropTypes.func.isRequired,
};

const CreateDefect = withHoverableTooltip({
TooltipComponent: CreateDefectTooltip,
data: {
placement: 'bottom',
dynamicWidth: true,
},
const CreateDefect = withTooltip({
ContentComponent: CreateDefectTooltip,
side: 'bottom',
dynamicWidth: true,
})(({ onClick, disabled }) => (
<i
className={cx('group-create', { disabled })}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,6 @@ $DEFECT_NAME_PADDING: 16px;
padding-bottom: 10px;
}

.create-tooltip {
font-family: $FONT-ROBOTO-REGULAR;
font-size: 11px;
color: $COLOR--e-400;
}

.button {
margin-left: auto;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export const messages = defineMessages({
},
createDefectIcon: {
id: 'DefectTypesTab.createDefectIcon',
defaultMessage: 'Create a new Defect Type',
defaultMessage: 'Create a new Defect',
},
description: {
id: 'DefectTypesTab.description',
Expand Down