+ );
+};
+
+FilterContent.propTypes = {
+ setIsOpen: PropTypes.func.isRequired,
+ setAppliedFiltersCount: PropTypes.func.isRequired,
+ onFilterChange: PropTypes.func.isRequired,
+ defaultFilters: PropTypes.object.isRequired,
+ initialFilters: PropTypes.array.isRequired,
+ filters: PropTypes.array.isRequired,
+ setFilters: PropTypes.func.isRequired,
+ filteredAction: PropTypes.func.isRequired,
+};
diff --git a/app/src/components/main/filterButton/filterContent/filterContent.scss b/app/src/components/main/filterButton/filterContent/filterContent.scss
new file mode 100644
index 0000000000..b760c08945
--- /dev/null
+++ b/app/src/components/main/filterButton/filterContent/filterContent.scss
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+.filter-popover-content {
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+}
+
+.filter-items {
+ display: flex;
+ flex-direction: column;
+}
+
+.actions {
+ display: flex;
+ justify-content: space-between;
+
+ .controls {
+ display: flex;
+ gap: 8px;
+ }
+}
diff --git a/app/src/components/main/filterButton/filterContent/filterInput/filterInput.jsx b/app/src/components/main/filterButton/filterContent/filterInput/filterInput.jsx
new file mode 100644
index 0000000000..8170bafad8
--- /dev/null
+++ b/app/src/components/main/filterButton/filterContent/filterInput/filterInput.jsx
@@ -0,0 +1,79 @@
+/*
+ * 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 classNames from 'classnames/bind';
+import { Dropdown, FieldText } from '@reportportal/ui-kit';
+import PropTypes from 'prop-types';
+import styles from './filterInput.scss';
+
+const cx = classNames.bind(styles);
+
+export const FilterInput = ({ filter, onFilter }) => {
+ const { filterName, options, value, condition, placeholder, title, withField, helpText } = filter;
+
+ const onChangeOption = (newValue) => {
+ onFilter({
+ [filterName]: {
+ ...filter,
+ ...(withField ? { condition: newValue } : { value: newValue }),
+ },
+ });
+ };
+
+ const onTextFieldChange = ({ target }) => {
+ if (helpText && !Number(target.value)) {
+ return;
+ }
+
+ onFilter({ [filterName]: { ...filter, value: target.value } });
+ };
+
+ const onClear = () => onFilter({ [filterName]: { ...filter, value: '' } });
+
+ return (
+
+ {title}
+
+
+ {withField && (
+
+
+
+ )}
+
+
+ );
+};
+
+FilterInput.propTypes = {
+ filter: PropTypes.object,
+ onFilter: PropTypes.func,
+};
diff --git a/app/src/components/main/filterButton/filterContent/filterInput/filterInput.scss b/app/src/components/main/filterButton/filterContent/filterInput/filterInput.scss
new file mode 100644
index 0000000000..4c37692b73
--- /dev/null
+++ b/app/src/components/main/filterButton/filterContent/filterInput/filterInput.scss
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+.filter-item {
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+ margin-bottom: 16px;
+
+ .label {
+ font-size: 13px;
+ line-height: 20px;
+ color: $COLOR--almost-black;
+ font-family: $FONT-ROBOTO-MEDIUM;
+ }
+
+ .container {
+ display: flex;
+ width: 100%;
+ gap: 8px;
+
+ .dropdown {
+ min-width: 156px;
+ width: 156px;
+ }
+
+ .input-field {
+ flex: 1;
+ }
+ }
+}
+
+.with-help-text {
+ margin-bottom: 0;
+}
+
+.input-field-container {
+ width: 100%;
+
+ &:last-child span {
+ color: $COLOR--e-400;
+ }
+
+ div.input-field {
+ width: 100%;
+ }
+}
diff --git a/app/src/components/main/filterButton/filterContent/filterInput/index.js b/app/src/components/main/filterButton/filterContent/filterInput/index.js
new file mode 100644
index 0000000000..92bef2de3a
--- /dev/null
+++ b/app/src/components/main/filterButton/filterContent/filterInput/index.js
@@ -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 { FilterInput } from './filterInput';
diff --git a/app/src/components/main/filterButton/filterContent/index.js b/app/src/components/main/filterButton/filterContent/index.js
new file mode 100644
index 0000000000..16b3e405f8
--- /dev/null
+++ b/app/src/components/main/filterButton/filterContent/index.js
@@ -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 { FilterContent } from './filterContent';
diff --git a/app/src/components/main/filterButton/filterContent/messages.js b/app/src/components/main/filterButton/filterContent/messages.js
new file mode 100644
index 0000000000..d798aa5f93
--- /dev/null
+++ b/app/src/components/main/filterButton/filterContent/messages.js
@@ -0,0 +1,24 @@
+/*
+ * 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 { defineMessages } from 'react-intl';
+
+export const messages = defineMessages({
+ clearAllFilters: {
+ id: 'ProjectsFilterPopover.clearAllFilters',
+ defaultMessage: 'Clear all filters',
+ },
+});
diff --git a/app/src/components/main/filterButton/index.jsx b/app/src/components/main/filterButton/index.jsx
new file mode 100644
index 0000000000..446d829301
--- /dev/null
+++ b/app/src/components/main/filterButton/index.jsx
@@ -0,0 +1,27 @@
+/*
+ * 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 { FilterButton } from './filterButton';
+export {
+ LAST_RUN_DATE_FILTER_NAME,
+ LAUNCHES_FILTER_NAME,
+ TEAMMATES_FILTER_NAME,
+ FILTER_NAME,
+ getContainmentComparisons,
+ getRangeComparisons,
+ getTimeRange,
+} from './constants';
+export { messages } from './messages';
diff --git a/app/src/components/main/filterButton/messages.js b/app/src/components/main/filterButton/messages.js
new file mode 100644
index 0000000000..e7333803e5
--- /dev/null
+++ b/app/src/components/main/filterButton/messages.js
@@ -0,0 +1,68 @@
+/*
+ * 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 { defineMessages } from 'react-intl';
+
+export const messages = defineMessages({
+ any: {
+ id: 'FilterButton.any',
+ defaultMessage: 'Any',
+ },
+ today: {
+ id: 'FilterButton.today',
+ defaultMessage: 'Today',
+ },
+ last2days: {
+ id: 'FilterButton.last2days',
+ defaultMessage: 'Last 2 days',
+ },
+ last7days: {
+ id: 'FilterButton.last7days',
+ defaultMessage: 'Last 7 days',
+ },
+ last30days: {
+ id: 'FilterButton.last30days',
+ defaultMessage: 'Last 30 days',
+ },
+ equals: {
+ id: 'FilterButton.equals',
+ defaultMessage: 'Equals',
+ },
+ greaterOrEqual: {
+ id: 'FilterButton.greaterOrEqual',
+ defaultMessage: 'Greater or equal',
+ },
+ lessOrEqual: {
+ id: 'FilterButton.lessOrEqual',
+ defaultMessage: 'Less or equal',
+ },
+ notEqual: {
+ id: 'FilterButton.notEqual',
+ defaultMessage: 'Not equal',
+ },
+ contains: {
+ id: 'FilterButton.contains',
+ defaultMessage: 'Contains',
+ },
+ notContains: {
+ id: 'FilterButton.notContains',
+ defaultMessage: 'Not contains',
+ },
+ helpText: {
+ id: 'FilterButton.helpText',
+ defaultMessage: 'Only digits are allowed',
+ },
+});
diff --git a/app/src/controllers/instance/events/utils.js b/app/src/controllers/instance/events/utils.js
index 5e3825cb94..2d40807b47 100644
--- a/app/src/controllers/instance/events/utils.js
+++ b/app/src/controllers/instance/events/utils.js
@@ -57,5 +57,7 @@ export const getAppliedFilters = (filters, projectKey) => {
};
});
- return { search_criterias: [...appliedFilters, projectIdFilterParam] };
+ return {
+ search_criterias: [...appliedFilters, ...(projectKey ? [projectIdFilterParam] : [])],
+ };
};
diff --git a/app/src/controllers/instance/organizations/actionCreators.js b/app/src/controllers/instance/organizations/actionCreators.js
index 46a7ea66f6..44eb3ea8f9 100644
--- a/app/src/controllers/instance/organizations/actionCreators.js
+++ b/app/src/controllers/instance/organizations/actionCreators.js
@@ -14,8 +14,12 @@
* limitations under the License.
*/
-import { FETCH_ORGANIZATIONS } from './constants';
+import { FETCH_ORGANIZATIONS, FETCH_FILTERED_ORGANIZATIONS } from './constants';
export const fetchOrganizationsAction = () => ({
type: FETCH_ORGANIZATIONS,
});
+
+export const fetchFilteredOrganizationsAction = () => ({
+ type: FETCH_FILTERED_ORGANIZATIONS,
+});
diff --git a/app/src/controllers/instance/organizations/constants.js b/app/src/controllers/instance/organizations/constants.js
index 1e93837fdd..32431cb22f 100644
--- a/app/src/controllers/instance/organizations/constants.js
+++ b/app/src/controllers/instance/organizations/constants.js
@@ -18,7 +18,9 @@ import { PAGE_KEY, SIZE_KEY } from 'controllers/pagination';
export const NAMESPACE = 'organizations';
+// TODO: After joining the filter and the search, leave one constant
export const FETCH_ORGANIZATIONS = 'fetchOrganizations';
+export const FETCH_FILTERED_ORGANIZATIONS = 'fetchFilteredOrganizations';
export const DEFAULT_PAGE_SIZE_OPTIONS = [10, 20, 50, 100];
export const DEFAULT_LIMITATION = 20;
export const initialPaginationState = {
diff --git a/app/src/controllers/instance/organizations/index.js b/app/src/controllers/instance/organizations/index.js
index b89052a05d..1763ffeded 100644
--- a/app/src/controllers/instance/organizations/index.js
+++ b/app/src/controllers/instance/organizations/index.js
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-export { FETCH_ORGANIZATIONS } from './constants';
-export { fetchOrganizationsAction } from './actionCreators';
+export { FETCH_ORGANIZATIONS, FETCH_FILTERED_ORGANIZATIONS } from './constants';
+export { fetchOrganizationsAction, fetchFilteredOrganizationsAction } from './actionCreators';
export { organizationsReducer } from './reducer';
export {
organizationsSelector,
diff --git a/app/src/controllers/instance/organizations/sagas.js b/app/src/controllers/instance/organizations/sagas.js
index 398cd30330..eecdfacf16 100644
--- a/app/src/controllers/instance/organizations/sagas.js
+++ b/app/src/controllers/instance/organizations/sagas.js
@@ -18,8 +18,9 @@ import { takeEvery, all, put, select } from 'redux-saga/effects';
import { URLS } from 'common/urls';
import { showDefaultErrorNotification } from 'controllers/notification';
import { fetchDataAction } from 'controllers/fetch';
+import { prepareQueryFilters } from 'components/filterEntities/utils';
import { querySelector } from './selectors';
-import { FETCH_ORGANIZATIONS, NAMESPACE } from './constants';
+import { FETCH_ORGANIZATIONS, FETCH_FILTERED_ORGANIZATIONS, NAMESPACE } from './constants';
function* fetchOrganizations() {
try {
@@ -35,6 +36,22 @@ function* watchFetchOrganizations() {
yield takeEvery(FETCH_ORGANIZATIONS, fetchOrganizations);
}
+function* fetchFilteredOrganizations() {
+ const filtersParams = yield select(querySelector);
+ const data = prepareQueryFilters(filtersParams);
+
+ yield put(
+ fetchDataAction(NAMESPACE)(URLS.organizationSearches(), {
+ method: 'post',
+ data,
+ }),
+ );
+}
+
+function* watchFetchFilteredProjects() {
+ yield takeEvery(FETCH_FILTERED_ORGANIZATIONS, fetchFilteredOrganizations);
+}
+
export function* organizationsSagas() {
- yield all([watchFetchOrganizations()]);
+ yield all([watchFetchOrganizations(), watchFetchFilteredProjects()]);
}
diff --git a/app/src/controllers/organization/projects/actionCreators.js b/app/src/controllers/organization/projects/actionCreators.js
index d6117f8c2a..5c2fd07c9b 100644
--- a/app/src/controllers/organization/projects/actionCreators.js
+++ b/app/src/controllers/organization/projects/actionCreators.js
@@ -14,7 +14,12 @@
* limitations under the License.
*/
-import { CREATE_PROJECT, DELETE_PROJECT, FETCH_ORGANIZATION_PROJECTS } from './constants';
+import {
+ CREATE_PROJECT,
+ DELETE_PROJECT,
+ FETCH_ORGANIZATION_PROJECTS,
+ FETCH_FILTERED_PROJECTS,
+} from './constants';
export const fetchOrganizationProjectsAction = (params) => {
return {
@@ -32,3 +37,7 @@ export const deleteProjectAction = (project) => ({
type: DELETE_PROJECT,
payload: project,
});
+
+export const fetchFilteredProjectAction = () => ({
+ type: FETCH_FILTERED_PROJECTS,
+});
diff --git a/app/src/controllers/organization/projects/constants.js b/app/src/controllers/organization/projects/constants.js
index c9f1abcb85..88d783b4d9 100644
--- a/app/src/controllers/organization/projects/constants.js
+++ b/app/src/controllers/organization/projects/constants.js
@@ -17,7 +17,9 @@
import { PAGE_KEY, SIZE_KEY } from 'controllers/pagination';
import { formatSortingString, SORTING_ASC } from 'controllers/sorting';
+// TODO: After joining the filter and the search, leave one constant
export const FETCH_ORGANIZATION_PROJECTS = 'fetchOrganizationProjects';
+export const FETCH_FILTERED_PROJECTS = 'fetchFilteredProjects';
export const NAMESPACE = 'organizationProjects';
export const CREATE_PROJECT = 'createProject';
export const DELETE_PROJECT = 'deleteProject';
diff --git a/app/src/controllers/organization/projects/index.js b/app/src/controllers/organization/projects/index.js
index 1c5865f409..b448d58f98 100644
--- a/app/src/controllers/organization/projects/index.js
+++ b/app/src/controllers/organization/projects/index.js
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-export { fetchOrganizationProjectsAction } from './actionCreators';
+export { fetchOrganizationProjectsAction, fetchFilteredProjectAction } from './actionCreators';
export { projectsReducer } from './reducer';
export { projectsPaginationSelector, projectsSelector, loadingSelector } from './selectors';
export { projectsSagas } from './sagas';
@@ -26,4 +26,5 @@ export {
DEFAULT_QUERY_PARAMS,
FETCH_ORGANIZATION_PROJECTS,
SORTING_KEY,
+ FETCH_FILTERED_PROJECTS,
} from './constants';
diff --git a/app/src/controllers/organization/projects/sagas.js b/app/src/controllers/organization/projects/sagas.js
index e06d9044fe..290d9801af 100644
--- a/app/src/controllers/organization/projects/sagas.js
+++ b/app/src/controllers/organization/projects/sagas.js
@@ -20,17 +20,19 @@ import { URLS } from 'common/urls';
import { fetch } from 'common/utils';
import { hideModalAction } from 'controllers/modal';
import { NOTIFICATION_TYPES, showNotification } from 'controllers/notification';
-import { fetchOrganizationBySlugAction } from '..';
-import { querySelector } from './selectors';
-import { activeOrganizationSelector } from '../selectors';
-import { fetchOrganizationProjectsAction } from './actionCreators';
+import { prepareQueryFilters } from 'components/filterEntities/utils';
import {
CREATE_PROJECT,
FETCH_ORGANIZATION_PROJECTS,
ERROR_CODES,
NAMESPACE,
DELETE_PROJECT,
+ FETCH_FILTERED_PROJECTS,
} from './constants';
+import { fetchOrganizationBySlugAction } from '..';
+import { querySelector } from './selectors';
+import { activeOrganizationIdSelector, activeOrganizationSelector } from '../selectors';
+import { fetchOrganizationProjectsAction } from './actionCreators';
function* fetchOrganizationProjects({ payload: organizationId }) {
const query = yield select(querySelector);
@@ -116,6 +118,29 @@ function* deleteProject({ payload: { projectId, projectName } }) {
function* watchDeleteProject() {
yield takeEvery(DELETE_PROJECT, deleteProject);
}
+
+function* fetchFilteredProjects() {
+ const activeOrganizationId = yield select(activeOrganizationIdSelector);
+ const filtersParams = yield select(querySelector);
+ const data = prepareQueryFilters(filtersParams);
+
+ yield put(
+ fetchDataAction(NAMESPACE)(URLS.organizationProjectsSearches(activeOrganizationId), {
+ method: 'post',
+ data,
+ }),
+ );
+}
+
+function* watchFetchFilteredProjects() {
+ yield takeEvery(FETCH_FILTERED_PROJECTS, fetchFilteredProjects);
+}
+
export function* projectsSagas() {
- yield all([watchFetchProjects(), watchCreateProject(), watchDeleteProject()]);
+ yield all([
+ watchFetchProjects(),
+ watchCreateProject(),
+ watchDeleteProject(),
+ watchFetchFilteredProjects(),
+ ]);
}
diff --git a/app/src/controllers/organization/projects/selectors.js b/app/src/controllers/organization/projects/selectors.js
index f88be72964..14e0ad37f1 100644
--- a/app/src/controllers/organization/projects/selectors.js
+++ b/app/src/controllers/organization/projects/selectors.js
@@ -16,8 +16,8 @@
import { createAlternativeQueryParametersSelector } from 'controllers/pages/selectors';
import { SORTING_ASC } from 'controllers/sorting';
-import { DEFAULT_PAGINATION, NAMESPACE, SORTING_KEY } from './constants';
import { organizationSelector } from '../selectors';
+import { DEFAULT_PAGINATION, NAMESPACE, SORTING_KEY } from './constants';
const domainSelector = (state) => organizationSelector(state).projects || {};
diff --git a/app/src/controllers/pages/selectors.js b/app/src/controllers/pages/selectors.js
index efd7de301e..6ec1c1623d 100644
--- a/app/src/controllers/pages/selectors.js
+++ b/app/src/controllers/pages/selectors.js
@@ -17,7 +17,7 @@
import { createSelector } from 'reselect';
import { extractNamespacedQuery } from 'common/utils/routingUtils';
import { DEFAULT_PAGINATION, SIZE_KEY, PAGE_KEY } from 'controllers/pagination/constants';
-import { SORTING_KEY } from 'controllers/sorting/constants';
+import { SORTING_KEY, SORTING_ORDER_KEY } from 'controllers/sorting/constants';
import { getStorageItem } from 'common/utils/storageUtils';
import {
activeProjectSelector,
@@ -148,7 +148,7 @@ export const createAlternativeQueryParametersSelector = ({
sortingKey,
namespace,
}),
- ({ [SIZE_KEY]: limit, [SORTING_KEY]: sort, [PAGE_KEY]: pageNumber, ...rest }) => {
+ ({ [SIZE_KEY]: limit, [SORTING_ORDER_KEY]: sort, [PAGE_KEY]: pageNumber, ...rest }) => {
return { ...getAlternativePaginationAndSortParams(sort, limit, pageNumber), ...rest };
},
);
diff --git a/app/src/controllers/sorting/constants.js b/app/src/controllers/sorting/constants.js
index 985b404dc6..ebd451eb17 100644
--- a/app/src/controllers/sorting/constants.js
+++ b/app/src/controllers/sorting/constants.js
@@ -17,3 +17,4 @@
export const SORTING_ASC = 'ASC';
export const SORTING_DESC = 'DESC';
export const SORTING_KEY = 'page.sort';
+export const SORTING_ORDER_KEY = 'order';
diff --git a/app/src/pages/inside/projectSettingsPageContainer/content/notifications/modals/addEditNotificationModal/addEditNotificationModal.jsx b/app/src/pages/inside/projectSettingsPageContainer/content/notifications/modals/addEditNotificationModal/addEditNotificationModal.jsx
index 7b5473d9f4..505c99a860 100644
--- a/app/src/pages/inside/projectSettingsPageContainer/content/notifications/modals/addEditNotificationModal/addEditNotificationModal.jsx
+++ b/app/src/pages/inside/projectSettingsPageContainer/content/notifications/modals/addEditNotificationModal/addEditNotificationModal.jsx
@@ -37,7 +37,7 @@ import { EMAIL } from 'common/constants/pluginNames';
import { FieldTextFlex } from 'componentLibrary/fieldTextFlex';
import { ruleField } from 'pages/inside/projectSettingsPageContainer/content/notifications/propTypes';
import { fetchProjectAction } from 'controllers/project/actionCreators';
-import { projectIdSelector } from 'controllers/pages';
+import { projectKeySelector } from 'controllers/project';
import { capitalizeWord } from '../util';
import { RecipientsContainer } from './recipientsContainer';
import { LaunchNamesContainer } from './launchNamesContainer';
@@ -215,14 +215,14 @@ const AddEditNotificationModal = ({
}) => {
const { formatMessage } = useIntl();
const dispatch = useDispatch();
- const projectId = useSelector(projectIdSelector);
+ const projectKey = useSelector(projectKeySelector);
const [isEditorShown, setShowEditor] = React.useState(data.notification.attributes.length > 0);
const attributesValue =
useSelector((state) => attributesValueSelector(state, ATTRIBUTES_FIELD_KEY)) ?? [];
useEffect(() => {
initialize(data.notification);
- dispatch(fetchProjectAction(projectId, false));
+ dispatch(fetchProjectAction(projectKey, false));
}, []);
const caseOptions = [
diff --git a/app/src/pages/instance/organizationsPage/organizationsPage.jsx b/app/src/pages/instance/organizationsPage/organizationsPage.jsx
index 57f0568501..394ce1c0db 100644
--- a/app/src/pages/instance/organizationsPage/organizationsPage.jsx
+++ b/app/src/pages/instance/organizationsPage/organizationsPage.jsx
@@ -49,6 +49,7 @@ export const OrganizationsPage = () => {
const isOrganizationsLoading = useSelector(organizationsListLoadingSelector);
const userId = useSelector(userIdSelector);
const [searchValue, setSearchValue] = useState(null);
+ const [appliedFiltersCount, setAppliedFiltersCount] = useState(0);
const isEmptyOrganizations = !isOrganizationsLoading && organizationsList.length === 0;
const [isOpenTableView, setIsOpenTableView] = useState(
getStorageItem(`${userId}_settings`)?.organizationsPanel === TABLE_VIEW,
@@ -73,7 +74,7 @@ export const OrganizationsPage = () => {
);
}
- return searchValue === null ? (
+ return searchValue === null && appliedFiltersCount === 0 ? (
{
openPanelView={openPanelView}
openTableView={openTableView}
isOpenTableView={isOpenTableView}
+ appliedFiltersCount={appliedFiltersCount}
+ setAppliedFiltersCount={setAppliedFiltersCount}
/>
{isEmptyOrganizations ? (
getEmptyPageState()
diff --git a/app/src/pages/instance/organizationsPage/organizationsPageHeader/organizationsFilter/index.js b/app/src/pages/instance/organizationsPage/organizationsPageHeader/organizationsFilter/index.js
new file mode 100644
index 0000000000..36998207a6
--- /dev/null
+++ b/app/src/pages/instance/organizationsPage/organizationsPageHeader/organizationsFilter/index.js
@@ -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 { OrganizationsFilter } from './organizationsFilter';
diff --git a/app/src/pages/instance/organizationsPage/organizationsPageHeader/organizationsFilter/messages.js b/app/src/pages/instance/organizationsPage/organizationsPageHeader/organizationsFilter/messages.js
new file mode 100644
index 0000000000..43a51fc83e
--- /dev/null
+++ b/app/src/pages/instance/organizationsPage/organizationsPageHeader/organizationsFilter/messages.js
@@ -0,0 +1,52 @@
+/*
+ * 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 { defineMessages } from 'react-intl';
+
+export const messages = defineMessages({
+ lastRunDate: {
+ id: 'OrganizationsFilter.lastRunDate',
+ defaultMessage: 'Last Run Date',
+ },
+ lastRunDatePlaceholder: {
+ id: 'OrganizationsFilter.lastRunDatePlaceholder',
+ defaultMessage: 'Any',
+ },
+ launches: {
+ id: 'OrganizationsFilter.launches',
+ defaultMessage: 'Launches',
+ },
+ launchesPlaceholder: {
+ id: 'OrganizationsFilter.launchesPlaceholder',
+ defaultMessage: 'Enter the number of launches',
+ },
+ users: {
+ id: 'OrganizationsFilter.users',
+ defaultMessage: 'Users',
+ },
+ usersPlaceholder: {
+ id: 'OrganizationsFilter.usersPlaceholder',
+ defaultMessage: 'Enter the number of members',
+ },
+ name: {
+ id: 'OrganizationsFilter.name',
+ defaultMessage: 'Organization name',
+ },
+ namePlaceholder: {
+ id: 'OrganizationsFilter.namePlaceholder',
+ defaultMessage: 'Enter part of the name',
+ },
+});
diff --git a/app/src/pages/instance/organizationsPage/organizationsPageHeader/organizationsFilter/organizationsFilter.jsx b/app/src/pages/instance/organizationsPage/organizationsPageHeader/organizationsFilter/organizationsFilter.jsx
new file mode 100644
index 0000000000..2eb3126ca6
--- /dev/null
+++ b/app/src/pages/instance/organizationsPage/organizationsPageHeader/organizationsFilter/organizationsFilter.jsx
@@ -0,0 +1,112 @@
+/*
+ * 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 { useIntl } from 'react-intl';
+import PropTypes from 'prop-types';
+import { useDispatch } from 'react-redux';
+import {
+ LAUNCHES_FILTER_NAME,
+ FILTER_NAME,
+ TEAMMATES_FILTER_NAME,
+ LAST_RUN_DATE_FILTER_NAME,
+ getContainmentComparisons,
+ getRangeComparisons,
+ getTimeRange,
+ messages as helpMessage,
+} from 'components/main/filterButton';
+import { FilterButton } from 'components/main/filterButton/filterButton';
+import { fetchFilteredOrganizationsAction } from 'controllers/instance/organizations';
+import { CONDITION_BETWEEN } from 'components/filterEntities/constants';
+import { messages } from './messages';
+
+export const OrganizationsFilter = ({
+ entities,
+ onFilterChange,
+ appliedFiltersCount,
+ setAppliedFiltersCount,
+}) => {
+ const { formatMessage } = useIntl();
+ const dispatch = useDispatch();
+
+ const timeRange = getTimeRange(formatMessage);
+ const rangeComparisons = getRangeComparisons(formatMessage);
+ const containmentComparisons = getContainmentComparisons(formatMessage);
+
+ const filters = {
+ [LAST_RUN_DATE_FILTER_NAME]: {
+ filterName: LAST_RUN_DATE_FILTER_NAME,
+ value: timeRange[0].value,
+ title: formatMessage(messages.lastRunDate),
+ options: timeRange,
+ condition: CONDITION_BETWEEN.toUpperCase(),
+ placeholder: formatMessage(messages.lastRunDatePlaceholder),
+ },
+ [LAUNCHES_FILTER_NAME]: {
+ filterName: LAUNCHES_FILTER_NAME,
+ value: '',
+ title: formatMessage(messages.launches),
+ placeholder: formatMessage(messages.launchesPlaceholder),
+ options: rangeComparisons,
+ condition: rangeComparisons[0].value,
+ helpText: formatMessage(helpMessage.helpText),
+ withField: true,
+ },
+ [TEAMMATES_FILTER_NAME]: {
+ filterName: TEAMMATES_FILTER_NAME,
+ value: '',
+ title: formatMessage(messages.users),
+ placeholder: formatMessage(messages.usersPlaceholder),
+ options: rangeComparisons,
+ condition: rangeComparisons[0].value,
+ helpText: formatMessage(helpMessage.helpText),
+ withField: true,
+ },
+ [FILTER_NAME]: {
+ filterName: FILTER_NAME,
+ value: '',
+ title: formatMessage(messages.name),
+ placeholder: formatMessage(messages.namePlaceholder),
+ options: containmentComparisons,
+ condition: containmentComparisons[0].value,
+ withField: true,
+ },
+ };
+
+ return (
+ dispatch(fetchFilteredOrganizationsAction())}
+ />
+ );
+};
+
+OrganizationsFilter.propTypes = {
+ entities: PropTypes.objectOf(
+ PropTypes.shape({
+ filter_key: PropTypes.string,
+ value: PropTypes.string,
+ condition: PropTypes.string,
+ }),
+ ),
+ onFilterChange: PropTypes.func,
+ appliedFiltersCount: PropTypes.number,
+ setAppliedFiltersCount: PropTypes.func,
+ defaultFilters: PropTypes.object,
+};
diff --git a/app/src/pages/instance/organizationsPage/organizationsPageHeader/organizationsPageHeader.jsx b/app/src/pages/instance/organizationsPage/organizationsPageHeader/organizationsPageHeader.jsx
index 9ffd5e96aa..ce3692bae0 100644
--- a/app/src/pages/instance/organizationsPage/organizationsPageHeader/organizationsPageHeader.jsx
+++ b/app/src/pages/instance/organizationsPage/organizationsPageHeader/organizationsPageHeader.jsx
@@ -15,21 +15,22 @@
*/
import React from 'react';
+import { useSelector } from 'react-redux';
import PropTypes from 'prop-types';
import Parser from 'html-react-parser';
import classNames from 'classnames/bind';
-import filterIcon from 'common/img/newIcons/filters-outline-inline.svg';
+import { BaseIconButton } from '@reportportal/ui-kit';
import { useIntl } from 'react-intl';
import { SearchField } from 'components/fields/searchField';
import { SEARCH_KEY } from 'controllers/organization/projects/constants';
import { withFilter } from 'controllers/filter';
import { NAMESPACE } from 'controllers/instance/organizations/constants';
-import { useSelector } from 'react-redux';
import { organizationsListLoadingSelector } from 'controllers/instance/organizations';
import { ORGANIZATION_PAGE_EVENTS } from 'components/main/analytics/events/ga4Events/organizationsPageEvents';
-import { BaseIconButton } from '@reportportal/ui-kit';
+import { withFilterEntitiesURL } from 'components/filterEntities/containers';
import PanelViewIcon from '../img/panel-view-inline.svg';
import TableViewIcon from '../img/table-view-inline.svg';
+import { OrganizationsFilter } from './organizationsFilter';
import { messages } from '../messages';
import styles from './organizationsPageHeader.scss';
@@ -39,6 +40,8 @@ const SearchFieldWithFilter = withFilter({ filterKey: SEARCH_KEY, namespace: NAM
SearchField,
);
+const FiltersFields = withFilterEntitiesURL(NAMESPACE)(OrganizationsFilter);
+
export const OrganizationsPageHeader = ({
isEmpty,
searchValue,
@@ -46,6 +49,8 @@ export const OrganizationsPageHeader = ({
openPanelView,
openTableView,
isOpenTableView,
+ appliedFiltersCount,
+ setAppliedFiltersCount,
}) => {
const { formatMessage } = useIntl();
const projectsLoading = useSelector(organizationsListLoadingSelector);
@@ -64,7 +69,11 @@ export const OrganizationsPageHeader = ({
placeholder={formatMessage(messages.searchPlaceholder)}
event={ORGANIZATION_PAGE_EVENTS.SEARCH_ORGANIZATION_FIELD}
/>
- {Parser(filterIcon)}
+ {
const isProjectsEmpty = !projectsLoading && projects.length === 0;
const [searchValue, setSearchValue] = useState(null);
+ const [appliedFiltersCount, setAppliedFiltersCount] = useState(0);
const showCreateProjectModal = () => {
dispatch(
@@ -91,7 +92,7 @@ export const OrganizationProjectsPage = () => {
};
const getEmptyPageState = () => {
- return searchValue === null ? (
+ return searchValue === null && appliedFiltersCount === 0 ? (
{
onCreateProject={showCreateProjectModal}
searchValue={searchValue}
setSearchValue={setSearchValue}
+ appliedFiltersCount={appliedFiltersCount}
+ setAppliedFiltersCount={setAppliedFiltersCount}
/>
{renderContent()}
diff --git a/app/src/pages/organization/organizationProjectsPage/projectsPageHeader/projectsFilter/index.js b/app/src/pages/organization/organizationProjectsPage/projectsPageHeader/projectsFilter/index.js
new file mode 100644
index 0000000000..e788469ec0
--- /dev/null
+++ b/app/src/pages/organization/organizationProjectsPage/projectsPageHeader/projectsFilter/index.js
@@ -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 { ProjectsFilter } from './projectsFilter';
diff --git a/app/src/pages/organization/organizationProjectsPage/projectsPageHeader/projectsFilter/messages.js b/app/src/pages/organization/organizationProjectsPage/projectsPageHeader/projectsFilter/messages.js
new file mode 100644
index 0000000000..9911e14050
--- /dev/null
+++ b/app/src/pages/organization/organizationProjectsPage/projectsPageHeader/projectsFilter/messages.js
@@ -0,0 +1,52 @@
+/*
+ * 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 { defineMessages } from 'react-intl';
+
+export const messages = defineMessages({
+ lastRunDate: {
+ id: 'ProjectsFilter.lastRunDate',
+ defaultMessage: 'Last Run Date',
+ },
+ lastRunDatePlaceholder: {
+ id: 'ProjectsFilter.lastRunDatePlaceholder',
+ defaultMessage: 'Any',
+ },
+ launches: {
+ id: 'ProjectsFilter.launches',
+ defaultMessage: 'Launches',
+ },
+ launchesPlaceholder: {
+ id: 'ProjectsFilter.launchesPlaceholder',
+ defaultMessage: 'Enter the number of launches',
+ },
+ users: {
+ id: 'ProjectsFilter.users',
+ defaultMessage: 'Teammates',
+ },
+ usersPlaceholder: {
+ id: 'ProjectsFilter.usersPlaceholder',
+ defaultMessage: 'Enter the number of members',
+ },
+ name: {
+ id: 'ProjectsFilter.name',
+ defaultMessage: 'Project Name',
+ },
+ namePlaceholder: {
+ id: 'ProjectsFilter.namePlaceholder',
+ defaultMessage: 'Enter part of the name',
+ },
+});
diff --git a/app/src/pages/organization/organizationProjectsPage/projectsPageHeader/projectsFilter/projectsFilter.jsx b/app/src/pages/organization/organizationProjectsPage/projectsPageHeader/projectsFilter/projectsFilter.jsx
new file mode 100644
index 0000000000..5c0d918cf1
--- /dev/null
+++ b/app/src/pages/organization/organizationProjectsPage/projectsPageHeader/projectsFilter/projectsFilter.jsx
@@ -0,0 +1,112 @@
+/*
+ * 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 { useIntl } from 'react-intl';
+import { useDispatch } from 'react-redux';
+import PropTypes from 'prop-types';
+import {
+ LAUNCHES_FILTER_NAME,
+ FILTER_NAME,
+ TEAMMATES_FILTER_NAME,
+ LAST_RUN_DATE_FILTER_NAME,
+ getContainmentComparisons,
+ getRangeComparisons,
+ getTimeRange,
+ messages as helpMessage,
+} from 'components/main/filterButton';
+import { FilterButton } from 'components/main/filterButton/filterButton';
+import { fetchFilteredProjectAction } from 'controllers/organization/projects';
+import { CONDITION_BETWEEN } from 'components/filterEntities/constants';
+import { messages } from './messages';
+
+export const ProjectsFilter = ({
+ entities,
+ onFilterChange,
+ appliedFiltersCount,
+ setAppliedFiltersCount,
+}) => {
+ const { formatMessage } = useIntl();
+ const dispatch = useDispatch();
+
+ const timeRange = getTimeRange(formatMessage);
+ const rangeComparisons = getRangeComparisons(formatMessage);
+ const containmentComparisons = getContainmentComparisons(formatMessage);
+
+ const filters = {
+ [LAST_RUN_DATE_FILTER_NAME]: {
+ filterName: LAST_RUN_DATE_FILTER_NAME,
+ value: timeRange[0].value,
+ title: formatMessage(messages.lastRunDate),
+ options: timeRange,
+ condition: CONDITION_BETWEEN.toUpperCase(),
+ placeholder: formatMessage(messages.lastRunDatePlaceholder),
+ },
+ [LAUNCHES_FILTER_NAME]: {
+ filterName: LAUNCHES_FILTER_NAME,
+ value: '',
+ title: formatMessage(messages.launches),
+ placeholder: formatMessage(messages.launchesPlaceholder),
+ options: rangeComparisons,
+ condition: rangeComparisons[0].value,
+ helpText: formatMessage(helpMessage.helpText),
+ withField: true,
+ },
+ [TEAMMATES_FILTER_NAME]: {
+ filterName: TEAMMATES_FILTER_NAME,
+ value: '',
+ title: formatMessage(messages.users),
+ placeholder: formatMessage(messages.usersPlaceholder),
+ options: rangeComparisons,
+ condition: rangeComparisons[0].value,
+ helpText: formatMessage(helpMessage.helpText),
+ withField: true,
+ },
+ [FILTER_NAME]: {
+ filterName: FILTER_NAME,
+ value: '',
+ title: formatMessage(messages.name),
+ placeholder: formatMessage(messages.namePlaceholder),
+ options: containmentComparisons,
+ condition: containmentComparisons[0].value,
+ withField: true,
+ },
+ };
+
+ return (
+ dispatch(fetchFilteredProjectAction())}
+ />
+ );
+};
+
+ProjectsFilter.propTypes = {
+ entities: PropTypes.objectOf(
+ PropTypes.shape({
+ filter_key: PropTypes.string,
+ value: PropTypes.string,
+ condition: PropTypes.string,
+ }),
+ ),
+ onFilterChange: PropTypes.func,
+ appliedFiltersCount: PropTypes.number,
+ setAppliedFiltersCount: PropTypes.func,
+ defaultFilters: PropTypes.object,
+};
diff --git a/app/src/pages/organization/organizationProjectsPage/projectsPageHeader/projectsPageHeader.jsx b/app/src/pages/organization/organizationProjectsPage/projectsPageHeader/projectsPageHeader.jsx
index ab181c6aff..1840c40299 100644
--- a/app/src/pages/organization/organizationProjectsPage/projectsPageHeader/projectsPageHeader.jsx
+++ b/app/src/pages/organization/organizationProjectsPage/projectsPageHeader/projectsPageHeader.jsx
@@ -21,17 +21,18 @@ import Parser from 'html-react-parser';
import { Button, PlusIcon } from '@reportportal/ui-kit';
import classNames from 'classnames/bind';
import { ORGANIZATIONS_PAGE } from 'controllers/pages';
-import filterIcon from 'common/img/newIcons/filters-outline-inline.svg';
import { Breadcrumbs } from 'componentLibrary/breadcrumbs';
import { activeOrganizationSelector } from 'controllers/organization';
import { loadingSelector } from 'controllers/organization/projects';
import { SearchField } from 'components/fields/searchField';
import { SEARCH_KEY, NAMESPACE } from 'controllers/organization/projects/constants';
import { withFilter } from 'controllers/filter';
+import { withFilterEntitiesURL } from 'components/filterEntities/containers';
import projectsIcon from './img/projects-inline.svg';
-import styles from './projectsPageHeader.scss';
-import { messages } from '../messages';
import userIcon from './img/user-inline.svg';
+import { ProjectsFilter } from './projectsFilter';
+import { messages } from '../messages';
+import styles from './projectsPageHeader.scss';
const cx = classNames.bind(styles);
@@ -39,11 +40,15 @@ const SearchFieldWithFilter = withFilter({ filterKey: SEARCH_KEY, namespace: NAM
SearchField,
);
+const FiltersFields = withFilterEntitiesURL(NAMESPACE)(ProjectsFilter);
+
export const ProjectsPageHeader = ({
hasPermission,
onCreateProject,
searchValue,
setSearchValue,
+ appliedFiltersCount,
+ setAppliedFiltersCount,
}) => {
const { formatMessage } = useIntl();
const organization = useSelector(activeOrganizationSelector);
@@ -95,7 +100,11 @@ export const ProjectsPageHeader = ({
setSearchValue={setSearchValue}
placeholder={formatMessage(messages.searchPlaceholder)}
/>
- {Parser(filterIcon)}
+
)}
{isNotEmpty && hasPermission && (
@@ -114,6 +123,8 @@ ProjectsPageHeader.propTypes = {
onCreateProject: PropTypes.func.isRequired,
searchValue: PropTypes.string || null,
setSearchValue: PropTypes.func.isRequired,
+ appliedFiltersCount: PropTypes.number,
+ setAppliedFiltersCount: PropTypes.func,
};
ProjectsPageHeader.defaultProps = {
diff --git a/app/src/pages/organization/projectTeamPage/projectTeamPageHeader/projectTeamPageHeader.jsx b/app/src/pages/organization/projectTeamPage/projectTeamPageHeader/projectTeamPageHeader.jsx
index bfcff49831..63c765e609 100644
--- a/app/src/pages/organization/projectTeamPage/projectTeamPageHeader/projectTeamPageHeader.jsx
+++ b/app/src/pages/organization/projectTeamPage/projectTeamPageHeader/projectTeamPageHeader.jsx
@@ -17,15 +17,13 @@
import React from 'react';
import { useSelector } from 'react-redux';
import PropTypes from 'prop-types';
-import Parser from 'html-react-parser';
import classNames from 'classnames/bind';
-import { Button } from '@reportportal/ui-kit';
+import { Button, FilterOutlineIcon } from '@reportportal/ui-kit';
import { useIntl } from 'react-intl';
import { projectMembersSelector, projectNameSelector } from 'controllers/project';
import { SearchField } from 'components/fields/searchField';
import { NAMESPACE, SEARCH_KEY } from 'controllers/members/constants';
import { withFilter } from 'controllers/filter';
-import filterIcon from 'common/img/newIcons/filters-outline-inline.svg';
import { PROJECT_PAGE_EVENTS } from 'components/main/analytics/events/ga4Events/projectPageEvents';
import { activeOrganizationNameSelector } from 'controllers/organization';
import { messages } from '../../common/membersPage/membersPageHeader/messages';
@@ -68,7 +66,9 @@ export const ProjectTeamPageHeader = ({
placeholder={formatMessage(messages.searchPlaceholder)}
event={PROJECT_PAGE_EVENTS.SEARCH_PROJECT_TEAM_FIELD}
/>
- {Parser(filterIcon)}
+
+
+
{hasPermission && (