Skip to content

Commit

Permalink
EPMRPP-90322 || Help and Service Implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
maria-hambardzumian committed May 17, 2024
1 parent 3c4ed90 commit 505775d
Show file tree
Hide file tree
Showing 22 changed files with 969 additions and 2 deletions.
1 change: 1 addition & 0 deletions app/src/common/css/variables/newColors.scss
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ $COLOR--system-message-error: #db3549;
$COLOR--system-message-error-line-100: #fccbcb;
$COLOR--system-message-error-line-200: #ffc0bd;
$COLOR--system-message-information-line-100: #ced3db;
$COLOR--system-notification-marker: #00FF66;
$COLOR--system-issue-group: #3e7be6;
$COLOR--product-bug-group: #d32f2f;
$COLOR--automation-bug-group: #ffc208;
Expand Down
3 changes: 3 additions & 0 deletions app/src/common/img/help-inline.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions app/src/common/utils/referenceDictionary.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,18 @@ export const docsReferences = {
workWithReports: 'https://reportportal.io/docs/work-with-reports/InvestigationOfFailure',
pluginsDocs: 'https://reportportal.io/docs/category/plugins',
};

export const referenceFAQDictionary = {
configureReportingFAQ:
'https://reportportal.io/docs/log-data-in-reportportal/test-framework-integration/',
improvePerformanceFAQ:
'https://reportportal.io/docs/installation-steps/OptimalPerformanceHardwareSetup',
configureAnalyzerFAQ:
'https://reportportal.io/docs/issues-troubleshooting/ResolveAnalyzerKnownIssues',
integrateJiraFAQ: 'https://reportportal.io/docs/plugins/AtlassianJiraServer',
configureCertificateFAQ:
'https://reportportal.io/docs/installation-steps/SetupTSLSSLInTraefik2.0.x',
fileStorageOptionsFAQ:
'https://reportportal.io/docs/installation-steps/ReportPortal23.1FileStorageOptions',
pricingOptionsFAQ: 'https://reportportal.io/pricing/saas',
};
1 change: 1 addition & 0 deletions app/src/controllers/log/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export const LOG_LEVEL_FILTER_KEY = 'filter.gte.level';
export const LOG_STATUS_FILTER_KEY = 'filter.in.status';
export const WITH_ATTACHMENTS_FILTER_KEY = 'filter.ex.binaryContent';
export const LOG_VIEW_MODE_STORAGE_KEY = 'logViewMode';
export const FAQ_OPEN_STATUS_STORAGE_KEY = 'isFAQOpened';
export const HIDE_PASSED_LOGS = 'excludePassedLogs';
export const HIDE_EMPTY_STEPS = 'excludeEmptySteps';
export const DEFAULT_SORTING = formatSortingString(['logTime'], SORTING_ASC);
Expand Down
6 changes: 6 additions & 0 deletions app/src/controllers/log/storageUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
LOG_LEVELS,
DEFAULT_LOG_LEVEL,
LOG_VIEW_MODE_STORAGE_KEY,
FAQ_OPEN_STATUS_STORAGE_KEY,
} from './constants';

const getUserSettingsFromStorage = (userId) => getStorageItem(`${userId}_settings`) || {};
Expand Down Expand Up @@ -51,3 +52,8 @@ export const getLogViewMode = (userId) => getLogViewModeFromStorage(userId) || M

export const setLogViewMode = (userId, viewMode) =>
updateUserSettingsInStorage(userId, { [LOG_VIEW_MODE_STORAGE_KEY]: viewMode });

export const getFAQOpenStatus = (userId) =>
getUserSettingsFromStorage(userId)[FAQ_OPEN_STATUS_STORAGE_KEY];
export const setFAQOpenStatusTrue = (userId) =>
updateUserSettingsInStorage(userId, { [FAQ_OPEN_STATUS_STORAGE_KEY]: true });
42 changes: 41 additions & 1 deletion app/src/layouts/common/appSidebar/appSidebar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ import classNames from 'classnames/bind';
import { referenceDictionary } from 'common/utils';
import { useIntl, defineMessages } from 'react-intl';
import { Sidebar } from 'componentLibrary/sidebar';
import { ServiceWithPopover } from 'layouts/common/appSidebar/helpAndService';
import LogoHelp from 'common/img/help-inline.svg';
import { useSelector } from 'react-redux';
import { userIdSelector } from 'controllers/user';
import { getFAQOpenStatus } from 'controllers/log/storageUtils';
import Parser from 'html-react-parser';
import LogoBlockIcon from './img/logo-icon-inline.svg';
import LogoControlIcon from './img/logo-text-icon-inline.svg';
import { UserAvatar } from './userAvatar';
Expand All @@ -44,9 +50,14 @@ export const AppSidebar = ({
bottomSidebarControlItems,
isOpenOrganizationPopover,
}) => {
const userId = useSelector(userIdSelector);
const [isFAQOpened, setIsFAQOpened] = useState(!!getFAQOpenStatus(userId));

const { formatMessage } = useIntl();
const [isOpenAvatarPopover, setIsOpenAvatarPopover] = useState(false);
const [isOpenSupportPopover, setIsOpenSupportPopover] = useState(false);
const [isHoveredUser, setIsHoveredUser] = useState(false);
const [isHoveredService, setIsHoveredService] = useState(false);

const onHoverUser = () => {
setIsHoveredUser(true);
Expand All @@ -55,10 +66,28 @@ export const AppSidebar = ({
const onClearUser = () => {
setIsHoveredUser(false);
};
const onHoverService = () => {
setIsHoveredService(true);
};

const onClearService = () => {
setIsHoveredService(false);
};

const createFooterBlock = (openNavbar) => (
<>
<div className={cx('policy-block')} />
<div
className={cx('service-block', { 'active-tooltip': !isFAQOpened })}
onClick={() => {
openNavbar();
setIsOpenSupportPopover(!isOpenSupportPopover);
}}
onMouseEnter={onHoverService}
onMouseLeave={onClearService}
>
<i>{Parser(LogoHelp)}</i>
</div>
<UserAvatar
onClick={() => {
openNavbar();
Expand All @@ -78,6 +107,15 @@ export const AppSidebar = ({
{formatMessage(messages.privacyPolicy)}
</a>
</div>
<div className={cx('service-control', { hover: isHoveredService })}>
<ServiceWithPopover
closeNavbar={onCloseNavbar}
isOpenPopover={isOpenSupportPopover}
togglePopover={setIsOpenSupportPopover}
isFAQOpened={isFAQOpened}
onFAQOpen={setIsFAQOpened}
/>
</div>
<div className={cx('user-control', { hover: isHoveredUser })}>
<UserControlWithPopover
closeNavbar={onCloseNavbar}
Expand All @@ -100,7 +138,9 @@ export const AppSidebar = ({
bottomSidebarControlItems={bottomSidebarControlItems}
createFooterControlBlock={createFooterControlBlock}
createFooterBlock={createFooterBlock}
shouldBeCollapsedOnLeave={!(isOpenAvatarPopover || isOpenOrganizationPopover)}
shouldBeCollapsedOnLeave={
!(isOpenAvatarPopover || isOpenOrganizationPopover || isOpenSupportPopover)
}
/>
);
};
Expand Down
30 changes: 29 additions & 1 deletion app/src/layouts/common/appSidebar/appSidebar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@

&:hover {
background-color: $COLOR--darkmode-gray-500;

a {
color: $COLOR--white-two;
}
Expand Down Expand Up @@ -127,7 +128,7 @@
}
}

.user-control {
.user-control, .service-control {
width: 100%;
box-sizing: border-box;
padding: 0 8px;
Expand All @@ -137,3 +138,30 @@
@extend .hover;
}
}

.service-block {
position: relative;
width: 40px;
height: 48px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;

svg {
width: 20px;
height: 20px;
}

&.active-tooltip::after {
content: '';
position: absolute;
width: 8px;
height: 8px;
background-color: $COLOR--system-notification-marker;
border-radius: 50%;
border: 2px solid #222222;
right: 20%;
top: 20%;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*
* 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 PropTypes from 'prop-types';
import classNames from 'classnames/bind';
import { FormattedMessage, useIntl } from 'react-intl';
import OpenIcon from 'common/img/open-in-new-tab-inline.svg';
import React from 'react';
import { referenceDictionary, uniqueId } from 'common/utils';
import { showModalAction } from 'controllers/modal';
import { useDispatch, useSelector } from 'react-redux';
import { userIdSelector } from 'controllers/user';
import { setFAQOpenStatusTrue } from 'controllers/log/storageUtils';
import { messages } from 'layouts/common/appSidebar/helpAndService/messages';
import { LinkItem } from 'layouts/common/appSidebar/helpAndService/linkItem/linkItem';
import { referenceFAQDictionary } from 'common/utils/referenceDictionary';
import styles from './FAQContent.scss';

const cx = classNames.bind(styles);

export const FAQContent = ({ onFAQOpen, closeNavbar, closePopover }) => {
const { formatMessage } = useIntl();
onFAQOpen(true);
const userId = useSelector(userIdSelector);
setFAQOpenStatusTrue(userId);
const dispatch = useDispatch();

const FAQContentItems = [
{
linkTo: referenceFAQDictionary.configureReportingFAQ,
message: messages.configureReporting,
},
{
linkTo: referenceFAQDictionary.improvePerformanceFAQ,
message: messages.improvePerformance,
},
{
linkTo: referenceFAQDictionary.configureAnalyzerFAQ,
message: messages.configureAnalyzer,
},
{
linkTo: referenceFAQDictionary.integrateJiraFAQ,
message: messages.integrateJira,
},
{
linkTo: referenceFAQDictionary.configureCertificateFAQ,
message: messages.configureCertificate,
},
{
linkTo: referenceFAQDictionary.fileStorageOptionsFAQ,
message: messages.fileStorageOptions,
},
{
linkTo: referenceFAQDictionary.pricingOptionsFAQ,
message: messages.pricingOptions,
},
];
const openModal = () => {
dispatch(
showModalAction({
id: 'RequestSupportModal',
}),
);
};

return (
<>
{FAQContentItems.map((contentItem) => {
return (
<LinkItem
link={contentItem.linkTo}
content={formatMessage(contentItem.message)}
className={cx('menu-item')}
onClick={() => {
closePopover();
closeNavbar();
}}
key={`faq-${uniqueId()}`}
/>
);
})}
<p className={cx('assistance')}>
{formatMessage(messages.furtherAssistance, {
support: (data) => (
<LinkItem
link={referenceDictionary.rpEmail}
content={data}
icon={OpenIcon}
className={cx('inline-ref')}
/>
),
channel: (data) => (
<LinkItem
link={referenceDictionary.rpSlack}
content={data}
className={cx('inline-ref')}
icon={OpenIcon}
/>
),
})}
</p>
<div className={cx('divider')} />
<span className={cx('menu-item')} onClick={openModal}>
<FormattedMessage
id={'Sidebar.services.requestService'}
defaultMessage={'Request professional service'}
/>
</span>
</>
);
};

FAQContent.propTypes = {
onFAQOpen: PropTypes.func.isRequired,
closeNavbar: PropTypes.func.isRequired,
closePopover: PropTypes.func.isRequired,
};
Loading

0 comments on commit 505775d

Please sign in to comment.