Skip to content

Commit

Permalink
EPMRPP-91199 || Search for organizations and projects (#3959)
Browse files Browse the repository at this point in the history
* EPMRPP-91199 || Search for organizations and projects

* EPMRPP-91199 || fix case insensitive search

* EPMRPP-92480 || code review fix - 1

* EPMRPP-92480 || code review fix - 2

* EPMRPP-92480 || ui-kit version update

---------

Co-authored-by: maria-hambardzumian <maria_hambardzumyan@epam.com>
  • Loading branch information
BlazarQSO and maria-hambardzumian authored Aug 16, 2024
1 parent 2932681 commit 21c3559
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 21 deletions.
8 changes: 4 additions & 4 deletions app/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"@formatjs/intl-pluralrules": "1.3.9",
"@formatjs/intl-relativetimeformat": "4.5.1",
"@formatjs/intl-utils": "1.6.0",
"@reportportal/ui-kit": "^0.0.1-alpha.16",
"@reportportal/ui-kit": "^0.0.1-alpha.18",
"axios": "1.6.4",
"c3": "0.7.20",
"chart.js": "2.9.4",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import PropTypes from 'prop-types';
import classNames from 'classnames/bind';
import { useIntl, defineMessages } from 'react-intl';
import Parser from 'html-react-parser';
import { useLayoutEffect, useRef, useState } from 'react';
import { useEffect, useLayoutEffect, useRef, useState } from 'react';
import { NavLink } from 'components/main/navLink';
import { ORGANIZATION_PROJECTS_PAGE } from 'controllers/pages/constants';
import ArrowDownIcon from './img/arrow-down-inline.svg';
Expand All @@ -45,6 +45,7 @@ export const OrganizationsItem = ({
isActive,
onClick,
currentProject,
isAllOpen,
}) => {
const { formatMessage } = useIntl();
const [isCollapsed, setIsCollapsed] = useState(isOpen);
Expand All @@ -61,6 +62,10 @@ export const OrganizationsItem = ({
}
}, [isActive]);

useEffect(() => {
setIsCollapsed(isAllOpen);
}, [isAllOpen]);

const onShowOpenButton = () => {
setIsShowOpenButton(true);
};
Expand Down Expand Up @@ -168,6 +173,7 @@ OrganizationsItem.propTypes = {
organizationSlug: PropTypes.string.isRequired,
projects: PropTypes.array.isRequired,
isOpen: PropTypes.bool.isRequired,
isAllOpen: PropTypes.bool.isRequired,
isActive: PropTypes.bool.isRequired,
onClick: PropTypes.func.isRequired,
currentProject: PropTypes.string.isRequired,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,18 @@
* limitations under the License.
*/

import { useMemo, useState } from 'react';
import PropTypes from 'prop-types';
import { useIntl, defineMessages } from 'react-intl';
import { FieldText, SearchIcon, ThemeProvider } from '@reportportal/ui-kit';
import classNames from 'classnames/bind';
import { useSelector } from 'react-redux';
import { availableProjectsSelector } from 'controllers/user';
import { urlProjectSlugSelector, urlOrganizationSlugSelector } from 'controllers/pages';
import { ScrollWrapper } from 'components/main/scrollWrapper';
import { ALL_ORGANIZATIONS_PAGE } from 'controllers/pages/constants';
import { NavLink } from 'components/main/navLink';
import { COMMON_LOCALE_KEYS } from 'common/constants/localization';
import { OrganizationsItem } from './organizationsItem';
import styles from './organizationsPopover.scss';

Expand All @@ -45,15 +48,59 @@ export const OrganizationsPopover = ({ closePopover, closeSidebar }) => {
const availableProjects = useSelector(availableProjectsSelector);
const currentOrganization = useSelector(urlOrganizationSlugSelector);
const projectSlug = useSelector(urlProjectSlugSelector);
const [valueSearch, setValueSearch] = useState('');
const maxHeightPopover = window.innerHeight - MARGIN_TOP_AND_MARGIN_BOTTOM;

const filteredProjects = useMemo(
() =>
availableProjects.reduce((acc, { organizationSlug, organizationName, projects }) => {
const isOrganization = organizationName.toLowerCase().includes(valueSearch.toLowerCase());
const searchProjects = projects.filter(({ projectName }) =>
projectName.toLowerCase().includes(valueSearch.toLowerCase()),
);

return isOrganization || searchProjects.length > 0
? [
...acc,
{
organizationSlug,
organizationName,
projects: searchProjects,
},
]
: acc;
}, []),
[valueSearch, availableProjects],
);

const onClose = () => {
closeSidebar();
closePopover();
};

const handleChange = (event) => {
setValueSearch(event.target.value);
};

const handleClear = () => {
setValueSearch('');
};

return (
<div className={cx('organizations-popover')}>
<div className={cx('organizations-search')}>
<ThemeProvider theme="dark">
<FieldText
startIcon={<SearchIcon />}
placeholder={formatMessage(COMMON_LOCALE_KEYS.SEARCH)}
defaultWidth={false}
value={valueSearch}
onChange={handleChange}
onClear={handleClear}
clearable
/>
</ThemeProvider>
</div>
{availableProjects.length > 0 && (
<>
<div className={cx('all-organizations')}>
Expand All @@ -69,28 +116,37 @@ export const OrganizationsPopover = ({ closePopover, closeSidebar }) => {
<div className={cx('divider')} />
</>
)}
<div className={cx('organizations-assignments')}>
{formatMessage(messages.assignmentsList)}
</div>
{filteredProjects.length > 0 && (
<div className={cx('organizations-assignments')}>
{formatMessage(messages.assignmentsList)}
</div>
)}
<ScrollWrapper
autoHide
autoHeight
autoHeightMax={maxHeightPopover}
hideTracksWhenNotNeeded
className={cx('scroll-wrapper')}
>
{availableProjects.map(({ organizationName, organizationSlug, projects }) => (
<OrganizationsItem
organizationName={organizationName}
organizationSlug={organizationSlug}
projects={projects}
onClick={onClose}
isOpen={currentOrganization === organizationSlug}
isActive={currentOrganization === organizationSlug && !projectSlug}
currentProject={projectSlug}
key={`${organizationSlug}-${projectSlug}`}
/>
))}
{filteredProjects.length > 0 ? (
filteredProjects.map(({ organizationName, organizationSlug, projects }) => (
<OrganizationsItem
organizationName={organizationName}
organizationSlug={organizationSlug}
projects={projects}
onClick={onClose}
isOpen={currentOrganization === organizationSlug}
isActive={currentOrganization === organizationSlug && !projectSlug}
currentProject={projectSlug}
key={`${organizationSlug}-${projectSlug}`}
isAllOpen={currentOrganization === organizationSlug || !!valueSearch}
/>
))
) : (
<div className={cx('organizations-empty-state')}>
{formatMessage(COMMON_LOCALE_KEYS.NO_RESULTS)}
</div>
)}
</ScrollWrapper>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,15 @@
color: $COLOR--darkmode-gray-150;
font-family: $FONT-ROBOTO-MEDIUM;
}

.organizations-empty-state {
width: 300px;
height: 100px;
font-size: 13px;
line-height: 20px;
font-family: $FONT-ROBOTO-REGULAR;
color: $COLOR--darkmode-gray-150;
display: flex;
align-items: center;
justify-content: center;
}

0 comments on commit 21c3559

Please sign in to comment.