diff --git a/ui/.eslintrc b/ui/.eslintrc index 5586611a85..05d18446ec 100644 --- a/ui/.eslintrc +++ b/ui/.eslintrc @@ -55,6 +55,7 @@ "react/destructuring-assignment": "off", "react/prefer-stateless-function": "off", "react-hooks/rules-of-hooks": "error", + "react/jsx-no-target-blank": "off", "react/jsx-filename-extension": [ 2, { "extensions": [".js", ".jsx", ".ts", ".tsx"] } diff --git a/ui/src/actions/actionTypes.ts b/ui/src/actions/actionTypes.ts index cbcaa30cc8..4b60151c72 100644 --- a/ui/src/actions/actionTypes.ts +++ b/ui/src/actions/actionTypes.ts @@ -144,3 +144,9 @@ export const HOLDINGPEN_SEARCH_QUERY_RESET = 'HOLDINGPEN_SEARCH_QUERY_RESET'; export const HOLDINGPEN_AUTHOR_REQUEST = 'HOLDINGPEN_AUTHOR_REQUEST'; export const HOLDINGPEN_AUTHOR_ERROR = 'HOLDINGPEN_AUTHOR_ERROR'; export const HOLDINGPEN_AUTHOR_SUCCESS = 'HOLDINGPEN_AUTHOR_SUCCESS'; +export const HOLDINGPEN_RESOLVE_ACTION_REQUEST = + 'HOLDINGPEN_RESOLVE_ACTION_REQUEST'; +export const HOLDINGPEN_RESOLVE_ACTION_SUCCESS = + 'HOLDINGPEN_RESOLVE_ACTION_SUCCESS'; +export const HOLDINGPEN_RESOLVE_ACTION_ERROR = + 'HOLDINGPEN_RESOLVE_ACTION_ERROR'; diff --git a/ui/src/actions/holdingpen.ts b/ui/src/actions/holdingpen.ts index faea84602f..f618828b5b 100644 --- a/ui/src/actions/holdingpen.ts +++ b/ui/src/actions/holdingpen.ts @@ -17,6 +17,9 @@ import { HOLDINGPEN_AUTHOR_REQUEST, HOLDINGPEN_AUTHOR_SUCCESS, HOLDINGPEN_SEARCH_QUERY_RESET, + HOLDINGPEN_RESOLVE_ACTION_REQUEST, + HOLDINGPEN_RESOLVE_ACTION_SUCCESS, + HOLDINGPEN_RESOLVE_ACTION_ERROR, } from './actionTypes'; import { BACKOFFICE_API, @@ -27,7 +30,11 @@ import { } from '../common/routes'; import { Credentials } from '../types'; import storage from '../common/storage'; -import { notifyLoginError } from '../holdingpen-new/notifications'; +import { + notifyLoginError, + notifyActionError, + notifyActionSuccess, +} from '../holdingpen-new/notifications'; import { refreshToken } from '../holdingpen-new/utils/utils'; const httpClient = axios.create(); @@ -70,6 +77,7 @@ httpClient.interceptors.response.use( } ); +// LOGIN ACTIONS export function holdingpenLoginSuccess() { return { type: HOLDINGPEN_LOGIN_SUCCESS, @@ -89,59 +97,6 @@ function holdingpenLogoutSuccess() { }; } -function searching() { - return { - type: HOLDINGPEN_SEARCH_REQUEST, - }; -} - -function searchSuccess(data: any) { - return { - type: HOLDINGPEN_SEARCH_SUCCESS, - payload: { data }, - }; -} - -function searchError(errorPayload: { error: Error }) { - return { - type: HOLDINGPEN_SEARCH_ERROR, - payload: { ...errorPayload }, - }; -} - -function fetchingAuthor() { - return { - type: HOLDINGPEN_AUTHOR_REQUEST, - }; -} - -function fetchAuthorSuccess(data: any) { - return { - type: HOLDINGPEN_AUTHOR_SUCCESS, - payload: { data }, - }; -} - -function fetchAuthorError(errorPayload: { error: Error }) { - return { - type: HOLDINGPEN_AUTHOR_ERROR, - payload: { ...errorPayload }, - }; -} - -function updateQuery(data: any) { - return { - type: HOLDINGPEN_SEARCH_QUERY_UPDATE, - payload: data, - }; -} - -function resetQuery() { - return { - type: HOLDINGPEN_SEARCH_QUERY_RESET, - }; -} - export function holdingpenLogin( credentials: Credentials ): (dispatch: ActionCreator) => Promise { @@ -192,6 +147,57 @@ export function holdingpenLogout(): ( }; } +// SEARCH ACTIONS +function searching() { + return { + type: HOLDINGPEN_SEARCH_REQUEST, + }; +} + +function searchSuccess(data: any) { + return { + type: HOLDINGPEN_SEARCH_SUCCESS, + payload: { data }, + }; +} + +function searchError(errorPayload: { error: Error }) { + return { + type: HOLDINGPEN_SEARCH_ERROR, + payload: { ...errorPayload }, + }; +} + +function updateQuery(data: any) { + return { + type: HOLDINGPEN_SEARCH_QUERY_UPDATE, + payload: data, + }; +} + +function resetQuery() { + return { + type: HOLDINGPEN_SEARCH_QUERY_RESET, + }; +} + +type QueryParams = { page: number; size: number; [key: string]: any }; +export function searchQueryUpdate( + query: QueryParams +): (dispatch: ActionCreator) => Promise { + return async (dispatch) => { + dispatch(updateQuery(query)); + }; +} + +export function searchQueryReset(): ( + dispatch: ActionCreator +) => Promise { + return async (dispatch) => { + dispatch(resetQuery()); + }; +} + export function fetchSearchResults(): ( dispatch: ActionCreator, getState: () => RootStateOrAny @@ -200,7 +206,6 @@ export function fetchSearchResults(): ( dispatch(searching()); const currentQuery = getState()?.holdingpen?.get('query')?.toJS() || {}; - const resolveQuery = `${BACKOFFICE_SEARCH_API}/?${ Object.entries(currentQuery) ?.map(([key, value]: [string, any]) => `${key}=${value}`) @@ -217,6 +222,27 @@ export function fetchSearchResults(): ( }; } +// AUTHOR ACTIONS +function fetchingAuthor() { + return { + type: HOLDINGPEN_AUTHOR_REQUEST, + }; +} + +function fetchAuthorSuccess(data: any) { + return { + type: HOLDINGPEN_AUTHOR_SUCCESS, + payload: { data }, + }; +} + +function fetchAuthorError(errorPayload: { error: Error }) { + return { + type: HOLDINGPEN_AUTHOR_ERROR, + payload: { ...errorPayload }, + }; +} + export function fetchAuthor( id: string ): (dispatch: ActionCreator) => Promise { @@ -234,19 +260,53 @@ export function fetchAuthor( }; } -type QueryParams = { page: number; size: number; [key: string]: any }; -export function searchQueryUpdate( - query: QueryParams -): (dispatch: ActionCreator) => Promise { - return async (dispatch) => { - dispatch(updateQuery(query)); +// DECISSION ACTIONS +function resolvingAction(type: string) { + return { + type: HOLDINGPEN_RESOLVE_ACTION_REQUEST, + payload: { type }, }; } -export function searchQueryReset(): ( - dispatch: ActionCreator -) => Promise { +function resolveActionSuccess() { + return { + type: HOLDINGPEN_RESOLVE_ACTION_SUCCESS, + }; +} + +function resolveActionError(errorPayload: { error: Error }) { + return { + type: HOLDINGPEN_RESOLVE_ACTION_ERROR, + payload: { ...errorPayload }, + }; +} + +export function resolveAction( + id: string, + action: string, + payload: any +): (dispatch: ActionCreator) => Promise { return async (dispatch) => { - dispatch(resetQuery()); + dispatch(resolvingAction(action)); + try { + await httpClient.post( + `${BACKOFFICE_API}/authors/${id}/${action}/`, + payload + ); + + dispatch(resolveActionSuccess()); + notifyActionSuccess(action); + setTimeout(() => { + window?.location?.reload(); + }, 3000); + } catch (err) { + const { error } = httpErrorToActionPayload(err); + notifyActionError( + (typeof error?.error === 'string' + ? error?.error + : error?.error?.detail) || 'An error occurred' + ); + dispatch(resolveActionError(error)); + } }; } diff --git a/ui/src/authors/components/AssignNoProfileAction.tsx b/ui/src/authors/components/AssignNoProfileAction.tsx index c8775878c8..4f16345f46 100644 --- a/ui/src/authors/components/AssignNoProfileAction.tsx +++ b/ui/src/authors/components/AssignNoProfileAction.tsx @@ -12,7 +12,6 @@ export const CLAIMING_DISABLED_INFO = ( contact us diff --git a/ui/src/authors/components/EditAuthorRecordAction.tsx b/ui/src/authors/components/EditAuthorRecordAction.tsx index 5fd1ec175d..182713bb59 100644 --- a/ui/src/authors/components/EditAuthorRecordAction.tsx +++ b/ui/src/authors/components/EditAuthorRecordAction.tsx @@ -17,7 +17,6 @@ const CAN_NOT_EDIT_AUTHOR_MESSAGE = ( contact us diff --git a/ui/src/authors/components/__tests__/__snapshots__/AssignNoProfileAction.test.jsx.snap b/ui/src/authors/components/__tests__/__snapshots__/AssignNoProfileAction.test.jsx.snap index bb2102a6af..28499b0e45 100644 --- a/ui/src/authors/components/__tests__/__snapshots__/AssignNoProfileAction.test.jsx.snap +++ b/ui/src/authors/components/__tests__/__snapshots__/AssignNoProfileAction.test.jsx.snap @@ -12,7 +12,6 @@ exports[`AssignNoProfileAction renders 1`] = ` contact us diff --git a/ui/src/common/components/UserFeedback/UserFeedback.jsx b/ui/src/common/components/UserFeedback/UserFeedback.jsx index 9c138b5046..89a010ea77 100644 --- a/ui/src/common/components/UserFeedback/UserFeedback.jsx +++ b/ui/src/common/components/UserFeedback/UserFeedback.jsx @@ -122,7 +122,6 @@ class UserFeedback extends Component { contact us diff --git a/ui/src/common/components/UserFeedback/__tests__/__snapshots__/UserFeedback.test.jsx.snap b/ui/src/common/components/UserFeedback/__tests__/__snapshots__/UserFeedback.test.jsx.snap index 6b9b33cc82..962af15deb 100644 --- a/ui/src/common/components/UserFeedback/__tests__/__snapshots__/UserFeedback.test.jsx.snap +++ b/ui/src/common/components/UserFeedback/__tests__/__snapshots__/UserFeedback.test.jsx.snap @@ -172,7 +172,6 @@ exports[`UserFeedback renders when tracker is blocked 1`] = ` or contact us diff --git a/ui/src/common/layouts/Header/HeaderMenu.tsx b/ui/src/common/layouts/Header/HeaderMenu.tsx index 16a3cae2df..9be1509ffd 100644 --- a/ui/src/common/layouts/Header/HeaderMenu.tsx +++ b/ui/src/common/layouts/Header/HeaderMenu.tsx @@ -206,7 +206,11 @@ const HeaderMenu = ({ loggedInToHoldingpen && { key: 'logout-holdingpen', label: [ - onLogout()}> + onLogout()} + key="logout-holdingpen" + > Logout Holdingpen , ], diff --git a/ui/src/common/layouts/Header/__tests__/__snapshots__/HeaderMenu.test.jsx.snap b/ui/src/common/layouts/Header/__tests__/__snapshots__/HeaderMenu.test.jsx.snap index e1ab19e53d..60e6523bfe 100644 --- a/ui/src/common/layouts/Header/__tests__/__snapshots__/HeaderMenu.test.jsx.snap +++ b/ui/src/common/layouts/Header/__tests__/__snapshots__/HeaderMenu.test.jsx.snap @@ -129,7 +129,6 @@ exports[`HeaderMenu renders when logged in 1`] = ` contact us diff --git a/ui/src/holdingpen-new/components/AuthorResultItem.tsx b/ui/src/holdingpen-new/components/AuthorResultItem.tsx index d0791d627a..831533ebd6 100644 --- a/ui/src/holdingpen-new/components/AuthorResultItem.tsx +++ b/ui/src/holdingpen-new/components/AuthorResultItem.tsx @@ -2,6 +2,7 @@ import React from 'react'; import { CheckOutlined, + LoadingOutlined, StopOutlined, WarningOutlined, } from '@ant-design/icons'; @@ -34,7 +35,7 @@ const renderWorkflowStatus = (status: string) => { }, approval: { icon: , - text: 'Halted', + text: 'Waiting for approval', description: 'This workflow has been halted until decision is made.', }, error: { @@ -43,6 +44,12 @@ const renderWorkflowStatus = (status: string) => { description: 'This record is in error state. View record details for more information.', }, + running: { + icon: , + text: 'Running', + description: + 'This workflow is currently running. Please wait for it to complete.', + }, }; const statusInfo = statuses[status]; diff --git a/ui/src/holdingpen-new/components/Links.tsx b/ui/src/holdingpen-new/components/Links.tsx new file mode 100644 index 0000000000..a7a6f9d22a --- /dev/null +++ b/ui/src/holdingpen-new/components/Links.tsx @@ -0,0 +1,72 @@ +import React from 'react'; +import { Map } from 'immutable'; +import { + LinkOutlined, + LinkedinOutlined, + TwitterOutlined, +} from '@ant-design/icons'; + +import orcidLogo from '../../common/assets/orcid.svg'; + +interface LinksProps { + urls: Map; + ids: Map; +} + +const Links: React.FC = ({ urls, ids }) => { + function getLinkData(schema: string, value: string) { + switch (schema) { + case 'LINKEDIN': + return { + href: `https://www.linkedin.com/in/${value}`, + icon: , + }; + case 'TWITTER': + return { + href: `https://twitter.com/${value}`, + icon: , + }; + case 'ORCID': + return { + href: `https://orcid.org/my-orcid?orcid=${value}`, + icon: ORCID, + }; + default: + return { + href: value, + icon: , + }; + } + } + return ( + <> + {ids?.map((link: Map) => ( +

+ {getLinkData(link?.get('schema'), link?.get('value'))?.icon} + {link?.get('schema') && ( + {link?.get('schema').toLowerCase()}: + )}{' '} + + {link?.get('value')} + +

+ ))} + {urls?.map((link: Map) => ( +

+ {getLinkData(link?.get('schema'), link?.get('value'))?.icon} + {link?.get('description') && ( + {link?.get('description')}: + )}{' '} + + {link?.get('value')} + +

+ ))} + + ); +}; + +export default Links; diff --git a/ui/src/holdingpen-new/containers/DashboardPageContainer/DashboardPageContainer.less b/ui/src/holdingpen-new/containers/DashboardPageContainer/DashboardPageContainer.less index feb96c762a..9d5fd660ef 100644 --- a/ui/src/holdingpen-new/containers/DashboardPageContainer/DashboardPageContainer.less +++ b/ui/src/holdingpen-new/containers/DashboardPageContainer/DashboardPageContainer.less @@ -61,7 +61,8 @@ } // Color palette -.waiting { +.waiting, +.running { color: #7b898a; } .error { @@ -74,9 +75,6 @@ .completed { color: #16a085; } -.running { - color: black; -} .initial { color: black; } @@ -90,6 +88,9 @@ .bg-completed { background-color: #16a085; } +.bg-running { + background-color: #b8b8b8; +} .bg-halted, .bg-approval { background-color: #f39c12; diff --git a/ui/src/holdingpen-new/containers/DashboardPageContainer/mockData.ts b/ui/src/holdingpen-new/containers/DashboardPageContainer/mockData.ts deleted file mode 100644 index dd018780e9..0000000000 --- a/ui/src/holdingpen-new/containers/DashboardPageContainer/mockData.ts +++ /dev/null @@ -1,133 +0,0 @@ -export const tasks = [ - { - title: 'new authors', - total: 1, - actions: [ - { action: 'Waiting', number: 0 }, - { action: 'Error', number: 1 }, - { action: 'Halted', number: 0 }, - { action: 'Completed', number: 0 }, - { action: 'Running', number: 0 }, - { action: 'Initial', number: 0 }, - ], - }, - { - title: 'author updates', - total: 0, - actions: [ - { action: 'Waiting', number: 0 }, - { action: 'Error', number: 0 }, - { action: 'Halted', number: 0 }, - { action: 'Completed', number: 0 }, - { action: 'Running', number: 0 }, - { action: 'Initial', number: 0 }, - ], - }, - { - title: 'new arxiv harvests', - total: 2323, - actions: [ - { action: 'Waiting', number: 0 }, - { action: 'Error', number: 1 }, - { action: 'Halted', number: 2 }, - { action: 'Completed', number: 3 }, - { action: 'Running', number: 4 }, - { action: 'Initial', number: 5 }, - ], - }, - { - title: 'Arxiv updates', - total: 329927, - actions: [ - { action: 'Waiting', number: 0 }, - { action: 'Error', number: 1 }, - { action: 'Halted', number: 2 }, - { action: 'Completed', number: 3 }, - { action: 'Running', number: 4 }, - { action: 'Initial', number: 5 }, - ], - }, - { - title: 'New literature submissions', - total: 2, - actions: [ - { action: 'Waiting', number: 0 }, - { action: 'Error', number: 1 }, - { action: 'Halted', number: 2 }, - { action: 'Completed', number: 3 }, - { action: 'Running', number: 4 }, - { action: 'Initial', number: 5 }, - ], - }, - { - title: 'New publisher harvests', - total: 756, - actions: [ - { action: 'Waiting', number: 0 }, - { action: 'Error', number: 1 }, - { action: 'Halted', number: 2 }, - { action: 'Completed', number: 3 }, - { action: 'Running', number: 4 }, - { action: 'Initial', number: 5 }, - ], - }, - { - title: 'Publisher updates', - total: 2777, - actions: [ - { action: 'Waiting', number: 0 }, - { action: 'Error', number: 1 }, - { action: 'Halted', number: 2 }, - { action: 'Completed', number: 3 }, - { action: 'Running', number: 4 }, - { action: 'Initial', number: 5 }, - ], - }, - { - title: 'all harvests', - total: 23232, - actions: [ - { action: 'Waiting', number: 0 }, - { action: 'Error', number: 1 }, - { action: 'Halted', number: 2 }, - { action: 'Completed', number: 3 }, - { action: 'Running', number: 4 }, - { action: 'Initial', number: 5 }, - ], - }, -]; - -export const actions = [ - { - title: 'merging', - total: 110, - actions: [ - { action: 'Awaiting decision', number: 21 }, - { action: 'Completed', number: 89 }, - ], - }, - { - title: 'matching', - total: 70, - actions: [ - { action: 'Awaiting decision', number: 14 }, - { action: 'Completed', number: 56 }, - ], - }, - { - title: 'core selection', - total: 33, - actions: [ - { action: 'Awaiting decision', number: 30 }, - { action: 'Completed', number: 3 }, - ], - }, - { - title: 'core selection approval', - total: 923, - actions: [ - { action: 'Awaiting decision', number: 30 }, - { action: 'Completed', number: 893 }, - ], - }, -]; diff --git a/ui/src/holdingpen-new/containers/DetailPageContainer/AuthorDetailPageContainer.tsx b/ui/src/holdingpen-new/containers/DetailPageContainer/AuthorDetailPageContainer.tsx index 0dad32c564..2a8f04d1b8 100644 --- a/ui/src/holdingpen-new/containers/DetailPageContainer/AuthorDetailPageContainer.tsx +++ b/ui/src/holdingpen-new/containers/DetailPageContainer/AuthorDetailPageContainer.tsx @@ -1,17 +1,12 @@ /* eslint-disable react-hooks/exhaustive-deps */ -/* eslint-disable no-underscore-dangle */ import React, { useEffect } from 'react'; import { useParams } from 'react-router-dom'; import { Row, Col, Button, Table } from 'antd'; import { - LinkOutlined, EditOutlined, RedoOutlined, SyncOutlined, - CheckCircleOutlined, - CloseCircleOutlined, PlayCircleOutlined, - CloseOutlined, } from '@ant-design/icons'; import { Action, ActionCreator } from 'redux'; import { connect, RootStateOrAny } from 'react-redux'; @@ -22,109 +17,27 @@ import Breadcrumbs from '../../components/Breadcrumbs'; import ContentBox from '../../../common/components/ContentBox'; import CollapsableForm from '../../../submissions/common/components/CollapsableForm'; import LoadingOrChildren from '../../../common/components/LoadingOrChildren'; -import { fetchAuthor } from '../../../actions/holdingpen'; +import { fetchAuthor, resolveAction } from '../../../actions/holdingpen'; +import Links from '../../components/Links'; +import { + columnsInstitutions, + columnsProjects, + columnsSubject, + columnsAdvisors, +} from './columnData'; interface AuthorDetailPageContainerProps { dispatch: ActionCreator; author: Map; loading: boolean; + actionInProgress: string | false; } -const columnsInstitutions = [ - { - title: 'Institution', - dataIndex: 'institution', - }, - { - title: 'Start date', - dataIndex: 'start_date', - render: (start: string) => (!start ? '-' : start), - }, - { - title: 'End date', - dataIndex: 'end_date', - render: (end: string) => (!end ? 'Present' : end), - }, - { - title: 'Rank', - dataIndex: 'rank', - render: (rank: string) => (!rank ? '-' : rank), - }, - { - title: 'Current', - dataIndex: 'current', - render: (current: boolean) => - current ? ( - - ) : ( - - ), - align: 'center' as const, - }, -]; - -const columnsProjects = [ - { - title: 'Project name', - dataIndex: 'name', - }, - { - title: 'Current', - dataIndex: 'current', - render: (current: boolean) => - current ? ( - - ) : ( - - ), - align: 'center' as const, - }, - { - title: 'Start date', - dataIndex: 'start_date', - render: (start: string) => (!start ? '-' : start), - }, - { - title: 'End date', - dataIndex: 'end_date', - render: (end: string) => (!end ? 'Present' : end), - }, -]; - -const columnsSubject = [ - { - title: 'Term', - dataIndex: 'term', - }, - { - title: 'Action', - // TODO: Add action to remove term - render: () => ( - - - - ), - width: '10%', - align: 'center' as const, - }, -]; - -const columnsAdvisors = [ - { - title: 'Name', - dataIndex: 'name', - }, - { - title: 'Position', - dataIndex: 'degree_type', - render: (deg: string) => (!deg ? '-' : deg), - }, -]; - const AuthorDetailPageContainer: React.FC = ({ dispatch, author, loading, + actionInProgress, }) => { const { id } = useParams<{ id: string }>(); @@ -167,12 +80,6 @@ const AuthorDetailPageContainer: React.FC = ({ >

{author?.get('status').toUpperCase()} - {author?.get('status') !== 'completed' - ? ` on: "${ - author?.get('_message') || - author?.get('_last_task_name') - }"` - : ''}

@@ -202,7 +109,6 @@ const AuthorDetailPageContainer: React.FC = ({ 'orcid', ])}`} target="_blank" - rel="noreferrer" > {data?.getIn(['acquisition_source', 'orcid'])} @@ -236,42 +142,9 @@ const AuthorDetailPageContainer: React.FC = ({ rowKey={(record) => `${record?.name}+${Math.random()}`} /> - {data?.get('urls') && ( + {(data?.get('urls') || data?.get('ids')) && ( - {data?.get('ids')?.map((link: Map) => ( -

- - {link?.get('schema') && ( - - {link?.get('schema').toLowerCase()}: - - )}{' '} - - {link?.get('value')} - -

- ))} - {data?.get('urls')?.map((link: Map) => ( -

- - {link?.get('description') && ( - - {link?.get('description')}: - - )}{' '} - {link?.get('value')} -

- ))} +
)} @@ -318,26 +191,60 @@ const AuthorDetailPageContainer: React.FC = ({ - -
- - - - -
-
+ {author?.get('status') && + author?.get('status') === 'approval' && ( + +
+ + {/* TODO1: change to acceptSubmissionWithCuration once it's ready */} + + +
+
+ )} = ({ . - {/* TODO: find out how notes are stored in workflow */} - {data?.get('notes') && ( + {data?.get('_private_notes') && ( - "Thank you for reviewing my submission" + + {data?.get('_private_notes')?.map((note: any) => ( +

+ "{note?.get('value')}" +

+ ))} +
)} = ({ subTitle="SNow information" > {author?.get('ticket_id') && ( - + See related ticket #{author?.get('ticket_id')} )} - +
- - @@ -391,14 +317,18 @@ const AuthorDetailPageContainer: React.FC = ({ {' '} Open in Editor - @@ -416,6 +346,7 @@ const AuthorDetailPageContainer: React.FC = ({ const stateToProps = (state: RootStateOrAny) => ({ author: state.holdingpen.get('author'), loading: state.holdingpen.get('loading'), + actionInProgress: state.holdingpen.get('actionInProgress'), }); export default connect(stateToProps)(AuthorDetailPageContainer); diff --git a/ui/src/holdingpen-new/containers/DetailPageContainer/DetailPageContainer.less b/ui/src/holdingpen-new/containers/DetailPageContainer/DetailPageContainer.less index be095566e6..84d170d8f3 100644 --- a/ui/src/holdingpen-new/containers/DetailPageContainer/DetailPageContainer.less +++ b/ui/src/holdingpen-new/containers/DetailPageContainer/DetailPageContainer.less @@ -1,6 +1,25 @@ .__DetailPageContainer__ { width: 100%; + .ant-btn:hover, + .ant-btn:focus, + .ant-btn:active, + .ant-btn:focus-visible, + .ant-btn:focus-within { + &.bg-completed { + background-color: #16bb9a; + border: 1px solid #16bb9a; + } + &.bg-error { + background-color: #e3685b; + border: 1px solid #e3685b; + } + &.bg-halted { + background-color: #f7b852; + border: 1px solid #f7b852; + } + } + .ant-collapse-content-box { padding-bottom: 1rem; .error-code { @@ -19,20 +38,4 @@ border: none; } } - - .ant-switch-checked { - background-color: #16a085; - } - - .ant-btn:hover { - &.bg-completed { - background-color: #16bb9a; - } - &.bg-error { - background-color: #e3685b; - } - &.bg-halted { - background-color: #f7b852; - } - } } diff --git a/ui/src/holdingpen-new/containers/DetailPageContainer/columnData.tsx b/ui/src/holdingpen-new/containers/DetailPageContainer/columnData.tsx new file mode 100644 index 0000000000..46b765de3c --- /dev/null +++ b/ui/src/holdingpen-new/containers/DetailPageContainer/columnData.tsx @@ -0,0 +1,97 @@ +import React from 'react'; +import { + CheckCircleOutlined, + CloseCircleOutlined, + CloseOutlined, +} from '@ant-design/icons'; + +export const columnsInstitutions = [ + { + title: 'Institution', + dataIndex: 'institution', + }, + { + title: 'Start date', + dataIndex: 'start_date', + render: (start: string) => (!start ? '-' : start), + }, + { + title: 'End date', + dataIndex: 'end_date', + render: (end: string) => (!end ? 'Present' : end), + }, + { + title: 'Rank', + dataIndex: 'rank', + render: (rank: string) => (!rank ? '-' : rank), + }, + { + title: 'Current', + dataIndex: 'current', + render: (current: boolean) => + current ? ( + + ) : ( + + ), + align: 'center' as const, + }, +]; + +export const columnsProjects = [ + { + title: 'Project name', + dataIndex: 'name', + }, + { + title: 'Current', + dataIndex: 'current', + render: (current: boolean) => + current ? ( + + ) : ( + + ), + align: 'center' as const, + }, + { + title: 'Start date', + dataIndex: 'start_date', + render: (start: string) => (!start ? '-' : start), + }, + { + title: 'End date', + dataIndex: 'end_date', + render: (end: string) => (!end ? 'Present' : end), + }, +]; + +export const columnsSubject = [ + { + title: 'Term', + dataIndex: 'term', + }, + { + title: 'Action', + // TODO 0: Add action to remove term + render: () => ( + + + + ), + width: '10%', + align: 'center' as const, + }, +]; + +export const columnsAdvisors = [ + { + title: 'Name', + dataIndex: 'name', + }, + { + title: 'Position', + dataIndex: 'degree_type', + render: (deg: string) => (!deg ? '-' : deg), + }, +]; diff --git a/ui/src/holdingpen-new/mocks/mockAuthorData.ts b/ui/src/holdingpen-new/mocks/mockAuthorData.ts deleted file mode 100644 index 4399724728..0000000000 --- a/ui/src/holdingpen-new/mocks/mockAuthorData.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { List, Map } from 'immutable'; - -export default Map({ - id: 123456, - display_name: 'Doe, John Marc', - name: Map({ title: 'John Marc Doe' }), - preferred_name: 'Johnny Marc Doe', - status: 'active', - orcid: '0000-0000-0000-0000', - author_profile: Map({ - url: 'https://inspirehep.net/authors/1072974', - value: 'J.D.Siemieniuk.1', - }), - institutions: List([ - Map({ - name: 'University of Toronto', - rank: 1, - start_date: '2019', - end_date: '-', - current: 'true', - }), - Map({ - name: 'Sunnybrook Health Sciences Centre', - rank: 2, - start_date: '2007', - end_date: '2019', - current: 'false', - }), - Map({ - name: 'University of Warsaw', - rank: 3, - start_date: '1998', - end_date: '2007', - current: 'false', - }), - ]), - projects: List([ - Map({ - name: 'Project A', - start_date: '2019', - end_date: '-', - current: 'true', - }), - Map({ - name: 'Project B', - start_date: '2007', - end_date: '2019', - current: 'false', - }), - Map({ - name: 'Project C', - start_date: '1998', - end_date: '2007', - current: 'false', - }), - ]), - subject_areas: List([ - Map({ - term: 'hep-ex', - }), - Map({ - term: 'hep-ph', - }), - ]), - advisors: List([ - Map({ - name: 'Giri, Anjan', - position: 'PhD', - }), - Map({ - name: 'Gugri, Injan', - position: 'PhD', - }), - ]), -}); diff --git a/ui/src/holdingpen-new/notifications.ts b/ui/src/holdingpen-new/notifications.ts index 6d5fe6be7d..de5d353f45 100644 --- a/ui/src/holdingpen-new/notifications.ts +++ b/ui/src/holdingpen-new/notifications.ts @@ -1,10 +1,27 @@ import React from 'react'; import { notification } from 'antd'; +import _ from 'lodash'; export function notifyLoginError(error: string) { notification.error({ message: 'Login unsuccessful', description: error, - duration: 2, + duration: 7, + }); +} + +export function notifyActionSuccess(action: string) { + notification.success({ + message: 'Success', + description: `${_.capitalize(action)} performed successfully`, + duration: 10, + }); +} + +export function notifyActionError(error: string) { + notification.error({ + message: 'Unable to perform action', + description: error, + duration: 10, }); } diff --git a/ui/src/holdingpen-new/utils/utils.ts b/ui/src/holdingpen-new/utils/utils.ts index 6e37c5db8b..e9ac74d80b 100644 --- a/ui/src/holdingpen-new/utils/utils.ts +++ b/ui/src/holdingpen-new/utils/utils.ts @@ -1,5 +1,9 @@ import storage from '../../common/storage'; -import { BACKOFFICE_LOGIN, HOLDINGPEN_LOGIN_NEW } from '../../common/routes'; +import { + BACKOFFICE_API, + BACKOFFICE_LOGIN, + HOLDINGPEN_LOGIN_NEW, +} from '../../common/routes'; export const refreshToken = async () => { try { diff --git a/ui/src/literature/assignNotification.jsx b/ui/src/literature/assignNotification.jsx index a5f338869e..5e14957995 100644 --- a/ui/src/literature/assignNotification.jsx +++ b/ui/src/literature/assignNotification.jsx @@ -56,9 +56,7 @@ export function assignSuccess({ conferenceId, conferenceTitle, papers }) { {papers.size} selected {pluralizeUnlessSingle('paper', papers.size)}{' '} assigned to{' '} - + {conferenceTitle} @@ -86,7 +84,6 @@ export function assignLiteratureItemError(key) { contact us diff --git a/ui/src/reducers/holdingpen.js b/ui/src/reducers/holdingpen.js index 911427c159..86ac2637b8 100644 --- a/ui/src/reducers/holdingpen.js +++ b/ui/src/reducers/holdingpen.js @@ -12,6 +12,9 @@ import { HOLDINGPEN_AUTHOR_SUCCESS, HOLDINGPEN_SEARCH_QUERY_UPDATE, HOLDINGPEN_SEARCH_QUERY_RESET, + HOLDINGPEN_RESOLVE_ACTION_REQUEST, + HOLDINGPEN_RESOLVE_ACTION_SUCCESS, + HOLDINGPEN_RESOLVE_ACTION_ERROR, } from '../actions/actionTypes'; export const initialState = fromJS({ @@ -22,6 +25,7 @@ export const initialState = fromJS({ loading: false, author: [], facets: [], + actionInProgress: false, }); const HOLDINGPENReducer = (state = initialState, action) => { @@ -59,6 +63,12 @@ const HOLDINGPENReducer = (state = initialState, action) => { return state.set('query', fromJS(action.payload)); case HOLDINGPEN_SEARCH_QUERY_RESET: return state.set('query', fromJS({ page: 1, size: 10 })); + case HOLDINGPEN_RESOLVE_ACTION_REQUEST: + return state.set('actionInProgress', fromJS(action.payload.type)); + case HOLDINGPEN_RESOLVE_ACTION_SUCCESS: + return state.set('actionInProgress', false); + case HOLDINGPEN_RESOLVE_ACTION_ERROR: + return state.set('actionInProgress', false); default: return state; }