{children}
diff --git a/app/src/layouts/common/sidebar/supportBlock/supportBlock.jsx b/app/src/layouts/common/sidebar/supportBlock/supportBlock.jsx
index 5b97a2c2d8..6adce6ce76 100644
--- a/app/src/layouts/common/sidebar/supportBlock/supportBlock.jsx
+++ b/app/src/layouts/common/sidebar/supportBlock/supportBlock.jsx
@@ -59,7 +59,7 @@ export const SupportBlock = ({ options }) => {
useEffect(() => {
const handleClickOutside = (event) => {
- if (wrapperRef && wrapperRef.current && !wrapperRef.current.contains(event.target)) {
+ if (!wrapperRef?.current?.contains(event.target)) {
setModalShown(false);
}
};
diff --git a/app/src/layouts/common/sidebar/userBlock/userBlock.jsx b/app/src/layouts/common/sidebar/userBlock/userBlock.jsx
index 20ec539715..143a63c19d 100644
--- a/app/src/layouts/common/sidebar/userBlock/userBlock.jsx
+++ b/app/src/layouts/common/sidebar/userBlock/userBlock.jsx
@@ -112,12 +112,7 @@ export class UserBlock extends Component {
};
handleOutsideClick = (e) => {
- if (
- this.controlNode &&
- this.controlNode.current &&
- !this.controlNode.current.contains(e.target) &&
- this.state.menuOpened
- ) {
+ if (!this.controlNode?.current?.contains(e.target) && this.state.menuOpened) {
this.setState({ menuOpened: false });
}
};
diff --git a/app/src/layouts/settingsLayout/footer/footer.scss b/app/src/layouts/settingsLayout/footer/footer.scss
index 5ff6d25b9e..8ad3955d2d 100644
--- a/app/src/layouts/settingsLayout/footer/footer.scss
+++ b/app/src/layouts/settingsLayout/footer/footer.scss
@@ -29,7 +29,8 @@
}
}
-.footer-info-items, .footer-link-items {
+.footer-info-items,
+.footer-link-items {
height: 16px;
margin-bottom: 4px;
}
@@ -38,7 +39,7 @@
display: inline-block;
line-height: 16px;
color: $COLOR--e-300;
- font-size: 9px;
+ font-size: 11px;
font-family: $FONT-ROBOTO-REGULAR;
margin: 0 8px;
diff --git a/app/src/layouts/settingsLayout/settingsLayout.jsx b/app/src/layouts/settingsLayout/settingsLayout.jsx
index 3a87ea3f4e..abf366191b 100644
--- a/app/src/layouts/settingsLayout/settingsLayout.jsx
+++ b/app/src/layouts/settingsLayout/settingsLayout.jsx
@@ -33,11 +33,9 @@ export const SettingsLayout = ({ navigation, children }) => (
);
SettingsLayout.propTypes = {
navigation: PropTypes.node,
- header: PropTypes.node,
children: PropTypes.node,
};
SettingsLayout.defaultProps = {
navigation: null,
- header: null,
children: null,
};
diff --git a/app/src/pages/admin/adminUiExtensionPage/adminUiExtensionPage.jsx b/app/src/pages/admin/adminUiExtensionPage/adminUiExtensionPage.jsx
index ca8019711c..8bff775cc2 100644
--- a/app/src/pages/admin/adminUiExtensionPage/adminUiExtensionPage.jsx
+++ b/app/src/pages/admin/adminUiExtensionPage/adminUiExtensionPage.jsx
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 EPAM Systems
+ * 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.
@@ -14,31 +14,53 @@
* limitations under the License.
*/
-import PropTypes from 'prop-types';
-import { connect } from 'react-redux';
+import React, { useState } from 'react';
+import classNames from 'classnames/bind';
import { uiExtensionAdminPagesSelector } from 'controllers/plugins/uiExtensions';
-import { pluginPageSelector } from 'controllers/pages';
-import { UiExtensionPage } from 'pages/common/uiExtensionPage';
+import { useActivePluginPageExtension } from 'controllers/plugins/uiExtensions/hooks';
+import { Header } from 'pages/inside/projectSettingsPageContainer/header';
+import { PageHeader, PageLayout, PageSection } from 'layouts/pageLayout';
+import { ExtensionLoader } from 'components/extensionLoader';
+import styles from './adminUiExtensionPage.scss';
-const AdminExtensionPage = ({ extensions, activePluginPage }) => (
-
-);
-AdminExtensionPage.propTypes = {
- extensions: PropTypes.arrayOf(
- PropTypes.shape({
- name: PropTypes.string,
- title: PropTypes.string,
- component: PropTypes.func,
- }),
- ),
- activePluginPage: PropTypes.string,
-};
-AdminExtensionPage.defaultProps = {
- extensions: [],
- activePluginPage: null,
-};
+const cx = classNames.bind(styles);
+
+export const AdminUiExtensionPage = () => {
+ const extension = useActivePluginPageExtension(uiExtensionAdminPagesSelector);
+ const [headerNodes, setHeaderNodes] = useState({});
-export const AdminUiExtensionPage = connect((state) => ({
- extensions: uiExtensionAdminPagesSelector(state),
- activePluginPage: pluginPageSelector(state),
-}))(AdminExtensionPage);
+ let pageLayout = null;
+
+ if (extension) {
+ if (extension.newLayout) {
+ pageLayout = (
+ <>
+
+
+ {headerNodes.children}
+
+
+
+
+
+ >
+ );
+ } else {
+ pageLayout = (
+
+
+
+
+
+
+ );
+ }
+ }
+
+ return pageLayout;
+};
diff --git a/app/src/pages/common/uiExtensionPage/uiExtensionPage.scss b/app/src/pages/admin/adminUiExtensionPage/adminUiExtensionPage.scss
similarity index 95%
rename from app/src/pages/common/uiExtensionPage/uiExtensionPage.scss
rename to app/src/pages/admin/adminUiExtensionPage/adminUiExtensionPage.scss
index 40f182d572..105d765fab 100644
--- a/app/src/pages/common/uiExtensionPage/uiExtensionPage.scss
+++ b/app/src/pages/admin/adminUiExtensionPage/adminUiExtensionPage.scss
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 EPAM Systems
+ * 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.
diff --git a/app/src/pages/admin/allUsersPage/allUsersGrid/projectsAndRolesColumn/projectsAndRolesColumn.jsx b/app/src/pages/admin/allUsersPage/allUsersGrid/projectsAndRolesColumn/projectsAndRolesColumn.jsx
index ab6dfd83fb..db81fff139 100644
--- a/app/src/pages/admin/allUsersPage/allUsersGrid/projectsAndRolesColumn/projectsAndRolesColumn.jsx
+++ b/app/src/pages/admin/allUsersPage/allUsersGrid/projectsAndRolesColumn/projectsAndRolesColumn.jsx
@@ -116,7 +116,7 @@ export class ProjectsAndRolesColumn extends Component {
intl,
value: { userId },
} = this.props;
- fetch(URLS.project(project), {
+ fetch(URLS.projectByName(project), {
method: 'put',
data: { users: { [userId]: role } },
})
diff --git a/app/src/pages/admin/allUsersPage/allUsersGrid/projectsAndRolesColumn/rolesRow/rolesRow.jsx b/app/src/pages/admin/allUsersPage/allUsersGrid/projectsAndRolesColumn/rolesRow/rolesRow.jsx
index f6fb8e7bdc..40290e6c84 100644
--- a/app/src/pages/admin/allUsersPage/allUsersGrid/projectsAndRolesColumn/rolesRow/rolesRow.jsx
+++ b/app/src/pages/admin/allUsersPage/allUsersGrid/projectsAndRolesColumn/rolesRow/rolesRow.jsx
@@ -83,7 +83,6 @@ export class RolesRow extends Component {
createNew: PropTypes.bool,
userId: PropTypes.string,
entryType: PropTypes.string,
- accountType: PropTypes.string,
tracking: PropTypes.shape({
trackEvent: PropTypes.func,
getTrackingData: PropTypes.func,
@@ -98,7 +97,6 @@ export class RolesRow extends Component {
createNew: false,
entryType: '',
userId: '',
- accountType: '',
};
constructor(props) {
super(props);
@@ -165,11 +163,13 @@ export class RolesRow extends Component {
? intl.formatMessage(messages.unAssignFromPersonalProject)
: intl.formatMessage(messages.unAssignFromProject);
const Tooltip = () =>
;
+ const disable = this.isPersonalProject();
+ const componentClickHandler = !disable ? clickHandler : null;
const WrappedComponent = () => (
);
diff --git a/app/src/pages/admin/allUsersPage/allUsersPage.jsx b/app/src/pages/admin/allUsersPage/allUsersPage.jsx
index 79e0445ff8..5822c4607f 100644
--- a/app/src/pages/admin/allUsersPage/allUsersPage.jsx
+++ b/app/src/pages/admin/allUsersPage/allUsersPage.jsx
@@ -40,7 +40,7 @@ import {
fetchAllUsersAction,
DEFAULT_SORT_COLUMN,
} from 'controllers/administrate/allUsers';
-import { userInfoSelector, userIdSelector } from 'controllers/user';
+import { userInfoSelector } from 'controllers/user';
import { COMMON_LOCALE_KEYS } from 'common/constants/localization';
import { SORTING_ASC, withSortingURL } from 'controllers/sorting';
import { UsersToolbar } from './usersToolbar';
@@ -93,7 +93,6 @@ const messages = defineMessages({
loading: loadingSelector(state),
selectedUsers: selectedUsersSelector(state),
userInfo: userInfoSelector(state),
- userId: userIdSelector(state),
}),
{
toggleUserSelectionAction,
@@ -123,7 +122,6 @@ export class AllUsersPage extends Component {
sortingColumn: PropTypes.string,
sortingDirection: PropTypes.string,
onChangeSorting: PropTypes.func,
- showModalAction: PropTypes.func,
onChangePage: PropTypes.func,
onChangePageSize: PropTypes.func,
loading: PropTypes.bool,
@@ -135,7 +133,6 @@ export class AllUsersPage extends Component {
toggleUserSelectionAction: PropTypes.func,
userInfo: PropTypes.object,
deleteItemsAction: PropTypes.func,
- userId: PropTypes.string,
showScreenLockAction: PropTypes.func,
hideScreenLockAction: PropTypes.func,
showNotification: PropTypes.func,
@@ -153,9 +150,7 @@ export class AllUsersPage extends Component {
pageSize: DEFAULT_PAGINATION[SIZE_KEY],
sortingColumn: null,
sortingDirection: null,
- userId: '',
onChangeSorting: () => {},
- showModalAction: () => {},
onChangePage: () => {},
onChangePageSize: () => {},
loading: false,
@@ -205,11 +200,8 @@ export class AllUsersPage extends Component {
confirmDeleteItems = (items) => {
const ids = items.map((item) => item.id);
this.props.showScreenLockAction();
- fetch(URLS.users(), {
+ fetch(URLS.users(ids), {
method: 'delete',
- data: {
- ids,
- },
})
.then(() => {
this.props.unselectAllUsersAction();
diff --git a/app/src/pages/admin/allUsersPage/usersToolbar/actionPanel/actionPanel.jsx b/app/src/pages/admin/allUsersPage/usersToolbar/actionPanel/actionPanel.jsx
index a21a30c15a..d0f80f9e01 100644
--- a/app/src/pages/admin/allUsersPage/usersToolbar/actionPanel/actionPanel.jsx
+++ b/app/src/pages/admin/allUsersPage/usersToolbar/actionPanel/actionPanel.jsx
@@ -32,11 +32,7 @@ import {
showDefaultErrorNotification,
NOTIFICATION_TYPES,
} from 'controllers/notification';
-import {
- fetchAllUsersAction,
- allUsersSelector,
- querySelector,
-} from 'controllers/administrate/allUsers';
+import { fetchAllUsersAction, querySelector } from 'controllers/administrate/allUsers';
import { fetch } from 'common/utils';
import { INTERNAL } from 'common/constants/accountType';
import { collectFilterEntities } from 'components/filterEntities/containers/utils';
@@ -68,8 +64,7 @@ const messages = defineMessages({
@track()
@connect(
(state) => ({
- users: allUsersSelector(state),
- filterEnities: collectFilterEntities(querySelector(state)),
+ filterEntities: collectFilterEntities(querySelector(state)),
}),
{
showModalAction,
@@ -82,8 +77,7 @@ const messages = defineMessages({
export class ActionPanel extends Component {
static propTypes = {
intl: PropTypes.object.isRequired,
- users: PropTypes.arrayOf(PropTypes.object),
- filterEnities: PropTypes.object,
+ filterEntities: PropTypes.object,
showNotification: PropTypes.func.isRequired,
showDefaultErrorNotification: PropTypes.func.isRequired,
fetchAllUsersAction: PropTypes.func.isRequired,
@@ -95,13 +89,12 @@ export class ActionPanel extends Component {
};
static defaultProps = {
- users: [],
- filterEnities: {},
+ filterEntities: {},
};
onExportUsers = () => {
this.props.tracking.trackEvent(ADMIN_ALL_USERS_PAGE_EVENTS.EXPORT_BTN);
- downloadFile(URLS.exportUsers(this.props.filterEnities));
+ downloadFile(URLS.exportUsers(this.props.filterEntities));
};
showAddUserModal = () => {
diff --git a/app/src/pages/admin/allUsersPage/usersToolbar/usersEntities.jsx b/app/src/pages/admin/allUsersPage/usersToolbar/usersEntities.jsx
index c08b5e9c33..90cf486bd7 100644
--- a/app/src/pages/admin/allUsersPage/usersToolbar/usersEntities.jsx
+++ b/app/src/pages/admin/allUsersPage/usersToolbar/usersEntities.jsx
@@ -95,8 +95,6 @@ export class UsersEntities extends Component {
};
static defaultProps = {
- loading: false,
- events: [],
filterValues: {},
};
getEntities = () => {
diff --git a/app/src/pages/admin/pluginsPage/modals/index.js b/app/src/pages/admin/pluginsPage/modals/index.js
new file mode 100644
index 0000000000..b75244fa1e
--- /dev/null
+++ b/app/src/pages/admin/pluginsPage/modals/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 { UploadPluginModal } from './uploadPluginModal';
diff --git a/app/src/pages/admin/pluginsPage/modals/uploadPluginModal/index.js b/app/src/pages/admin/pluginsPage/modals/uploadPluginModal/index.js
new file mode 100644
index 0000000000..b75244fa1e
--- /dev/null
+++ b/app/src/pages/admin/pluginsPage/modals/uploadPluginModal/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 { UploadPluginModal } from './uploadPluginModal';
diff --git a/app/src/pages/admin/pluginsPage/modals/uploadPluginModal/uploadPluginModal.jsx b/app/src/pages/admin/pluginsPage/modals/uploadPluginModal/uploadPluginModal.jsx
new file mode 100644
index 0000000000..f348a5b6a3
--- /dev/null
+++ b/app/src/pages/admin/pluginsPage/modals/uploadPluginModal/uploadPluginModal.jsx
@@ -0,0 +1,124 @@
+/*
+ * 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 from 'react';
+import { withModal } from 'controllers/modal';
+import PropTypes from 'prop-types';
+import { defineMessages, useIntl } from 'react-intl';
+import { useTracking } from 'react-tracking';
+import { useDispatch } from 'react-redux';
+import DOMPurify from 'dompurify';
+import { URLS } from 'common/urls';
+import { NOTIFICATION_TYPES, showNotification } from 'controllers/notification';
+import { getFilesNames } from 'pages/common/uploadFileControls/utils';
+import {
+ FilesDropzone,
+ UploadModalLayout,
+ useFiles,
+ useFilesUpload,
+} from 'pages/common/uploadFileControls';
+import { PLUGINS_PAGE_EVENTS } from 'components/main/analytics/events';
+
+const messages = defineMessages({
+ modalTitle: {
+ id: 'UploadPluginModal.modalTitle',
+ defaultMessage: 'Upload plugin',
+ },
+ uploadButton: {
+ id: 'UploadPluginModal.uploadButton',
+ defaultMessage: 'Upload',
+ },
+ uploadTip: {
+ id: 'UploadPluginModal.tip',
+ defaultMessage:
+ 'Drop only
.jar file under 128 MB to upload or
click to add it',
+ },
+ incorrectFileSize: {
+ id: 'UploadPluginModal.incorrectFileSize',
+ defaultMessage: 'File size is more than 128 Mb',
+ },
+ importConfirmationWarning: {
+ id: 'UploadPluginModal.importConfirmationWarning',
+ defaultMessage: 'Are you sure you want to interrupt the plugin uploading?',
+ },
+});
+
+const MAX_FILE_SIZE = 134217728;
+const ACCEPT_FILE_MIME_TYPES = ['.jar'];
+
+export const UploadPluginModal = ({ data: { onImport } }) => {
+ const {
+ files,
+ actions: { addFiles, removeFile, updateFile },
+ } = useFiles();
+ const { uploadFiles, cancelRequests } = useFilesUpload(files, updateFile);
+ const { formatMessage } = useIntl();
+ const { trackEvent } = useTracking();
+ const dispatch = useDispatch();
+
+ const onUploadSuccess = () => {
+ onImport();
+ };
+
+ const onUploadError = (id, err) => {
+ dispatch(
+ showNotification({
+ message: err.message,
+ type: NOTIFICATION_TYPES.ERROR,
+ }),
+ );
+ };
+
+ const saveFiles = async () => {
+ trackEvent(PLUGINS_PAGE_EVENTS.clickUploadModalBtn(getFilesNames(files)));
+ await uploadFiles(URLS.plugin(), onUploadSuccess, onUploadError);
+ };
+
+ return (
+
+ DOMPurify.sanitize(`${d}`),
+ span: (d) => DOMPurify.sanitize(`${d}`),
+ })}
+ />
+
+ );
+};
+UploadPluginModal.propTypes = {
+ data: PropTypes.shape({
+ onImport: PropTypes.func,
+ }).isRequired,
+};
+export default withModal('uploadPluginModal')(UploadPluginModal);
diff --git a/app/src/pages/admin/pluginsPage/pluginsFilter/pluginsFilter.jsx b/app/src/pages/admin/pluginsPage/pluginsFilter/pluginsFilter.jsx
index 549fa5a20e..7d093be566 100644
--- a/app/src/pages/admin/pluginsPage/pluginsFilter/pluginsFilter.jsx
+++ b/app/src/pages/admin/pluginsPage/pluginsFilter/pluginsFilter.jsx
@@ -14,52 +14,46 @@
* limitations under the License.
*/
-import React, { Component, Fragment } from 'react';
+import React from 'react';
import PropTypes from 'prop-types';
-import { injectIntl } from 'react-intl';
+import { useTracking } from 'react-tracking';
import classNames from 'classnames/bind';
import { getPluginsFilter } from 'common/constants/pluginsFilter';
+import { PLUGINS_PAGE_EVENTS } from 'components/main/analytics/events';
import styles from './pluginsFilter.scss';
const cx = classNames.bind(styles);
-@injectIntl
-export class PluginsFilter extends Component {
- static propTypes = {
- intl: PropTypes.object.isRequired,
- filterItems: PropTypes.array.isRequired,
- onFilterChange: PropTypes.func.isRequired,
- activeItem: PropTypes.string.isRequired,
- };
-
- getFilterItems = () => getPluginsFilter(this.props.filterItems);
+export const PluginsFilter = ({ filterItems, onFilterChange, activeItem }) => {
+ const { trackEvent } = useTracking();
+ const getFilterItems = () => getPluginsFilter(filterItems);
- changeFilterItem = (e) => {
+ const changeFilterItem = (e) => {
e.preventDefault();
- this.props.onFilterChange(e.currentTarget.id);
- };
-
- generateItems = () => {
- const { activeItem } = this.props;
-
- return (
-
- {this.getFilterItems().map((item) => (
- -
-
-
- ))}
-
- );
+ const { id } = e.currentTarget;
+ trackEvent(PLUGINS_PAGE_EVENTS.navigatedInPluginsFilterList(id));
+ onFilterChange(id);
};
- render() {
- return
{this.generateItems()};
- }
-}
+ return (
+
+ {getFilterItems().map((item) => (
+ -
+
+
+ ))}
+
+ );
+};
+
+PluginsFilter.propTypes = {
+ filterItems: PropTypes.array.isRequired,
+ onFilterChange: PropTypes.func.isRequired,
+ activeItem: PropTypes.string.isRequired,
+};
diff --git a/app/src/pages/admin/pluginsPage/pluginsListItems/pluginsItem/pluginsItem.jsx b/app/src/pages/admin/pluginsPage/pluginsListItems/pluginsItem/pluginsItem.jsx
index db18aeccc2..e60d562c47 100644
--- a/app/src/pages/admin/pluginsPage/pluginsListItems/pluginsItem/pluginsItem.jsx
+++ b/app/src/pages/admin/pluginsPage/pluginsListItems/pluginsItem/pluginsItem.jsx
@@ -49,7 +49,6 @@ export class PluginsItem extends Component {
onToggleActive: PropTypes.func.isRequired,
showToggleConfirmationModal: PropTypes.func.isRequired,
toggleable: PropTypes.bool,
- showNotification: PropTypes.func,
onClick: PropTypes.func,
tracking: PropTypes.shape({
trackEvent: PropTypes.func,
@@ -59,7 +58,6 @@ export class PluginsItem extends Component {
static defaultProps = {
toggleable: true,
- showNotification: () => {},
onClick: () => {},
};
diff --git a/app/src/pages/admin/pluginsPage/pluginsListItems/pluginsListItems.jsx b/app/src/pages/admin/pluginsPage/pluginsListItems/pluginsListItems.jsx
index 97406e83fc..db3778ac2b 100644
--- a/app/src/pages/admin/pluginsPage/pluginsListItems/pluginsListItems.jsx
+++ b/app/src/pages/admin/pluginsPage/pluginsListItems/pluginsListItems.jsx
@@ -25,6 +25,7 @@ import {
BTS_GROUP_TYPE,
ANALYZER_GROUP_TYPE,
OTHER_GROUP_TYPE,
+ IMPORT_GROUP_TYPE,
} from 'common/constants/pluginsGroupTypes';
import { isPluginSwitchable } from 'controllers/plugins';
import styles from './pluginsListItems.scss';
@@ -53,6 +54,10 @@ const pluginTitle = defineMessages({
id: 'PluginsList.analyzer',
defaultMessage: 'Analyzer',
},
+ [IMPORT_GROUP_TYPE]: {
+ id: 'PluginsList.import',
+ defaultMessage: 'Launches Import',
+ },
[OTHER_GROUP_TYPE]: {
id: 'PluginsList.other',
defaultMessage: 'Other',
diff --git a/app/src/pages/admin/pluginsPage/pluginsTabs/installedTab/installedTab.jsx b/app/src/pages/admin/pluginsPage/pluginsTabs/installedTab/installedTab.jsx
index eece3fbd42..32e1f23456 100644
--- a/app/src/pages/admin/pluginsPage/pluginsTabs/installedTab/installedTab.jsx
+++ b/app/src/pages/admin/pluginsPage/pluginsTabs/installedTab/installedTab.jsx
@@ -149,6 +149,9 @@ export class InstalledTab extends Component {
title: formatMessage(messages.enablePluginTitle),
confirmText: formatMessage(COMMON_LOCALE_KEYS.ENABLE),
cancelText: formatMessage(COMMON_LOCALE_KEYS.CANCEL),
+ eventsInfo: {
+ confirmBtn: PLUGINS_PAGE_EVENTS.clickEnablePlugin(pluginName),
+ },
},
});
};
@@ -167,6 +170,9 @@ export class InstalledTab extends Component {
title: formatMessage(messages.disablePluginTitle),
confirmText: formatMessage(COMMON_LOCALE_KEYS.DISABLE),
cancelText: formatMessage(COMMON_LOCALE_KEYS.CANCEL),
+ eventsInfo: {
+ confirmBtn: PLUGINS_PAGE_EVENTS.clickDisablePlugin(pluginName),
+ },
},
});
};
diff --git a/app/src/pages/admin/pluginsPage/pluginsToolbar/actionPanel/actionPanel.jsx b/app/src/pages/admin/pluginsPage/pluginsToolbar/actionPanel/actionPanel.jsx
index c6b343ad77..735356bef1 100644
--- a/app/src/pages/admin/pluginsPage/pluginsToolbar/actionPanel/actionPanel.jsx
+++ b/app/src/pages/admin/pluginsPage/pluginsToolbar/actionPanel/actionPanel.jsx
@@ -25,8 +25,6 @@ import { fetchPluginsAction } from 'controllers/plugins';
import { GhostButton } from 'components/buttons/ghostButton';
import { PLUGINS_PAGE_EVENTS } from 'components/main/analytics/events';
import ImportIcon from 'common/img/import-inline.svg';
-import { URLS } from 'common/urls';
-import { MODAL_TYPE_UPLOAD_PLUGIN } from 'pages/common/modals/importModal/constants';
import styles from './actionPanel.scss';
export const UPLOAD = 'upload';
@@ -38,31 +36,6 @@ const messages = defineMessages({
id: 'PluginsPage.upload',
defaultMessage: 'Upload',
},
- modalTitle: {
- id: 'PluginsPage.modalTitle',
- defaultMessage: 'Upload plugin',
- },
- uploadButton: {
- id: 'PluginsPage.uploadButton',
- defaultMessage: 'Upload',
- },
- uploadTip: {
- id: 'PluginsPage.tip',
- defaultMessage:
- 'Drop only
.jar file under 128 MB to upload or
click to add it',
- },
- incorrectFileSize: {
- id: 'PluginsPage.incorrectFileSize',
- defaultMessage: 'File size is more than 128 Mb',
- },
- incorrectFileVersion: {
- id: 'PluginsPage.incorrectFileVersion',
- defaultMessage: 'Plugin version should be specified',
- },
- incorrectFileManifest: {
- id: 'PluginsPage.incorrectFileManifest',
- defaultMessage: 'Cannot find the manifest path',
- },
});
@connect(null, {
@@ -80,40 +53,16 @@ export class ActionPanel extends Component {
trackEvent: PropTypes.func,
getTrackingData: PropTypes.func,
}).isRequired,
- initialParamsValues: PropTypes.array,
};
- static defaultProps = {
- initialParamsValues: [],
- };
-
- prepareInitialParamsValue = (initialParamsValues) =>
- JSON.stringify(
- initialParamsValues.reduce((acc, item) => ({ ...acc, [item.key]: item.value }), {}),
- );
openUploadModal = () => {
- const {
- intl: { formatMessage },
- tracking,
- } = this.props;
+ const { tracking } = this.props;
tracking.trackEvent(PLUGINS_PAGE_EVENTS.CLICK_UPLOAD_BTN);
this.props.showModalAction({
- id: 'importModal',
+ id: 'uploadPluginModal',
data: {
- type: MODAL_TYPE_UPLOAD_PLUGIN,
onImport: this.props.fetchPluginsAction,
- title: formatMessage(messages.modalTitle),
- importButton: formatMessage(messages.uploadButton),
- tip: formatMessage(messages.uploadTip),
- incorrectFileSize: formatMessage(messages.incorrectFileSize),
- url: URLS.plugin(),
- singleImport: true,
- eventsInfo: {
- uploadButton: PLUGINS_PAGE_EVENTS.clickUploadModalBtn,
- cancelBtn: PLUGINS_PAGE_EVENTS.CANCEL_BTN_UPLOAD_MODAL,
- closeIcon: PLUGINS_PAGE_EVENTS.CLOSE_ICON_UPLOAD_MODAL,
- },
},
});
};
diff --git a/app/src/pages/admin/projectEventsPage/eventsEntities.jsx b/app/src/pages/admin/projectEventsPage/eventsEntities.jsx
index 96f2762a69..71c9f4bec4 100644
--- a/app/src/pages/admin/projectEventsPage/eventsEntities.jsx
+++ b/app/src/pages/admin/projectEventsPage/eventsEntities.jsx
@@ -83,6 +83,8 @@ import {
IMPORT as EVENT_ACTIONS_IMPORT,
START_IMPORT,
FINISH_IMPORT,
+ MARK_LAUNCH_AS_IMPORTANT,
+ UNMARK_LAUNCH_AS_IMPORTANT,
} from 'common/constants/actionTypes';
import {
DASHBOARD,
@@ -142,8 +144,6 @@ export class EventsEntities extends Component {
};
static defaultProps = {
- loading: false,
- events: [],
filterValues: {},
};
@@ -247,6 +247,14 @@ export class EventsEntities extends Component {
label: intl.formatMessage(actionMessages[DELETE_LAUNCH]),
value: DELETE_LAUNCH,
},
+ {
+ label: intl.formatMessage(actionMessages[MARK_LAUNCH_AS_IMPORTANT]),
+ value: MARK_LAUNCH_AS_IMPORTANT,
+ },
+ {
+ label: intl.formatMessage(actionMessages[UNMARK_LAUNCH_AS_IMPORTANT]),
+ value: UNMARK_LAUNCH_AS_IMPORTANT,
+ },
{
label: intl.formatMessage(actionMessages[UPDATE_PROJECT]),
value: UPDATE_PROJECT,
diff --git a/app/src/pages/admin/projectEventsPage/eventsGrid/eventsGrid.jsx b/app/src/pages/admin/projectEventsPage/eventsGrid/eventsGrid.jsx
index cc6e321645..4d6a335679 100644
--- a/app/src/pages/admin/projectEventsPage/eventsGrid/eventsGrid.jsx
+++ b/app/src/pages/admin/projectEventsPage/eventsGrid/eventsGrid.jsx
@@ -42,7 +42,9 @@ const messages = defineMessages({
userCol: { id: 'EventsGrid.userCol', defaultMessage: 'User' },
actionCol: { id: 'EventsGrid.actionCol', defaultMessage: 'Action' },
objectTypeCol: { id: 'EventsGrid.objectTypeCol', defaultMessage: 'Object Type' },
+ objectTypeColShort: { id: 'EventsGrid.objectTypeColShort', defaultMessage: 'Type' },
objectNameCol: { id: 'EventsGrid.objectNameCol', defaultMessage: 'Object Name' },
+ objectNameColShort: { id: 'EventsGrid.objectNameColShort', defaultMessage: 'Name' },
oldValueCol: { id: 'EventsGrid.oldValueCol', defaultMessage: 'Old Value' },
newValueCol: { id: 'EventsGrid.newValueCol', defaultMessage: 'New Value' },
});
@@ -193,6 +195,7 @@ export class EventsGrid extends PureComponent {
id: ENTITY_EVENTS_OBJECT_TYPE,
title: {
full: this.props.intl.formatMessage(messages.objectTypeCol),
+ short: this.props.intl.formatMessage(messages.objectTypeColShort),
},
sortable: true,
component: ObjectTypeColumn,
@@ -204,6 +207,7 @@ export class EventsGrid extends PureComponent {
id: ENTITY_OBJECT_NAME,
title: {
full: this.props.intl.formatMessage(messages.objectNameCol),
+ short: this.props.intl.formatMessage(messages.objectNameColShort),
},
sortable: true,
component: ObjectNameColumn,
@@ -243,6 +247,9 @@ export class EventsGrid extends PureComponent {
sortingColumn={sortingColumn}
sortingDirection={sortingDirection}
onChangeSorting={onChangeSorting}
+ headerClassName={cx('events-grid-header')}
+ gridRowClassName={cx('events-grid-row')}
+ className={cx('events-grid')}
/>
{!data.length && !loading && (
diff --git a/app/src/pages/admin/projectEventsPage/eventsGrid/eventsGrid.scss b/app/src/pages/admin/projectEventsPage/eventsGrid/eventsGrid.scss
index b1bd8dd62e..7af8f8ac6d 100644
--- a/app/src/pages/admin/projectEventsPage/eventsGrid/eventsGrid.scss
+++ b/app/src/pages/admin/projectEventsPage/eventsGrid/eventsGrid.scss
@@ -14,53 +14,75 @@
* limitations under the License.
*/
+@mixin responsive-ellipsis($breakpoint) {
+ @media (max-width: $breakpoint) {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+}
+
.time-col {
width: 10%;
height: 70px;
vertical-align: top;
font-size: 12px;
}
+
.user-col {
width: 10%;
vertical-align: top;
font-size: 13px;
font-family: $FONT-SEMIBOLD;
- @media (max-width: $SCREEN_XS_MAX) {
- overflow: hidden;
- text-overflow: ellipsis;
- }
+ @include responsive-ellipsis($SCREEN_XS_MAX);
}
+
.action-col {
width: 20%;
vertical-align: top;
font-size: 13px;
+ @include responsive-ellipsis($SCREEN_XS_MAX);
}
+
.object-type-col {
width: 15%;
vertical-align: top;
font-size: 13px;
font-family: $FONT-SEMIBOLD;
- @media (max-width: $SCREEN_XS_MAX) {
- overflow: hidden;
- text-overflow: ellipsis;
- }
+ @include responsive-ellipsis($SCREEN_XS_MAX);
}
+
.object-name-col {
width: 15%;
vertical-align: top;
font-size: 13px;
font-family: $FONT-SEMIBOLD;
- @media (max-width: $SCREEN_XS_MAX) {
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- }
+ @include responsive-ellipsis($SCREEN_XS_MAX);
}
+
.value-col {
width: 15%;
vertical-align: top;
font-size: 13px;
}
+
.value-field {
font-family: $FONT-SEMIBOLD;
}
+
+.events-grid-header,
+.events-grid-row {
+ @media (max-width: $SCREEN_SM_MAX) {
+ display: table-row;
+ > :nth-last-child(-n+2) {
+ max-width: 0;
+ display: none;
+ }
+ }
+}
+
+.events-grid {
+ @media (max-width: $SCREEN_SM_MAX) {
+ table-layout: fixed;
+ }
+}
diff --git a/app/src/pages/admin/projectEventsPage/projectEventsPage.jsx b/app/src/pages/admin/projectEventsPage/projectEventsPage.jsx
index ce949ae689..e9bdc5aa84 100644
--- a/app/src/pages/admin/projectEventsPage/projectEventsPage.jsx
+++ b/app/src/pages/admin/projectEventsPage/projectEventsPage.jsx
@@ -49,7 +49,6 @@ export class ProjectEventsPage extends Component {
sortingColumn: PropTypes.string,
sortingDirection: PropTypes.string,
onChangeSorting: PropTypes.func,
- showModalAction: PropTypes.func,
onChangePage: PropTypes.func,
onChangePageSize: PropTypes.func,
loading: PropTypes.bool,
@@ -64,7 +63,6 @@ export class ProjectEventsPage extends Component {
sortingColumn: null,
sortingDirection: null,
onChangeSorting: () => {},
- showModalAction: () => {},
onChangePage: () => {},
onChangePageSize: () => {},
loading: false,
diff --git a/app/src/pages/admin/projectsPage/modals/addProjectModal.jsx b/app/src/pages/admin/projectsPage/modals/addProjectModal.jsx
index a3ed47366b..85f7d7b3c8 100644
--- a/app/src/pages/admin/projectsPage/modals/addProjectModal.jsx
+++ b/app/src/pages/admin/projectsPage/modals/addProjectModal.jsx
@@ -46,14 +46,12 @@ export class AddProjectModal extends Component {
data: PropTypes.object,
dirty: PropTypes.bool,
handleSubmit: PropTypes.func,
- change: PropTypes.func,
};
static defaultProps = {
data: {},
dirty: false,
handleSubmit: () => {},
- change: () => {},
};
getCloseConfirmationConfig = () => {
diff --git a/app/src/pages/admin/projectsPage/projectName/projectName.jsx b/app/src/pages/admin/projectsPage/projectName/projectName.jsx
index ab36d205e2..f12e87926b 100644
--- a/app/src/pages/admin/projectsPage/projectName/projectName.jsx
+++ b/app/src/pages/admin/projectsPage/projectName/projectName.jsx
@@ -16,7 +16,6 @@
import React, { Component } from 'react';
import track from 'react-tracking';
-import { injectIntl } from 'react-intl';
import classNames from 'classnames/bind';
import PropTypes from 'prop-types';
import Link from 'redux-first-router-link';
@@ -24,30 +23,25 @@ import { connect } from 'react-redux';
import { ADMIN_PROJECTS_PAGE_EVENTS } from 'components/main/analytics/events';
import { SCREEN_XS_MAX_MEDIA } from 'common/constants/screenSizeVariables';
import { navigateToProjectAction } from 'controllers/administrate/projects';
-import { showModalAction } from 'controllers/modal';
import { PROJECT_PAGE } from 'controllers/pages';
import { assignedProjectsSelector } from 'controllers/user';
import styles from './projectName.scss';
const cx = classNames.bind(styles);
-@injectIntl
@connect(
(state, ownProps) => ({
isAssigned: !!assignedProjectsSelector(state)[ownProps.project.projectName],
}),
{
navigateToProject: navigateToProjectAction,
- showModal: showModalAction,
},
)
@track()
export class ProjectName extends Component {
static propTypes = {
project: PropTypes.object.isRequired,
- intl: PropTypes.object.isRequired,
navigateToProject: PropTypes.func.isRequired,
- showModal: PropTypes.func.isRequired,
isAssigned: PropTypes.bool,
tracking: PropTypes.shape({
trackEvent: PropTypes.func,
diff --git a/app/src/pages/admin/projectsPage/projectsPanelView/projectPanel/projectTooltipIcon/projectTooltipIcon.jsx b/app/src/pages/admin/projectsPage/projectsPanelView/projectPanel/projectTooltipIcon/projectTooltipIcon.jsx
index f290dde3c5..fdfe41fdc2 100644
--- a/app/src/pages/admin/projectsPage/projectsPanelView/projectPanel/projectTooltipIcon/projectTooltipIcon.jsx
+++ b/app/src/pages/admin/projectsPage/projectsPanelView/projectPanel/projectTooltipIcon/projectTooltipIcon.jsx
@@ -28,11 +28,9 @@ import { TextTooltip } from 'components/main/tooltips/textTooltip';
})
export class ProjectTooltipIcon extends Component {
static propTypes = {
- tooltipContent: PropTypes.string,
children: PropTypes.node,
};
static defaultProps = {
- tooltipContent: '',
children: '',
};
diff --git a/app/src/pages/admin/projectsPage/projectsPanelView/projectsPanelView.jsx b/app/src/pages/admin/projectsPage/projectsPanelView/projectsPanelView.jsx
index dce55ae40e..ef8c359206 100644
--- a/app/src/pages/admin/projectsPage/projectsPanelView/projectsPanelView.jsx
+++ b/app/src/pages/admin/projectsPage/projectsPanelView/projectsPanelView.jsx
@@ -16,7 +16,6 @@
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
-import { injectIntl } from 'react-intl';
import classNames from 'classnames/bind';
import { connect } from 'react-redux';
import { loadingSelector, projectsSelector } from 'controllers/administrate/projects';
@@ -30,10 +29,8 @@ const cx = classNames.bind(styles);
projects: projectsSelector(state),
loading: loadingSelector(state),
}))
-@injectIntl
export class ProjectsPanelView extends Component {
static propTypes = {
- intl: PropTypes.object.isRequired,
projects: PropTypes.array,
loading: PropTypes.bool,
onMembers: PropTypes.func,
diff --git a/app/src/pages/admin/projectsPage/projectsToolbar/projectEntities.jsx b/app/src/pages/admin/projectsPage/projectsToolbar/projectEntities.jsx
index 4ebac2b728..ee0f1e88ea 100644
--- a/app/src/pages/admin/projectsPage/projectsToolbar/projectEntities.jsx
+++ b/app/src/pages/admin/projectsPage/projectsToolbar/projectEntities.jsx
@@ -93,7 +93,6 @@ export class ProjectEntities extends Component {
};
static defaultProps = {
- loading: false,
filterValues: {},
};
getEntities = () => {
diff --git a/app/src/pages/admin/projectsPage/projectsToolbar/projectsToolbar.jsx b/app/src/pages/admin/projectsPage/projectsToolbar/projectsToolbar.jsx
index 2ff9f941c7..3eab1ff587 100644
--- a/app/src/pages/admin/projectsPage/projectsToolbar/projectsToolbar.jsx
+++ b/app/src/pages/admin/projectsPage/projectsToolbar/projectsToolbar.jsx
@@ -125,11 +125,8 @@ export class ProjectsToolbar extends Component {
this.props.showScreenLockAction();
- fetch(URLS.project(''), {
+ fetch(URLS.project(ids), {
method: 'delete',
- data: {
- ids,
- },
})
.then(() => {
this.props.unselectAllProjectsAction();
diff --git a/app/src/pages/admin/serverSettingsPage/serverSettingsTabs/analyticsTab/analyticsTab.jsx b/app/src/pages/admin/serverSettingsPage/serverSettingsTabs/analyticsTab/analyticsTab.jsx
index ce95569925..a1f2df8c8c 100644
--- a/app/src/pages/admin/serverSettingsPage/serverSettingsTabs/analyticsTab/analyticsTab.jsx
+++ b/app/src/pages/admin/serverSettingsPage/serverSettingsTabs/analyticsTab/analyticsTab.jsx
@@ -100,7 +100,6 @@ export class AnalyticsTab extends Component {
};
static defaultProps = {
- change: () => {},
showNotification: () => {},
fetchInfo: () => {},
analyticsEnabled: false,
diff --git a/app/src/pages/admin/serverSettingsPage/serverSettingsTabs/authConfigurationTab/modals/removeOrganizationModal/removeOrganizationModal.jsx b/app/src/pages/admin/serverSettingsPage/serverSettingsTabs/authConfigurationTab/modals/removeOrganizationModal/removeOrganizationModal.jsx
index 5b3f34e468..b6d7603735 100644
--- a/app/src/pages/admin/serverSettingsPage/serverSettingsTabs/authConfigurationTab/modals/removeOrganizationModal/removeOrganizationModal.jsx
+++ b/app/src/pages/admin/serverSettingsPage/serverSettingsTabs/authConfigurationTab/modals/removeOrganizationModal/removeOrganizationModal.jsx
@@ -16,7 +16,7 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
-import { formValueSelector, change } from 'redux-form';
+import { formValueSelector } from 'redux-form';
import { defineMessages, injectIntl } from 'react-intl';
import { connect } from 'react-redux';
import { showNotification, NOTIFICATION_TYPES } from 'controllers/notification';
@@ -62,7 +62,7 @@ const messages = defineMessages({
CLIENT_SECRET_KEY,
),
}),
- { showNotification, change },
+ { showNotification },
)
@injectIntl
export class RemoveOrganizationModal extends Component {
@@ -70,13 +70,11 @@ export class RemoveOrganizationModal extends Component {
intl: PropTypes.object,
formData: PropTypes.object.isRequired,
data: PropTypes.object,
- change: PropTypes.func,
showNotification: PropTypes.func,
};
static defaultProps = {
intl: {},
data: {},
- change: () => {},
showNotification: () => {},
};
diff --git a/app/src/pages/common/membersPage/membersGrid/projectRole/projectRole.jsx b/app/src/pages/common/membersPage/membersGrid/projectRole/projectRole.jsx
index 49cf3c6bf8..9112eaa107 100644
--- a/app/src/pages/common/membersPage/membersGrid/projectRole/projectRole.jsx
+++ b/app/src/pages/common/membersPage/membersGrid/projectRole/projectRole.jsx
@@ -29,7 +29,6 @@ import { projectIdSelector } from 'controllers/pages';
import {
activeProjectRoleSelector,
userAccountRoleSelector,
- isAdminSelector,
userIdSelector,
} from 'controllers/user';
import { MEMBERS_PAGE_EVENTS } from 'components/main/analytics/events';
@@ -57,7 +56,6 @@ const messages = defineMessages({
(state) => ({
currentUser: userIdSelector(state),
projectId: projectIdSelector(state),
- isAdmin: isAdminSelector(state),
canChangeRole: canChangeUserRole(
userAccountRoleSelector(state),
activeProjectRoleSelector(state),
@@ -76,7 +74,6 @@ export class ProjectRole extends Component {
userId: PropTypes.string,
currentUser: PropTypes.string,
canChangeRole: PropTypes.bool,
- isAdmin: PropTypes.bool,
tracking: PropTypes.shape({
trackEvent: PropTypes.func,
getTrackingData: PropTypes.func,
@@ -90,7 +87,6 @@ export class ProjectRole extends Component {
currentUser: '',
showNotification: () => {},
canChangeRole: false,
- isAdmin: false,
};
state = {
currentRole: this.getUserRole(),
@@ -104,7 +100,7 @@ export class ProjectRole extends Component {
param.users[this.props.userId] = val;
this.setState({ currentRole: val });
tracking.trackEvent(MEMBERS_PAGE_EVENTS.CHANGE_PROJECT_ROLE);
- fetch(URLS.project(this.props.projectId), {
+ fetch(URLS.projectByName(this.props.projectId), {
method: 'put',
data: param,
})
@@ -126,7 +122,7 @@ export class ProjectRole extends Component {
};
getUserRole() {
const { assignedProjects, projectId } = this.props;
- return assignedProjects[projectId] && assignedProjects[projectId].projectRole;
+ return assignedProjects[projectId]?.projectRole;
}
render() {
this.getUserRole();
diff --git a/app/src/pages/common/membersPage/membersGrid/unassignButton/unassignButton.jsx b/app/src/pages/common/membersPage/membersGrid/unassignButton/unassignButton.jsx
index 0d44fad884..b6d2837985 100644
--- a/app/src/pages/common/membersPage/membersGrid/unassignButton/unassignButton.jsx
+++ b/app/src/pages/common/membersPage/membersGrid/unassignButton/unassignButton.jsx
@@ -88,9 +88,7 @@ const messages = defineMessages({
projectId: projectIdSelector(state),
projectRole: activeProjectRoleSelector(state),
accountRole: userAccountRoleSelector(state),
- entryType:
- assignedProjectsSelector(state)[projectIdSelector(state)] &&
- assignedProjectsSelector(state)[projectIdSelector(state)].entryType,
+ entryType: assignedProjectsSelector(state)[projectIdSelector(state)]?.entryType,
}),
{ showNotification, showModalAction },
)
diff --git a/app/src/pages/common/membersPage/membersPage.jsx b/app/src/pages/common/membersPage/membersPage.jsx
index 8fa6af94c6..1ba1731d3e 100644
--- a/app/src/pages/common/membersPage/membersPage.jsx
+++ b/app/src/pages/common/membersPage/membersPage.jsx
@@ -18,7 +18,7 @@ import React, { Component, Fragment } from 'react';
import track from 'react-tracking';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
-import { injectIntl, defineMessages } from 'react-intl';
+import { defineMessages } from 'react-intl';
import {
membersPaginationSelector,
fetchMembersAction,
@@ -54,12 +54,9 @@ const messages = defineMessages({
@withPagination({
paginationSelector: membersPaginationSelector,
})
-@injectIntl
@track({ page: MEMBERS_PAGE })
export class MembersPage extends Component {
static propTypes = {
- intl: PropTypes.object.isRequired,
- onSearchChange: PropTypes.func,
onFilterChange: PropTypes.func,
fetchMembersAction: PropTypes.func,
activePage: PropTypes.number,
@@ -77,7 +74,6 @@ export class MembersPage extends Component {
}).isRequired,
};
static defaultProps = {
- onSearchChange: () => {},
onFilterChange: () => {},
fetchMembersAction: () => {},
activePage: DEFAULT_PAGINATION[PAGE_KEY],
diff --git a/app/src/pages/common/membersPage/modals/inviteUserModal/inviteUserModal.jsx b/app/src/pages/common/membersPage/modals/inviteUserModal/inviteUserModal.jsx
index ab02b56850..b7e4b13140 100644
--- a/app/src/pages/common/membersPage/modals/inviteUserModal/inviteUserModal.jsx
+++ b/app/src/pages/common/membersPage/modals/inviteUserModal/inviteUserModal.jsx
@@ -29,11 +29,7 @@ import { commonValidators } from 'common/utils/validation';
import { projectIdSelector } from 'controllers/pages';
import { isAdminSelector } from 'controllers/user';
import { showScreenLockAction, hideScreenLockAction } from 'controllers/screenLock';
-import {
- showNotification,
- showDefaultErrorNotification,
- NOTIFICATION_TYPES,
-} from 'controllers/notification';
+import { showNotification, NOTIFICATION_TYPES } from 'controllers/notification';
import { withModal, ModalLayout, ModalField } from 'components/main/modal';
import { FieldProvider } from 'components/fields/fieldProvider';
import { FieldErrorHint } from 'components/fields/fieldErrorHint';
@@ -107,7 +103,6 @@ const inviteFormSelector = formValueSelector('inviteUserForm');
showScreenLockAction,
hideScreenLockAction,
showNotification,
- showDefaultErrorNotification,
},
)
@reduxForm({
@@ -131,7 +126,6 @@ export class InviteUserModal extends Component {
showScreenLockAction: PropTypes.func.isRequired,
hideScreenLockAction: PropTypes.func.isRequired,
showNotification: PropTypes.func.isRequired,
- showDefaultErrorNotification: PropTypes.func.isRequired,
selectedProject: PropTypes.string,
selectedUser: PropTypes.object,
isAdmin: PropTypes.bool,
@@ -186,7 +180,10 @@ export class InviteUserModal extends Component {
return data;
})
.catch((err) => {
- this.props.showDefaultErrorNotification(err);
+ this.props.showNotification({
+ message: err.message,
+ type: NOTIFICATION_TYPES.ERROR,
+ });
this.props.hideScreenLockAction();
return {
errorOccurred: true,
@@ -213,7 +210,10 @@ export class InviteUserModal extends Component {
onInvite();
})
.catch((err) => {
- this.props.showDefaultErrorNotification(err);
+ this.props.showNotification({
+ message: err.message,
+ type: NOTIFICATION_TYPES.ERROR,
+ });
return {
errorOccurred: true,
...err,
@@ -259,13 +259,7 @@ export class InviteUserModal extends Component {
};
formatUser = (user) => (user && { value: user.userLogin, label: user.userLogin }) || null;
- filterProject = (value) =>
- !(
- value &&
- this.props.selectedUser &&
- this.props.selectedUser.assignedProjects &&
- this.props.selectedUser.assignedProjects[value]
- );
+ filterProject = (value) => !(value && this.props.selectedUser?.assignedProjects?.[value]);
render() {
const {
diff --git a/app/src/pages/common/modals/importModal/importModal.jsx b/app/src/pages/common/modals/importModal/importModal.jsx
deleted file mode 100644
index a775a34f78..0000000000
--- a/app/src/pages/common/modals/importModal/importModal.jsx
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
- * Copyright 2019 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, { Component, Fragment } from 'react';
-import track from 'react-tracking';
-import classNames from 'classnames/bind';
-import Dropzone from 'react-dropzone';
-import Parser from 'html-react-parser';
-import PropTypes from 'prop-types';
-import { connect } from 'react-redux';
-import { injectIntl, defineMessages } from 'react-intl';
-import { ModalLayout, withModal } from 'components/main/modal';
-import { showNotification, NOTIFICATION_TYPES } from 'controllers/notification';
-import { COMMON_LOCALE_KEYS } from 'common/constants/localization';
-import { uniqueId, fetch } from 'common/utils';
-import DropZoneIcon from 'common/img/shape-inline.svg';
-import { ImportFileIcon } from './importFileIcon';
-import styles from './importModal.scss';
-import { ACCEPT_FILE_MIME_TYPES, MAX_FILE_SIZES } from './constants';
-
-const cx = classNames.bind(styles);
-
-const messages = defineMessages({
- note: {
- id: 'ImportModal.note',
- defaultMessage: 'Note:',
- },
- importConfirmation: {
- id: 'ImportModal.importConfirmation',
- defaultMessage: 'Confirm cancel',
- },
- incorrectFileFormat: {
- id: 'ImportModal.incorrectFileFormat',
- defaultMessage: 'Incorrect file format',
- },
-});
-
-@withModal('importModal')
-@injectIntl
-@connect(null, {
- showNotification,
-})
-@track()
-export class ImportModal extends Component {
- static propTypes = {
- intl: PropTypes.object.isRequired,
- showNotification: PropTypes.func.isRequired,
- data: PropTypes.object,
- tracking: PropTypes.shape({
- trackEvent: PropTypes.func,
- getTrackingData: PropTypes.func,
- }).isRequired,
- };
-
- static defaultProps = {
- data: { eventsInfo: { uploadButton: () => {}, cancelBtn: {}, closeIcon: {} } },
- };
-
- state = {
- files: [],
- };
-
- onDrop = (acceptedFiles, rejectedFiles) => {
- const { files: stateFiles } = this.state;
- const accepted = acceptedFiles.map(this.onDropAcceptedFileHandler);
- const rejected = rejectedFiles.map(this.onDropRejectedFileHandler);
-
- this.setState({
- files: [...stateFiles, ...accepted, ...rejected],
- });
- };
-
- onDropAcceptedFileHandler = (file) => ({
- file,
- valid: true,
- id: uniqueId(),
- isLoading: false,
- uploaded: false,
- uploadingProgress: 0,
- });
-
- onDropRejectedFileHandler = (file) => ({
- file,
- valid: false,
- id: uniqueId(),
- rejectMessage: this.addFileRejectMessage(file),
- });
-
- onDelete = (id) => {
- const { files } = this.state;
-
- this.setState({
- files: files.filter((item) => item.id !== id),
- });
- };
-
- getOkButtonConfig = (isLoading, uploadFinished) => {
- const {
- intl,
- tracking,
- data: { importButton, eventsInfo },
- } = this.props;
- const text =
- isLoading || uploadFinished ? intl.formatMessage(COMMON_LOCALE_KEYS.OK) : importButton;
-
- return {
- text,
- disabled: isLoading,
- onClick: (closeModal) => {
- if (uploadFinished) {
- closeModal();
- } else {
- tracking.trackEvent(eventsInfo.okBtn);
- this.uploadFilesOnOkClick();
- }
- },
- };
- };
-
- getCloseConfirmationConfig = (isValidFilesExists, loading, uploadFinished) => {
- const {
- intl,
- data: { importConfirmationWarning },
- } = this.props;
- const confirmationWarning = loading
- ? importConfirmationWarning
- : intl.formatMessage(COMMON_LOCALE_KEYS.CLOSE_MODAL_WARNING);
-
- if (!isValidFilesExists || uploadFinished) {
- return null;
- }
- return {
- withCheckbox: loading,
- closeConfirmedCallback: this.closeConfirmedCallback,
- confirmationMessage: intl.formatMessage(messages.importConfirmation),
- confirmationWarning,
- };
- };
- getValidFiles = () => this.state.files.filter(({ valid }) => valid);
- isUploadInProgress = () => this.getValidFiles().some(({ isLoading }) => isLoading);
- isUploadFinished = () =>
- this.getValidFiles().length ? this.getValidFiles().every(({ uploaded }) => uploaded) : false;
- cancelRequests = [];
- isDropZoneDisabled = () =>
- this.isUploadFinished() ||
- this.isUploadInProgress() ||
- (this.props.data.singleImport && this.state.files.length > 0);
-
- validateFile = (file) => {
- const { type } = this.props.data;
-
- return {
- incorrectFileFormat: !ACCEPT_FILE_MIME_TYPES[type].includes(file.type),
- incorrectFileSize: file.size > MAX_FILE_SIZES[type],
- };
- };
-
- getFilesNames = (files) => files.map(({ file: { name } }) => name).join('#');
-
- formValidationMessage = (validationProperties) => {
- const {
- intl,
- data: { incorrectFileSize },
- } = this.props;
- const validationMessages = {
- incorrectFileFormat: intl.formatMessage(messages.incorrectFileFormat),
- incorrectFileSize,
- };
- const validationMessage = [];
-
- Object.keys(validationProperties).forEach((message) => {
- if (validationProperties[message]) {
- validationMessage.push(validationMessages[message]);
- }
- });
-
- return validationMessage.join('. ').trim();
- };
-
- addFileRejectMessage = (file) => {
- const validationProperties = this.validateFile(file);
-
- return this.formValidationMessage(validationProperties);
- };
-
- uploadFilesOnOkClick = () => {
- const data = this.prepareDataForServerUploading();
-
- const { files } = this.state;
-
- this.setState({
- files: files.map((item) => {
- if (item.valid) {
- return { ...item, isLoading: true };
- }
- return item;
- }),
- });
-
- data.forEach(({ promise, id }) => {
- this.uploadFilesHandler(promise, id);
- });
- };
-
- uploadFilesHandler = (promise, id) => {
- promise
- .then(this.successUploadHandler.bind(null, id))
- .catch(this.failedUploadHandler.bind(null, id));
- };
-
- successUploadHandler = (id) => {
- this.props.data.onImport();
- const { files } = this.state;
- const {
- tracking: { trackEvent },
- data: { eventsInfo: { uploadButton } = {} },
- } = this.props;
-
- if (uploadButton) {
- trackEvent(uploadButton(this.getFilesNames(files)));
- }
-
- this.setState({
- files: files.map((item) => {
- if (item.id === id) {
- return { ...item, uploaded: true, isLoading: false, uploadFailed: false };
- }
-
- return item;
- }),
- });
- };
-
- failedUploadHandler = (id, err) => {
- const { files } = this.state;
-
- this.props.showNotification({
- message: err.message,
- type: NOTIFICATION_TYPES.ERROR,
- });
- this.setState({
- files: files.map((item) => {
- if (item.id !== id) {
- return item;
- }
- return {
- ...item,
- uploaded: true,
- isLoading: false,
- uploadFailed: true,
- uploadFailReason: err,
- };
- }),
- });
- };
-
- formDataForServerUploading() {
- const { files } = this.state;
-
- return files
- .filter((item) => item.valid)
- .map((item) => {
- const formData = new FormData();
-
- formData.append('file', item.file, item.file.name);
-
- return {
- data: formData,
- id: item.id,
- };
- });
- }
-
- prepareDataForServerUploading() {
- const data = this.formDataForServerUploading();
-
- return data.map((item) => ({ promise: this.uploadFile(item), id: item.id }));
- }
-
- closeConfirmedCallback = () => {
- if (this.cancelRequests.length) {
- this.cancelRequests.forEach((cancelRequest) => cancelRequest());
- }
- };
-
- uploadFile = (file) => {
- const {
- data: { url },
- } = this.props;
- const { id } = file;
-
- return fetch(url, {
- method: 'POST',
- headers: { 'Content-Type': 'multipart/form-data;' },
- data: file.data,
- abort: (cancelRequest) => {
- this.cancelRequests.push(cancelRequest);
- },
- onUploadProgress: (progressEvent) => {
- const { files } = this.state;
- const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
-
- this.setState({
- files: files.map((item) => {
- if (item.id === id) {
- return { ...item, uploadingProgress: percentCompleted };
- }
-
- return item;
- }),
- });
- },
- });
- };
-
- render() {
- const {
- intl,
- data: { type, title, tip, noteMessage, eventsInfo, singleImport },
- } = this.props;
-
- const { files } = this.state;
- const validFiles = this.getValidFiles();
- const loading = this.isUploadInProgress();
- const uploadFinished = this.isUploadFinished();
- const acceptFile = ACCEPT_FILE_MIME_TYPES[type].join(',');
-
- return (
-
-
- {files.length === 0 && (
-
-
{Parser(DropZoneIcon)}
-
{Parser(tip)}
-
- )}
- {files.length > 0 && (
-
- {files.map((item) => (
-
- ))}
-
- )}
-
- {noteMessage && (
-
- {intl.formatMessage(messages.note)}
- {Parser(noteMessage)}
-
- )}
-
- );
- }
-}
diff --git a/app/src/pages/common/modals/index.js b/app/src/pages/common/modals/index.js
index c0136eff35..b368244096 100644
--- a/app/src/pages/common/modals/index.js
+++ b/app/src/pages/common/modals/index.js
@@ -15,4 +15,3 @@
*/
export { ConfirmationModal } from './confirmationModal';
-export { ImportModal } from './importModal';
diff --git a/app/src/pages/common/uiExtensionPage/uiExtensionPage.jsx b/app/src/pages/common/uiExtensionPage/uiExtensionPage.jsx
deleted file mode 100644
index de4d4212d8..0000000000
--- a/app/src/pages/common/uiExtensionPage/uiExtensionPage.jsx
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2020 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, { useState } from 'react';
-import PropTypes from 'prop-types';
-import { PageHeader, PageLayout, PageSection } from 'layouts/pageLayout';
-import { ExtensionLoader, extensionType } from 'components/extensionLoader';
-import { Header } from 'pages/inside/projectSettingsPageContainer/header';
-import classNames from 'classnames/bind';
-import styles from './uiExtensionPage.scss';
-
-const cx = classNames.bind(styles);
-
-export const UiExtensionPage = ({ extensions, activePluginPage }) => {
- const extension = React.useMemo(() => extensions.find((ex) => ex.name === activePluginPage), [
- extensions,
- activePluginPage,
- ]);
-
- const [headerNodes, setHeaderNodes] = useState({});
-
- let pageLayout = null;
-
- if (extension) {
- if (extension.newLayout) {
- pageLayout = (
- <>
-
-
- {headerNodes.children}
-
-
-
-
-
- >
- );
- } else {
- pageLayout = (
-
-
-
-
-
-
- );
- }
- }
-
- return pageLayout;
-};
-UiExtensionPage.propTypes = {
- extensions: PropTypes.arrayOf(extensionType),
- activePluginPage: PropTypes.string,
-};
-UiExtensionPage.defaultProps = {
- extensions: [],
- activePluginPage: null,
-};
diff --git a/app/src/pages/common/uploadFileControls/filesDropzone/filesDropzone.jsx b/app/src/pages/common/uploadFileControls/filesDropzone/filesDropzone.jsx
new file mode 100644
index 0000000000..f90715a70a
--- /dev/null
+++ b/app/src/pages/common/uploadFileControls/filesDropzone/filesDropzone.jsx
@@ -0,0 +1,145 @@
+/*
+ * 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 from 'react';
+import PropTypes from 'prop-types';
+import { defineMessages, useIntl } from 'react-intl';
+import Dropzone from 'react-dropzone';
+import Parser from 'html-react-parser';
+import classNames from 'classnames/bind';
+import { uniqueId } from 'common/utils';
+import DropZoneIcon from 'common/img/shape-inline.svg';
+import { isUploadFinished, isUploadInProgress } from '../utils';
+import { fileType } from '../propTypes';
+import { ImportFileIcon } from './importFileIcon';
+import styles from './filesDropzone.scss';
+
+const cx = classNames.bind(styles);
+
+const messages = defineMessages({
+ incorrectFileFormat: {
+ id: 'ImportModal.incorrectFileFormat',
+ defaultMessage: 'Incorrect file format',
+ },
+});
+
+export const FilesDropzone = ({
+ files,
+ addFiles,
+ removeFile,
+ maxFileSize,
+ acceptFileMimeTypes,
+ multiple,
+ incorrectFileSizeMessage,
+ tip,
+}) => {
+ const { formatMessage } = useIntl();
+
+ const isDropZoneDisabled = () =>
+ isUploadFinished(files) || isUploadInProgress(files) || (!multiple && files.length > 0);
+
+ const acceptFile = acceptFileMimeTypes.join(',');
+
+ const onDropAcceptedFileHandler = (file) => ({
+ file,
+ valid: true,
+ id: uniqueId(),
+ isLoading: false,
+ uploaded: false,
+ uploadingProgress: 0,
+ });
+
+ const formValidationMessage = (validationProperties) => {
+ const validationMessages = {
+ incorrectFileFormat: formatMessage(messages.incorrectFileFormat),
+ incorrectFileSize: incorrectFileSizeMessage,
+ };
+ const validationMessage = [];
+
+ Object.keys(validationProperties).forEach((message) => {
+ if (validationProperties[message]) {
+ validationMessage.push(validationMessages[message]);
+ }
+ });
+
+ return validationMessage.join('. ').trim();
+ };
+
+ const validateFile = (file) => ({
+ incorrectFileFormat: !acceptFileMimeTypes.includes(file.type),
+ incorrectFileSize: file.size > maxFileSize,
+ });
+
+ const addFileRejectMessage = (file) => {
+ const validationProperties = validateFile(file);
+
+ return formValidationMessage(validationProperties);
+ };
+
+ const onDropRejectedFileHandler = (file) => ({
+ file,
+ valid: false,
+ id: uniqueId(),
+ rejectMessage: addFileRejectMessage(file),
+ });
+
+ const onDrop = (acceptedFiles, rejectedFiles) => {
+ const accepted = acceptedFiles.map(onDropAcceptedFileHandler);
+ const rejected = rejectedFiles.map(onDropRejectedFileHandler);
+
+ addFiles([...accepted, ...rejected]);
+ };
+
+ return (
+
+ {files.length === 0 ? (
+
+
{Parser(DropZoneIcon)}
+
{Parser(tip)}
+
+ ) : (
+
+ {files.map((item) => (
+
+ ))}
+
+ )}
+
+ );
+};
+FilesDropzone.propTypes = {
+ files: PropTypes.arrayOf(fileType).isRequired,
+ addFiles: PropTypes.func.isRequired,
+ removeFile: PropTypes.func.isRequired,
+ incorrectFileSizeMessage: PropTypes.string.isRequired,
+ tip: PropTypes.string.isRequired,
+ multiple: PropTypes.bool,
+ maxFileSize: PropTypes.number,
+ acceptFileMimeTypes: PropTypes.arrayOf(PropTypes.string),
+};
+FilesDropzone.defaultProps = {
+ multiple: true,
+ maxFileSize: 0,
+ acceptFileMimeTypes: [],
+};
diff --git a/app/src/pages/common/modals/importModal/importModal.scss b/app/src/pages/common/uploadFileControls/filesDropzone/filesDropzone.scss
similarity index 76%
rename from app/src/pages/common/modals/importModal/importModal.scss
rename to app/src/pages/common/uploadFileControls/filesDropzone/filesDropzone.scss
index 3a5c87f01d..29f80a3acd 100644
--- a/app/src/pages/common/modals/importModal/importModal.scss
+++ b/app/src/pages/common/uploadFileControls/filesDropzone/filesDropzone.scss
@@ -1,5 +1,5 @@
-/*!
- * Copyright 2019 EPAM Systems
+/*
+ * 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.
@@ -14,12 +14,7 @@
* limitations under the License.
*/
-.dropzone {
- padding: 20px 20px 25px 20px;
- text-align: center;
-}
-
-.dropzone-wrapper {
+.files-dropzone {
height: auto;
width: 100%;
background-color: $COLOR--white-four;
@@ -31,10 +26,15 @@
}
}
-.dropzone-wrapper-active {
+.files-dropzone-active {
opacity: 0.7;
}
+.dropzone {
+ padding: 20px 20px 25px 20px;
+ text-align: center;
+}
+
.icon {
width: 20px;
height: 24px;
@@ -44,7 +44,7 @@
.message {
color: $COLOR--gray-60;
font-size: 12px;
- font-family: $FONT-REGULAR, sans-serif;
+ font-family: $FONT-REGULAR;
b {
font-family: $FONT-SEMIBOLD, sans-serif;
@@ -60,16 +60,3 @@
flex-wrap: wrap;
padding: 20px;
}
-
-.note-label {
- margin-top: 20px;
- color: $COLOR--tealish;
- font-size: 13px;
- font-family: $FONT-SEMIBOLD, sans-serif;
-}
-
-.note-message {
- font-family: $FONT-REGULAR, sans-serif;
- font-size: 12px;
- line-height: 1.5;
-}
diff --git a/app/src/pages/common/modals/importModal/importFileIcon/iconStateIndicators/defaultIcon.jsx b/app/src/pages/common/uploadFileControls/filesDropzone/importFileIcon/iconStateIndicators/defaultIcon.jsx
similarity index 100%
rename from app/src/pages/common/modals/importModal/importFileIcon/iconStateIndicators/defaultIcon.jsx
rename to app/src/pages/common/uploadFileControls/filesDropzone/importFileIcon/iconStateIndicators/defaultIcon.jsx
diff --git a/app/src/pages/common/modals/importModal/importFileIcon/iconStateIndicators/iconStateIndicators.scss b/app/src/pages/common/uploadFileControls/filesDropzone/importFileIcon/iconStateIndicators/iconStateIndicators.scss
similarity index 100%
rename from app/src/pages/common/modals/importModal/importFileIcon/iconStateIndicators/iconStateIndicators.scss
rename to app/src/pages/common/uploadFileControls/filesDropzone/importFileIcon/iconStateIndicators/iconStateIndicators.scss
diff --git a/app/src/pages/common/modals/importModal/importFileIcon/iconStateIndicators/index.js b/app/src/pages/common/uploadFileControls/filesDropzone/importFileIcon/iconStateIndicators/index.js
similarity index 100%
rename from app/src/pages/common/modals/importModal/importFileIcon/iconStateIndicators/index.js
rename to app/src/pages/common/uploadFileControls/filesDropzone/importFileIcon/iconStateIndicators/index.js
diff --git a/app/src/pages/common/modals/importModal/importFileIcon/iconStateIndicators/invalidIcon.jsx b/app/src/pages/common/uploadFileControls/filesDropzone/importFileIcon/iconStateIndicators/invalidIcon.jsx
similarity index 88%
rename from app/src/pages/common/modals/importModal/importFileIcon/iconStateIndicators/invalidIcon.jsx
rename to app/src/pages/common/uploadFileControls/filesDropzone/importFileIcon/iconStateIndicators/invalidIcon.jsx
index eb0dd77562..7db2ff745e 100644
--- a/app/src/pages/common/modals/importModal/importFileIcon/iconStateIndicators/invalidIcon.jsx
+++ b/app/src/pages/common/uploadFileControls/filesDropzone/importFileIcon/iconStateIndicators/invalidIcon.jsx
@@ -15,7 +15,6 @@
*/
import React, { Component } from 'react';
-import PropTypes from 'prop-types';
import classNames from 'classnames/bind';
import Parser from 'html-react-parser';
import { withHoverableTooltip } from 'components/main/tooltips/hoverableTooltip';
@@ -33,14 +32,6 @@ const cx = classNames.bind(styles);
},
})
export class InvalidIcon extends Component {
- static propTypes = {
- rejectMessage: PropTypes.string,
- };
-
- static defaultProps = {
- rejectMessage: '',
- };
-
render() {
return
{Parser(WarningIcon)}
;
}
diff --git a/app/src/pages/common/modals/importModal/importFileIcon/iconStateIndicators/invalidIconTooltip.jsx b/app/src/pages/common/uploadFileControls/filesDropzone/importFileIcon/iconStateIndicators/invalidIconTooltip.jsx
similarity index 100%
rename from app/src/pages/common/modals/importModal/importFileIcon/iconStateIndicators/invalidIconTooltip.jsx
rename to app/src/pages/common/uploadFileControls/filesDropzone/importFileIcon/iconStateIndicators/invalidIconTooltip.jsx
diff --git a/app/src/pages/common/modals/importModal/importFileIcon/iconStateIndicators/uploadIndicator.jsx b/app/src/pages/common/uploadFileControls/filesDropzone/importFileIcon/iconStateIndicators/uploadIndicator.jsx
similarity index 100%
rename from app/src/pages/common/modals/importModal/importFileIcon/iconStateIndicators/uploadIndicator.jsx
rename to app/src/pages/common/uploadFileControls/filesDropzone/importFileIcon/iconStateIndicators/uploadIndicator.jsx
diff --git a/app/src/pages/common/modals/importModal/importFileIcon/iconStateIndicators/uploadStatusIndicator.jsx b/app/src/pages/common/uploadFileControls/filesDropzone/importFileIcon/iconStateIndicators/uploadStatusIndicator.jsx
similarity index 100%
rename from app/src/pages/common/modals/importModal/importFileIcon/iconStateIndicators/uploadStatusIndicator.jsx
rename to app/src/pages/common/uploadFileControls/filesDropzone/importFileIcon/iconStateIndicators/uploadStatusIndicator.jsx
diff --git a/app/src/pages/common/modals/importModal/importFileIcon/iconStateIndicators/uploadedIcon.jsx b/app/src/pages/common/uploadFileControls/filesDropzone/importFileIcon/iconStateIndicators/uploadedIcon.jsx
similarity index 100%
rename from app/src/pages/common/modals/importModal/importFileIcon/iconStateIndicators/uploadedIcon.jsx
rename to app/src/pages/common/uploadFileControls/filesDropzone/importFileIcon/iconStateIndicators/uploadedIcon.jsx
diff --git a/app/src/pages/common/modals/importModal/importFileIcon/importFileIcon.jsx b/app/src/pages/common/uploadFileControls/filesDropzone/importFileIcon/importFileIcon.jsx
similarity index 88%
rename from app/src/pages/common/modals/importModal/importFileIcon/importFileIcon.jsx
rename to app/src/pages/common/uploadFileControls/filesDropzone/importFileIcon/importFileIcon.jsx
index 8519d82451..a7fe5597e8 100644
--- a/app/src/pages/common/modals/importModal/importFileIcon/importFileIcon.jsx
+++ b/app/src/pages/common/uploadFileControls/filesDropzone/importFileIcon/importFileIcon.jsx
@@ -21,6 +21,7 @@ import classNames from 'classnames/bind';
import { fileSizeConverter } from 'common/utils';
import SheetIcon from 'common/img/file-icon-inline.svg';
import DeleteIcon from 'common/img/icon-delete-inline.svg';
+import { fileTypeFields } from '../../propTypes';
import { ProgressLoader } from './progressLoader';
import { InvalidIcon, UploadIndicator } from './iconStateIndicators';
import styles from './importFileIcon.scss';
@@ -74,28 +75,18 @@ export const ImportFileIcon = ({
)}
{!(uploaded || isLoading) && (
-