diff --git a/README.adoc b/README.adoc index 5db4c9ffb8..e74c0f12aa 100644 --- a/README.adoc +++ b/README.adoc @@ -1239,7 +1239,7 @@ curl -X POST -H 'Content-type: application/json' -H 'Accept: application/json' - |=== 3+| ``POST /api/views/count`` -3+| Count rows of a view matching request filters. +3+| Count rows of a view matching request filters. If `maxDisplayCount` configured in the `views.yaml` for a view, then the count for the view is limited by this value if total count exceeds it. Otherwise, the total count is returned. 3+| _Parameters:_ | ``view`` | string @@ -2685,7 +2685,7 @@ Create DNS records for the ``keycloak.example.com``, ``fairspace.example.com`` a # List available fairspace chart versions ~/bin/helm/helm search repo --versions fairspace/fairspace # Fetch the fairspace chart -~/bin/helm/helm pull fairspace/fairspace --version 1.0.1 +~/bin/helm/helm pull fairspace/fairspace --version 2.0.1 ---- ===== Deploy Keycloak @@ -2773,7 +2773,7 @@ Create a new deployment (called _release_ in helm terminology) and install the Fairspace chart: [source, shell] ---- -~/bin/helm/helm install fairspace-new fairspace/fairspace --version 1.0.1 --namespace fairspace-new \ +~/bin/helm/helm install fairspace-new fairspace/fairspace --version 2.0.1 --namespace fairspace-new \ -f /path/to/values.yaml --set-file saturn.vocabulary=/path/to/vocabulary.ttl --set-file saturn.views=/path/to/views.yaml ---- You can pass values files with ``-f`` and provide a file for a specified @@ -2870,7 +2870,7 @@ Additionally, to include custom icons for `fairspace.icons` option, you need to [source, shell] ---- -~/bin/helm/helm install fairspace-new fairspace/fairspace --version 1.0.1 --namespace fairspace-new \ +~/bin/helm/helm install fairspace-new fairspace/fairspace --version 2.0.1 --namespace fairspace-new \ -f /path/to/values.yaml --set-file saturn.vocabulary=/path/to/vocabulary.ttl --set-file saturn.views=/path/to/views.yaml --set-file svgicons.extra-icon=/path/to/extra-icon.svg ---- @@ -2926,7 +2926,7 @@ jupyterhub: To update a deployment using a new chart: [source, shell] ---- -~/bin/helm/helm upgrade fairspace-new fairspace-1.0.1.tgz +~/bin/helm/helm upgrade fairspace-new fairspace-2.0.1.tgz ---- With ``helm upgrade`` you can also pass new values files with ``-f`` and pass files with ``--set-file`` as for ``helm install``. diff --git a/VERSION b/VERSION index 7dea76edb3..38f77a65b3 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.0.1 +2.0.1 diff --git a/charts/fairspace/templates/project/configmap-saturn.yaml b/charts/fairspace/templates/project/configmap-saturn.yaml index 3b71175112..8e8dc5a9a9 100644 --- a/charts/fairspace/templates/project/configmap-saturn.yaml +++ b/charts/fairspace/templates/project/configmap-saturn.yaml @@ -31,7 +31,7 @@ data: blobStorePath: "/data/saturn/files/blobs" viewDatabase: enabled: true - mvRefreshOnStartRequired: {{ default true .Values.saturn.mvRefreshOnStartRequired }} + mvRefreshOnStartRequired: {{ .Values.saturn.mvRefreshOnStartRequired }} features: {{ toYaml .Values.fairspace.features | indent 6 }} {{ if has "ExtraStorage" .Values.fairspace.features }} diff --git a/charts/fairspace/values.yaml b/charts/fairspace/values.yaml index f02ec27d36..7979ed5dc5 100644 --- a/charts/fairspace/values.yaml +++ b/charts/fairspace/values.yaml @@ -57,6 +57,7 @@ saturn: enableBasicAuth: true defaultUserRoles: - canViewPublicMetadata + mvRefreshOnStartRequired: true persistence: files: ## A manually managed Persistent Volume and Claim diff --git a/docs/images/screenshots/Collection browser.png b/docs/images/screenshots/Collection browser.png index 3dd2dd6e97..baaaef2c99 100644 Binary files a/docs/images/screenshots/Collection browser.png and b/docs/images/screenshots/Collection browser.png differ diff --git a/docs/images/screenshots/Keycloak login.png b/docs/images/screenshots/Keycloak login.png index 1a74e4707b..03c709bb21 100644 Binary files a/docs/images/screenshots/Keycloak login.png and b/docs/images/screenshots/Keycloak login.png differ diff --git a/docs/images/screenshots/Metadata form.png b/docs/images/screenshots/Metadata form.png index 58888e8e80..04e71b23d5 100644 Binary files a/docs/images/screenshots/Metadata form.png and b/docs/images/screenshots/Metadata form.png differ diff --git a/docs/images/screenshots/Metadata view.png b/docs/images/screenshots/Metadata view.png index e370f12221..4042a9f34e 100644 Binary files a/docs/images/screenshots/Metadata view.png and b/docs/images/screenshots/Metadata view.png differ diff --git a/docs/images/screenshots/Workspace list.png b/docs/images/screenshots/Workspace list.png index a9423b75cb..39ec5ec0a1 100644 Binary files a/docs/images/screenshots/Workspace list.png and b/docs/images/screenshots/Workspace list.png differ diff --git a/docs/images/screenshots/Workspace overview.png b/docs/images/screenshots/Workspace overview.png index 30ef018ca4..8d654ddd5c 100644 Binary files a/docs/images/screenshots/Workspace overview.png and b/docs/images/screenshots/Workspace overview.png differ diff --git a/projects/mercury/package.json b/projects/mercury/package.json index e67023883b..1a13d312e5 100644 --- a/projects/mercury/package.json +++ b/projects/mercury/package.json @@ -31,7 +31,7 @@ "@mui/x-date-pickers": "^5.0.11", "@testing-library/react-hooks": "^8.0.1", "@wojtekmaj/enzyme-adapter-react-17": "^0.8.0", - "axios": "^1.6.7", + "axios": "^1.7.5", "body-parser": "^1.19.0", "classnames": "^2.2.6", "cors": "^2.8.5", @@ -60,7 +60,7 @@ "text-table": "^0.2.0", "typeface-roboto": "^1.1.13", "use-deep-compare-effect": "^1.3.0", - "webdav": "^4.0.0" + "webdav": "^4.11.2" }, "devDependencies": { "@testing-library/jest-dom": "^5.16.5", diff --git a/projects/mercury/public/public/images/icon_white.png b/projects/mercury/public/public/images/icon_white.png new file mode 100644 index 0000000000..6291bdf6a9 Binary files /dev/null and b/projects/mercury/public/public/images/icon_white.png differ diff --git a/projects/mercury/public/public/images/logo_white.png b/projects/mercury/public/public/images/logo_white.png index 6291bdf6a9..298c8e1a02 100644 Binary files a/projects/mercury/public/public/images/logo_white.png and b/projects/mercury/public/public/images/logo_white.png differ diff --git a/projects/mercury/src/App.theme.js b/projects/mercury/src/App.theme.js index c4280d50a8..db5153ed63 100644 --- a/projects/mercury/src/App.theme.js +++ b/projects/mercury/src/App.theme.js @@ -1,10 +1,90 @@ import {createTheme} from '@mui/material'; -import {blue, indigo, pink} from '@mui/material/colors'; +import {pink} from '@mui/material/colors'; -export default createTheme({ +export const COLORS = { + fsBlueLight: 'rgba(106,134,232,1)', + fsBlueLightTransp25: 'rgba(106,134,232,0.25)', + fsBlueMedium: 'rgba(63,102,177,1)', + fsBlueDark: 'rgba(7, 59, 82, 1)' +}; + +const globalTheme = createTheme({ palette: { - primary: process.env.NODE_ENV === 'development' ? blue : indigo, - secondary: pink + primary: { + main: COLORS.fsBlueMedium, + light: COLORS.fsBlueLight, + dark: COLORS.fsBlueDark, + contrastText: 'white' + }, + secondary: { + main: '#ffdb56', + contrastText: 'black' + }, + error: pink, + success: { + main: '#08a045' + }, + background: { + default: '#ECEDF0' + }, + text: { + primary: COLORS.fsBlueDark, + secondary: COLORS.fsBlueMedium + }, + mellow: { + light: '#cfd8dc', + main: '#b0bec5', + dark: '#37474f', + contrastText: '#47008F' + } + }, + shape: { + borderRadius: 15 + } +}); + +export const scrollbarStyles = { + '&::-webkit-scrollbar': { + width: '0.5em', + height: '0.5em' + }, + '&::-webkit-scrollbar-track': { + boxShadow: 'inset 0 0 6px rgba(0,0,0,0.00)', + webkitBoxShadow: 'inset 0 0 6px rgba(0,0,0,0.00)', + margin: 2 + }, + '&::-webkit-scrollbar-thumb': { + backgroundColor: globalTheme.palette.mellow.light, + borderRadius: 5, + margin: 1 + }, + '&::-webkit-scrollbar-thumb:hover': { + backgroundColor: globalTheme.palette.mellow.main + } +}; + +export default createTheme({ + ...globalTheme, + typography: { + fontFamily: 'Poppins', + fontSize: 13, + button: { + textTransform: 'none' + }, + h3: { + fontSize: '1.4rem', + fontWeight: 600 + }, + h4: { + fontSize: '1.3rem', + fontWeight: 600 + }, + h5: { + fontSize: '1rem' + }, + body2: { + fontSize: '0.8rem' + } }, components: { MuiMenu: { @@ -26,7 +106,8 @@ export default createTheme({ MuiDivider: { styleOverrides: { root: { - margin: 0 + margin: 0, + borderColor: globalTheme.palette.mellow.main }, margin: 0 } @@ -88,12 +169,51 @@ export default createTheme({ } } }, + MuiButton: { + styleOverrides: { + root: { + background: globalTheme.palette.primary.dark, + '&:hover': { + background: globalTheme.palette.primary.light + }, + '&:disabled': { + opacity: 0.4, + color: globalTheme.palette.primary.contrastText, + background: globalTheme.palette.mellow.main + }, + borderRadius: globalTheme.shape.borderRadius, + borderColor: globalTheme.palette.primary.light, + paddingBottom: 0, + paddingTop: 0, + minHeight: 35 + }, + text: { + color: globalTheme.palette.primary.contrastText + } + } + }, MuiCardHeader: { styleOverrides: { root: { - backgroundColor: 'whitesmoke', + backgroundColor: globalTheme.palette.primary.main, marginBottom: 0, padding: 5 + }, + title: { + color: globalTheme.palette.primary.contrastText + }, + avatar: { + color: globalTheme.palette.primary.contrastText + }, + subheader: { + color: globalTheme.palette.primary.contrastText + } + } + }, + MuiCardContent: { + styleOverrides: { + root: { + borderRadius: globalTheme.shape.borderRadius } } }, @@ -117,6 +237,52 @@ export default createTheme({ } } } + }, + MuiPaper: { + styleOverrides: { + root: { + backgroundColor: globalTheme.palette.background.default, + border: '1px solid', + borderColor: globalTheme.palette.primary.dark, + ...scrollbarStyles + } + } + }, + MuiGrid: { + styleOverrides: { + root: { + ...scrollbarStyles + } + } + }, + MuiTableContainer: { + styleOverrides: { + root: { + ...scrollbarStyles + } + } + }, + MuiTablePagination: { + styleOverrides: { + root: { + ...scrollbarStyles + } + } + }, + MuiTableCell: { + styleOverrides: { + root: { + borderBottom: '1px solid', + borderColor: globalTheme.palette.mellow.main + } + } + }, + MuiTab: { + styleOverrides: { + root: { + fontSize: 15 + } + } } } }); diff --git a/projects/mercury/src/collections/CollectionDetails.js b/projects/mercury/src/collections/CollectionDetails.js index 23ecf5d6f3..9914b6cb20 100644 --- a/projects/mercury/src/collections/CollectionDetails.js +++ b/projects/mercury/src/collections/CollectionDetails.js @@ -4,6 +4,7 @@ import { Card, CardContent, CardHeader, + Divider, FormControl, FormGroup, FormLabel, @@ -18,6 +19,7 @@ import { } from '@mui/material'; import {CloudDownload, Folder, MoreVert} from '@mui/icons-material'; import {useHistory, withRouter} from 'react-router-dom'; +import withStyles from '@mui/styles/withStyles'; import CollectionEditor from './CollectionEditor'; import type {Collection, Resource, Status} from './CollectionAPI'; @@ -75,6 +77,14 @@ type CollectionDetailsState = { anchorEl: any }; +const styles = theme => ({ + card: { + '& .MuiCardHeader-root .MuiSvgIcon-root': { + color: theme.palette.primary.contrastText + } + } +}); + class CollectionDetails extends React.Component { static defaultProps = { onChangeOwner: () => {}, @@ -265,6 +275,7 @@ class CollectionDetails extends React.Component dateDeleted && [ + , Deleted @@ -273,6 +284,7 @@ class CollectionDetails extends React.Component , + , Deleted by @@ -351,7 +363,7 @@ class CollectionDetails extends React.Component - + @@ -388,7 +401,10 @@ class CollectionDetails extends React.Component - {this.renderCollectionOwner(ownerWorkspace)} + + {this.renderCollectionOwner(ownerWorkspace)} + + {this.renderCollectionStatus()} {this.renderDeleted(collection.dateDeleted, deletedBy)} @@ -540,4 +556,4 @@ const ContextualCollectionDetails = props => { ); }; -export default withRouter(ContextualCollectionDetails); +export default withRouter(withStyles(styles)(ContextualCollectionDetails)); diff --git a/projects/mercury/src/collections/CollectionEditor.js b/projects/mercury/src/collections/CollectionEditor.js index a1a81dd30c..872754f0f2 100644 --- a/projects/mercury/src/collections/CollectionEditor.js +++ b/projects/mercury/src/collections/CollectionEditor.js @@ -45,7 +45,7 @@ export const formatPrefix = (prefix: string) => (prefix ? `[${prefix.replace(/[/ const styles = theme => ({ textHelperBasic: { - color: theme.palette.grey['600'] + color: theme.palette.mellow.main }, textHelperWarning: { color: theme.palette.warning.dark diff --git a/projects/mercury/src/collections/CollectionInformationDrawer.js b/projects/mercury/src/collections/CollectionInformationDrawer.js index 077ea2bce9..6b4e1f2592 100644 --- a/projects/mercury/src/collections/CollectionInformationDrawer.js +++ b/projects/mercury/src/collections/CollectionInformationDrawer.js @@ -50,7 +50,10 @@ const useStyles = makeStyles(theme => ({ flexDirection: 'column', outline: 'none', transitionBorder: '.24s', - easeInOut: true + easeInOut: true, + '& .MuiCardHeader-root .MuiSvgIcon-root': { + color: theme.palette.primary.contrastText + } }, activeStyle: { borderColor: theme.palette.info.main, @@ -222,6 +225,7 @@ const MetadataCard = props => { {'Download '} { {showMetadataSearchButton && ( - + @@ -156,7 +156,7 @@ const CollectionsPage = (props: CollectionsPageProperties) => { ' Your pending changes will be lost.' } agreeButtonText="Navigate" - disagreeButtonText="back to form" + disagreeButtonText="Back to form" onAgree={handleConfirmSwitchCollection} onDisagree={handleCancelSwitchCollection} /> diff --git a/projects/mercury/src/collections/CollectionsPage.styles.js b/projects/mercury/src/collections/CollectionsPage.styles.js index e3c5d50b76..ab26d23170 100644 --- a/projects/mercury/src/collections/CollectionsPage.styles.js +++ b/projects/mercury/src/collections/CollectionsPage.styles.js @@ -6,12 +6,17 @@ const styles = () => ({ width: consts.MAIN_CONTENT_WIDTH }, topBarSwitch: { + paddingLeft: 8, textAlign: 'right', whiteSpace: 'nowrap' }, + metadataButton: { + paddingRight: 8 + }, centralPanel: { width: consts.MAIN_CONTENT_WIDTH, - maxHeight: consts.MAIN_CONTENT_MAX_HEIGHT + maxHeight: consts.MAIN_CONTENT_MAX_HEIGHT, + paddingLeft: 0 }, sidePanel: { width: consts.SIDE_PANEL_WIDTH diff --git a/projects/mercury/src/common/components/ColumnFilterInput.js b/projects/mercury/src/common/components/ColumnFilterInput.js index 9ffd4cbb33..34c63d0707 100644 --- a/projects/mercury/src/common/components/ColumnFilterInput.js +++ b/projects/mercury/src/common/components/ColumnFilterInput.js @@ -11,10 +11,6 @@ const useStyles = makeStyles(theme => ({ position: 'relative', flex: 0.8, borderRadius: theme.shape.borderRadius, - backgroundColor: alpha(theme.palette.common.white, 0.15), - '&:hover': { - backgroundColor: alpha(theme.palette.common.white, 0.25) - }, marginLeft: 0, width: '100%', [theme.breakpoints.up('sm')]: { @@ -22,7 +18,14 @@ const useStyles = makeStyles(theme => ({ } }, inputRoot: { - color: 'inherit', + borderRadius: theme.shape.borderRadius, + borderColor: theme.palette.primary.main, + backgroundColor: alpha(theme.palette.primary.main, 0.15), + color: theme.palette.primary.contrastText, + '&:hover': { + backgroundColor: alpha(theme.palette.primary.main, 0.25), + borderColor: theme.palette.primary.main + }, width: '100%', fontSize: '0.9rem', minWidth: 180, diff --git a/projects/mercury/src/common/components/LoadingOverlayWrapper.js b/projects/mercury/src/common/components/LoadingOverlayWrapper.js index 71e69a7bf0..5871a5b501 100644 --- a/projects/mercury/src/common/components/LoadingOverlayWrapper.js +++ b/projects/mercury/src/common/components/LoadingOverlayWrapper.js @@ -23,12 +23,13 @@ const useStyles = makeStyles(theme => ({ opacity: 0.4 }, backdrop: { - backgroundColor: '#747474', + backgroundColor: theme.palette.mellow.dark, position: 'absolute', top: 0, left: 0, width: '100%', - height: '100%' + height: '100%', + borderRadius: theme.shape.borderRadius } })); diff --git a/projects/mercury/src/common/components/TablePaginationActions.js b/projects/mercury/src/common/components/TablePaginationActions.js index 4abe1ca0bc..176483fc78 100644 --- a/projects/mercury/src/common/components/TablePaginationActions.js +++ b/projects/mercury/src/common/components/TablePaginationActions.js @@ -2,7 +2,7 @@ import React from 'react'; import IconButton from '@mui/material/IconButton'; import {KeyboardArrowLeft, KeyboardArrowRight, LastPage, FirstPage} from '@mui/icons-material'; import makeStyles from '@mui/styles/makeStyles'; -import {Typography} from '@mui/material'; +import {Tooltip, Typography} from '@mui/material'; const useStyles = makeStyles(theme => ({ root: { @@ -15,12 +15,14 @@ export type TablePaginationActionsProperties = { count: number, onPageChange: () => {}, page: number, - rowsPerPage: number + rowsPerPage: number, + countDisplayLimitReached?: boolean, + currentPageCount?: number }; const TablePaginationActions = (props: TablePaginationActionsProperties) => { const classes = useStyles(); - const {count, page, rowsPerPage, onPageChange} = props; + const {count, page, rowsPerPage, onPageChange, countDisplayLimitReached = false, hasNextFlag = false} = props; const handleFirstPageButtonClick = event => { onPageChange(event, 0); @@ -56,20 +58,24 @@ const TablePaginationActions = (props: TablePaginationActionsProperties) => { = Math.ceil(count / rowsPerPage) - 1} + disabled={page >= Math.ceil(count / rowsPerPage) - 1 && !(countDisplayLimitReached && hasNextFlag)} aria-label="next page" size="medium" > - = Math.ceil(count / rowsPerPage) - 1} - aria-label="last page" - size="medium" - > - - + + + = Math.ceil(count / rowsPerPage) - 1} + aria-label="last page" + size="medium" + > + + + + ); }; diff --git a/projects/mercury/src/common/components/__tests__/TablePaginationAcrions.js b/projects/mercury/src/common/components/__tests__/TablePaginationAcrions.js new file mode 100644 index 0000000000..a23a3d1c0d --- /dev/null +++ b/projects/mercury/src/common/components/__tests__/TablePaginationAcrions.js @@ -0,0 +1,82 @@ +import React from 'react'; +import {render, fireEvent} from '@testing-library/react'; +import '@testing-library/jest-dom/extend-expect'; +import {ThemeProvider} from '@mui/material/styles'; +import TablePaginationActions from '../TablePaginationActions'; +import theme from '../../../App.theme'; + +describe('TablePaginationActions', () => { + const defaultProps = { + count: 100, + page: 0, + rowsPerPage: 10, + onPageChange: jest.fn() + }; + + const renderComponent = (props = {}) => { + return render( + + + + ); + }; + + it('renders all arrow buttons', () => { + const {getByLabelText} = renderComponent(); + expect(getByLabelText('first page')).toBeInTheDocument(); + expect(getByLabelText('previous page')).toBeInTheDocument(); + expect(getByLabelText('next page')).toBeInTheDocument(); + expect(getByLabelText('last page')).toBeInTheDocument(); + }); + + it('disables next and last buttons on last page', () => { + const props = {...defaultProps, page: 9}; + const {getByLabelText} = renderComponent(props); + expect(getByLabelText('next page')).toBeDisabled(); + expect(getByLabelText('last page')).toBeDisabled(); + }); + + it('calls onPageChange with correct arguments when first page button is clicked', () => { + const props = {...defaultProps, page: 1}; + const {getByLabelText} = renderComponent(props); + fireEvent.click(getByLabelText('first page')); + expect(defaultProps.onPageChange).toHaveBeenCalledWith(expect.anything(), 0); + }); + it('calls onPageChange with correct arguments when previous page button is clicked', () => { + const props = {...defaultProps, page: 1}; + const {getByLabelText} = renderComponent(props); + fireEvent.click(getByLabelText('previous page')); + expect(props.onPageChange).toHaveBeenCalledWith(expect.anything(), 0); + }); + + it('calls onPageChange with correct arguments when next page button is clicked', () => { + const {getByLabelText} = renderComponent(); + fireEvent.click(getByLabelText('next page')); + expect(defaultProps.onPageChange).toHaveBeenCalledWith(expect.anything(), 1); + }); + + it('calls onPageChange with correct arguments when last page button is clicked', () => { + const {getByLabelText} = renderComponent(); + fireEvent.click(getByLabelText('last page')); + expect(defaultProps.onPageChange).toHaveBeenCalledWith(expect.anything(), 9); + }); + + it('disables last page button when countDisplayLimitReached is true', () => { + const props = {...defaultProps, countDisplayLimitReached: true}; + const {getByLabelText} = renderComponent(props); + expect(getByLabelText('last page')).toBeDisabled(); + }); + + it('shows tooltip when countDisplayLimitReached is true', () => { + const props = {countDisplayLimitReached: true}; + const {getByLabelText} = renderComponent(props); + fireEvent.mouseOver(getByLabelText('last page')); + expect(getByLabelText('Total page count not available')).toBeInTheDocument(); + }); + + it('enables next page button when countDisplayLimitReached is true and hasNextFlag is true', () => { + const props = {...defaultProps, countDisplayLimitReached: true, hasNextFlag: true}; + const {getByLabelText} = renderComponent(props); + expect(getByLabelText('next page')).not.toBeDisabled(); + }); +}); diff --git a/projects/mercury/src/constants.js b/projects/mercury/src/constants.js index 0b6b12a352..b0cbada34d 100644 --- a/projects/mercury/src/constants.js +++ b/projects/mercury/src/constants.js @@ -1,5 +1,7 @@ export const APPLICATION_NAME = 'Fairspace'; export const DEFAULT_METADATA_VIEW_MENU_LABEL = 'Metadata'; +export const THE_HYVE_URL = 'https://thehyve.nl'; +export const APPLICATION_DOCS_URL = 'https://docs.fairway.app/'; export const LOCAL_STORAGE_MENU_KEY = 'FAIRSPACE_MENU_EXPANDED'; export const CUT = 'CUT'; export const COPY = 'COPY'; @@ -10,6 +12,7 @@ export const LEFT_MENU_EXPANSION_DELAY = 500; export const MAIN_CONTENT_WIDTH = '65%'; export const SIDE_PANEL_WIDTH = '35%'; export const MAIN_CONTENT_MAX_HEIGHT = 'calc(100vh - 156px)'; +export const LEFT_PANEL_MAX_WIDTH = 305; export const COLLECTIONS_PATH = 'collections'; export const METADATA_PATH = '/metadata'; export const CROSS_WORKSPACES_SEARCH_PATH = '/workspaces/_all'; diff --git a/projects/mercury/src/dashboard/DashboardPage.js b/projects/mercury/src/dashboard/DashboardPage.js index 1067022759..6dd10a0279 100644 --- a/projects/mercury/src/dashboard/DashboardPage.js +++ b/projects/mercury/src/dashboard/DashboardPage.js @@ -1,14 +1,13 @@ import React, {useContext} from 'react'; import withStyles from '@mui/styles/withStyles'; -import {Grid, Link, Paper, Typography} from '@mui/material'; -import BreadCrumbs from '../common/components/BreadCrumbs'; +import {Grid, Link, Paper, Typography, TextField} from '@mui/material'; import styles from './DashboardPage.styles'; import MetadataViewContext from '../metadata/views/MetadataViewContext'; import ExternalMetadataSourceContext from '../metadata/metadata-sources/ExternalMetadataSourceContext'; import UserContext from '../users/UserContext'; import DomainInfo from './DomainInfo'; -import {APPLICATION_NAME} from '../constants'; +import {APPLICATION_DOCS_URL, APPLICATION_NAME, THE_HYVE_URL} from '../constants'; import InternalMetadataSourceContext from '../metadata/metadata-sources/InternalMetadataSourceContext'; const DashboardPage = props => { @@ -17,58 +16,109 @@ const DashboardPage = props => { const {externalMetadataSources} = useContext(ExternalMetadataSourceContext); const {internalMetadataIcon, internalMetadataLabel} = useContext(InternalMetadataSourceContext); const canViewMetadata = currentUser && currentUser.canViewPublicMetadata && views && views.length > 0; + const askAIConfigured = false; return ( - - - - - - - {APPLICATION_NAME} + + + + + + Research Data Management - - - - research data management + + {APPLICATION_NAME} contains your research metadata. Click on one of the domains in `Search + the metadata` card and start exploring. + + + For more details on how to use Fairspace, e.g. how to query the API, please refer the{' '} + + user manual + + . + + + + + {canViewMetadata && ( + + + Search the metadata + + + + + + {externalMetadataSources.map(source => ( + + + + ))} + + + )} - - - - {APPLICATION_NAME} contains your research metadata. Click on one of the domains and - start exploring. + + + + About - - - - - For more details on how to use Fairspace, e.g. how to query the API, please refer the{' '} - user manual. + + {APPLICATION_NAME} version: {process.env.REACT_APP_VERSION} - - - - {canViewMetadata && ( - - )} - {canViewMetadata && - externalMetadataSources.map(source => ( - - ))} + + {/* eslint-disable-next-line prettier/prettier */} + {'Created by '} + + The Hyve + + + - + + + {askAIConfigured && ( + + + Ask AI + + + What do you want to know more about? + +
+ +
+
+ )} +
); }; diff --git a/projects/mercury/src/dashboard/DashboardPage.styles.js b/projects/mercury/src/dashboard/DashboardPage.styles.js index 600e008914..d5cfc89be3 100644 --- a/projects/mercury/src/dashboard/DashboardPage.styles.js +++ b/projects/mercury/src/dashboard/DashboardPage.styles.js @@ -1,22 +1,58 @@ -import * as consts from '../constants'; +import {alpha} from '@mui/material/styles'; const styles = theme => ({ mainPage: { - width: consts.MAIN_CONTENT_WIDTH, - maxWidth: '700px', - maxHeight: consts.MAIN_CONTENT_MAX_HEIGHT, - padding: 20, - marginTop: 20 + marginTop: 10, + width: '80%' + }, + paperContent: { + borderRadius: theme.shape.borderRadius, + borderColor: theme.palette.primary.main, + padding: '10px 20px 10px 20px', + height: '100%' + }, + domains: { + overflowX: 'auto', + minWidth: 190 + }, + link: { + color: theme.palette.primary.light, + textDecoration: 'underline' }, header: { - borderBottom: '2px solid ' + theme.palette.primary.main, - marginBottom: 50 + margin: 10 }, - textRow: { - minHeight: '250px' + mainHeader: { + paddingBottom: 40, + paddingTop: 20 + }, + footer: { + marginBottom: 0, + paddingTop: 10 + }, + paragraph: { + border: 2, + borderRadius: theme.shape.borderRadius, + borderColor: theme.palette.primary.main, + backgroundColor: theme.palette.primary.dark, + color: theme.palette.primary.contrastText, + padding: 10 + }, + textFieldWrapper: { + padding: 20, + alignItems: 'center' }, - customFont: { - fontFamily: 'sans-serif' + textField: { + border: 2, + borderRadius: theme.shape.borderRadius, + borderColor: theme.palette.primary.main, + backgroundColor: alpha(theme.palette.primary.main, 0.15), + '&:hover': { + backgroundColor: alpha(theme.palette.primary.main, 0.25), + borderColor: theme.palette.primary.dark + }, + color: theme.palette.primary.contrastText, + width: '100%' } }); diff --git a/projects/mercury/src/dashboard/DomainInfo.js b/projects/mercury/src/dashboard/DomainInfo.js index 88bc8e6688..bb63892707 100644 --- a/projects/mercury/src/dashboard/DomainInfo.js +++ b/projects/mercury/src/dashboard/DomainInfo.js @@ -7,14 +7,14 @@ import styles from './DomainInfo.styles'; const DomainInfo = props => { const {domainName, domainLink, domainIcon, classes} = props; return ( -
+
- + {domainName} {domainIcon ? ( - + {domainName} ) : ( diff --git a/projects/mercury/src/dashboard/DomainInfo.styles.js b/projects/mercury/src/dashboard/DomainInfo.styles.js index 7865f08138..dcf44d27ae 100644 --- a/projects/mercury/src/dashboard/DomainInfo.styles.js +++ b/projects/mercury/src/dashboard/DomainInfo.styles.js @@ -1,18 +1,22 @@ const styles = theme => ({ + outerDiv: { + padding: 10 + }, paper: { - width: '200px', - height: '100px', - borderStyle: 'solid', - borderColor: theme.palette.primary.light, - borderWidth: 2, + marginRight: 1, + height: 100, + minWidth: 90, + border: 'none', + background: theme.palette.primary.main, + '&:hover': { + backgroundColor: theme.palette.primary.light + }, textAlign: 'center' }, - outerMargin: { - margin: 10 - }, icon: { marginLeft: 10, - marginTop: 10 + marginTop: 10, + color: theme.palette.primary.contrastText }, imageIconRoot: { marginTop: 10, @@ -25,10 +29,12 @@ const styles = theme => ({ width: 'inherit' }, domainText: { - color: theme.palette.grey[700] + color: theme.palette.primary.contrastText, + paddingTop: 10 }, link: { - textDecoration: 'none' + textDecoration: 'none', + alignItems: 'center' } }); diff --git a/projects/mercury/src/external-storage/ExternalStorageInformationDrawer.js b/projects/mercury/src/external-storage/ExternalStorageInformationDrawer.js index 9c50971984..a916b71c51 100644 --- a/projects/mercury/src/external-storage/ExternalStorageInformationDrawer.js +++ b/projects/mercury/src/external-storage/ExternalStorageInformationDrawer.js @@ -27,7 +27,7 @@ import LinkedDataLink from '../metadata/common/LinkedDataLink'; import type {DisplayProperty} from './UseExternalStorageMetadata'; import useExternalStorageMetadata from './UseExternalStorageMetadata'; -const useStyles = makeStyles(() => ({ +const useStyles = makeStyles(theme => ({ expandOpen: { transform: 'rotate(180deg)' }, @@ -36,9 +36,21 @@ const useStyles = makeStyles(() => ({ flex: 1, display: 'flex', flexDirection: 'column', + maxHeight: '100%', + overflowY: 'auto', outline: 'none', transitionBorder: '.24s', - easeInOut: true + easeInOut: true, + '& .MuiCardHeader-root .MuiSvgIcon-root': { + color: theme.palette.primary.contrastText + }, + cardHeader: { + wordBreak: 'break-word', + top: 0, + zIndex: 2, + position: 'sticky', + backgroundColor: theme.palette.primary.main + } } })); @@ -128,7 +140,7 @@ const ExternalMetadataCard = (props: ExternalMetadataCardProperties) => { titleTypographyProps={{variant: 'h6'}} title={title} avatar={avatar} - style={{wordBreak: 'break-word'}} + className={classes.cardHeader} action={ ({ '& .MuiListItem-root': { paddingTop: 4, paddingBottom: 4 + }, + '& .MuiDivider-root': { + marginTop: 2, + marginBottom: 0 } }, uploadMenuHelper: { borderLeft: '8px solid #999', - padding: 20 + padding: '5px 10px 5px 10px' }, uploadMenuHelperText: { margin: 0, diff --git a/projects/mercury/src/file/FileVersionsList.js b/projects/mercury/src/file/FileVersionsList.js index d48ca2cd51..259bdfcc96 100644 --- a/projects/mercury/src/file/FileVersionsList.js +++ b/projects/mercury/src/file/FileVersionsList.js @@ -176,12 +176,7 @@ const FileVersionsList = ({selectedFile, onRevertVersion, isWritingEnabled, clas ); const renderHeader = ({label}) => ( - + {label} ); diff --git a/projects/mercury/src/file/FilesPage.js b/projects/mercury/src/file/FilesPage.js index e38035e248..af84427ee1 100644 --- a/projects/mercury/src/file/FilesPage.js +++ b/projects/mercury/src/file/FilesPage.js @@ -150,7 +150,7 @@ export const FilesPage = (props: FilesPageProperties) => { {showMetadataSearchButton && ( - + {externalStorages && externalStorages.map(storage => ( - } > - - - - - + {open && storage.label} + ))} {views && views.length > 0 && currentUser.canViewPublicMetadata && ( - - - {internalMetadataIcon ? ( + startIcon={ + internalMetadataIcon ? ( - Metadata + Metadata ) : ( - )} - - - + ) + } + > + {open && internalMetadataLabel} + )} {currentUser.canViewPublicMetadata && externalMetadataSources && externalMetadataSources.map(source => ( - - - {source.icon ? ( + startIcon={ + source.icon ? ( {source.name} { ) : ( - )} - - - + ) + } + > + {open && source.label} + ))} {isAdmin(currentUser) && ( - } > - - - - - + {open && 'Users'} + )} - - -
- - - {services.map(service => ( - - - {service.icon ? ( - - {service.name} - - ) : ( - - )} - - - - ))} - -
+ + + {services.map(service => ( + + ))} + ); }; diff --git a/projects/mercury/src/layout/MenuDrawer.js b/projects/mercury/src/layout/MenuDrawer.js index 0dc5b4897c..c1635e3565 100644 --- a/projects/mercury/src/layout/MenuDrawer.js +++ b/projects/mercury/src/layout/MenuDrawer.js @@ -1,12 +1,13 @@ import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; -import {Divider, Drawer, IconButton} from '@mui/material'; +import {Drawer, IconButton} from '@mui/material'; import withStyles from '@mui/styles/withStyles'; import ChevronLeftIcon from '@mui/icons-material/ChevronLeft'; import ChevronRightIcon from '@mui/icons-material/ChevronRight'; import styles from './MenuDrawer.styles'; +import UserMenu from './UserMenu'; const MenuDrawer = ({open, renderMenu, toggleMenuExpansion, onMouseEnter, onMouseLeave, classes}) => ( -
- +
+ {open ? ( + Fairspace + ) : ( + Fairspace + )} +
+
+ {renderMenu(open)} +
+
+ + {open ? : }
- -
- {renderMenu()} -
); diff --git a/projects/mercury/src/layout/MenuDrawer.styles.js b/projects/mercury/src/layout/MenuDrawer.styles.js index fafd21fbd5..b8b56f5c46 100644 --- a/projects/mercury/src/layout/MenuDrawer.styles.js +++ b/projects/mercury/src/layout/MenuDrawer.styles.js @@ -1,14 +1,20 @@ +import {scrollbarStyles} from '../App.theme'; +import {LEFT_PANEL_MAX_WIDTH} from '../constants'; + const styles = theme => ({ drawerPaper: { position: 'fixed', whiteSpace: 'nowrap', - width: 240, - marginTop: '65px', + width: LEFT_PANEL_MAX_WIDTH, + marginTop: '0', + border: 'none', overflow: 'hidden', transition: theme.transitions.create('width', { easing: theme.transitions.easing.sharp, duration: theme.transitions.duration.enteringScreen - }) + }), + background: `radial-gradient(at right center, ${theme.palette.primary.main} 20%, ${theme.palette.primary.dark} 75%)`, + height: '100vh' }, drawerPaperOpen: { transition: theme.transitions.create('width', { @@ -24,17 +30,43 @@ const styles = theme => ({ width: 62 }, toolbar: { - backgroundColor: '#f0f0f0', display: 'flex', - alignItems: 'center', justifyContent: 'flex-end', + alignItems: 'center', padding: '0 8px', + marginTop: 'auto', + marginBottom: 0, ...theme.mixins.toolbar }, + toolbarCollapsed: { + display: 'flex', + flexDirection: 'column', + height: 80, + alignItems: 'center', + padding: '0 8px', + marginTop: 'auto', + marginBottom: 0, + ...theme.mixins.toolbar + }, + toolbarIcon: { + color: 'white', + marginLeft: 'auto' + }, + mainLogo: { + flexGrow: 1, + textAlign: 'center', + maxHeight: 140, + marginTop: 60, + marginBottom: 30 + }, customerLogo: { position: 'absolute', bottom: 50, height: 100 + }, + menu: { + overflowY: 'auto', + ...scrollbarStyles } }); diff --git a/projects/mercury/src/layout/TopBar.js b/projects/mercury/src/layout/TopBar.js index ff057142fc..1f2b5f38d7 100644 --- a/projects/mercury/src/layout/TopBar.js +++ b/projects/mercury/src/layout/TopBar.js @@ -4,8 +4,6 @@ import {AppBar, Toolbar} from '@mui/material'; import withStyles from '@mui/styles/withStyles'; -import UserMenu from './UserMenu'; - const styles = theme => ({ root: { zIndex: theme.zIndex.drawer + 1 @@ -21,10 +19,9 @@ const TopBar = ({classes, children}) => (
- Fairspace + Fairspace
{children} -
); diff --git a/projects/mercury/src/layout/UserMenu.js b/projects/mercury/src/layout/UserMenu.js index 071aa7d9d4..5b1fea9cd3 100644 --- a/projects/mercury/src/layout/UserMenu.js +++ b/projects/mercury/src/layout/UserMenu.js @@ -7,6 +7,7 @@ import { CardContent, ClickAwayListener, Grow, + IconButton, MenuItem, MenuList, Paper, @@ -16,16 +17,22 @@ import { import withStyles from '@mui/styles/withStyles'; import {ErrorOutline} from '@mui/icons-material'; +import ExitToApp from '@mui/icons-material/ExitToApp'; import UserContext from '../users/UserContext'; import LogoutContext from '../users/LogoutContext'; import {getDisplayName} from '../users/userUtils'; import versionInfo from '../common/VersionInfo'; import {APPLICATION_NAME} from '../constants'; +import {COLORS} from '../App.theme'; -const styles = { +const styles = theme => ({ row: { display: 'flex', - justifyContent: 'center', + justifyContent: 'flex-start' + }, + button: { + display: 'flex', + justifyContent: 'flex-start', paddingTop: 0, paddingBottom: 0 }, @@ -34,22 +41,29 @@ const styles = { width: 28, height: 28 }, + username: { + color: theme.palette.primary.contrastText, + fontSize: 12 + }, logout: { width: 50 }, + logoutIcon: { + color: theme.palette.primary.contrastText + }, menu: { paddingTop: 0 }, userMenu: { - backgroundColor: 'lightgrey', + backgroundColor: COLORS.fsBlueLightTransp25, cursor: 'default' }, customFont: { fontFamily: 'sans-serif' } -}; +}); -const UserMenu = ({classes}) => { +const UserMenu = ({menuOpen, classes}) => { const [anchorEl, setAnchorEl] = useState(null); const {currentUser, currentUserLoading, currentUserError} = useContext(UserContext); const logout = useContext(LogoutContext); @@ -72,20 +86,30 @@ const UserMenu = ({classes}) => { } if (currentUserError || !currentUser) { - return ; + return ; + } + + if (!menuOpen) { + return ( + + + + ); } return ( - <> +
{({TransitionProps, placement}) => ( @@ -100,7 +124,7 @@ const UserMenu = ({classes}) => { - + Welcome @@ -130,7 +154,7 @@ const UserMenu = ({classes}) => { )} - +
); }; diff --git a/projects/mercury/src/layout/WorkspaceLayout.js b/projects/mercury/src/layout/WorkspaceLayout.js index 52e8c1379b..c020edf61e 100644 --- a/projects/mercury/src/layout/WorkspaceLayout.js +++ b/projects/mercury/src/layout/WorkspaceLayout.js @@ -39,7 +39,7 @@ const WorkspaceLayoutInner = () => { } + renderMenu={open => } renderMain={() => } renderTopbar={() => } /> diff --git a/projects/mercury/src/layout/__tests__/MainMenu.js b/projects/mercury/src/layout/__tests__/MainMenu.js index a5e12f95ff..0ce585ab55 100644 --- a/projects/mercury/src/layout/__tests__/MainMenu.js +++ b/projects/mercury/src/layout/__tests__/MainMenu.js @@ -1,6 +1,7 @@ import React from 'react'; import {render} from '@testing-library/react'; import {BrowserRouter as Router} from 'react-router-dom'; +import {ThemeProvider} from '@mui/material/styles'; import ServicesContext from '../../common/contexts/ServicesContext'; import UserContext from '../../users/UserContext'; import ExternalStoragesContext from '../../external-storage/ExternalStoragesContext'; @@ -9,31 +10,34 @@ import InternalMetadataSourceContext from '../../metadata/metadata-sources/Inter import MetadataViewContext from '../../metadata/views/MetadataViewContext'; import MainMenu from '../MainMenu'; import {DEFAULT_METADATA_VIEW_MENU_LABEL} from '../../constants'; +import theme from '../../App.theme'; describe('MainMenu', () => { const setup = (user, services, externalStorages, externalMetadataSources, internalMetadata, views) => { return render( - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + ); }; diff --git a/projects/mercury/src/metadata/common/LinkedDataEntityFormContainer.js b/projects/mercury/src/metadata/common/LinkedDataEntityFormContainer.js index bbc84ecda3..c03d03aa76 100644 --- a/projects/mercury/src/metadata/common/LinkedDataEntityFormContainer.js +++ b/projects/mercury/src/metadata/common/LinkedDataEntityFormContainer.js @@ -102,6 +102,7 @@ const LinkedDataEntityFormContainer = ({ clearForm(); setEditingEnabled(!showEditButtons); }} + style={{marginLeft: 8}} > Cancel @@ -111,7 +112,7 @@ const LinkedDataEntityFormContainer = ({ return ( - + executeNavigation()} onDisagree={hideConfirmation} /> diff --git a/projects/mercury/src/metadata/common/LinkedDataLink.js b/projects/mercury/src/metadata/common/LinkedDataLink.js index 45d3c8582b..cc5a272dca 100644 --- a/projects/mercury/src/metadata/common/LinkedDataLink.js +++ b/projects/mercury/src/metadata/common/LinkedDataLink.js @@ -1,6 +1,6 @@ import React, {useContext} from 'react'; import * as PropTypes from 'prop-types'; -import {Box, Modal, Tooltip} from '@mui/material'; +import {Card, Modal, Tooltip} from '@mui/material'; import withStyles from '@mui/styles/withStyles'; import CloseIcon from '@mui/icons-material/Close'; import LinkedDataEntityPage from './LinkedDataEntityPage'; @@ -17,13 +17,13 @@ const renderModal = (classes, open, handleClose, uri) => ( aria-labelledby="modal-modal-title" aria-describedby="modal-modal-description" > -
- +
+ - +
); diff --git a/projects/mercury/src/metadata/common/LinkedDataLink.styles.js b/projects/mercury/src/metadata/common/LinkedDataLink.styles.js index 2a9ad45ef9..5e05a20c1e 100644 --- a/projects/mercury/src/metadata/common/LinkedDataLink.styles.js +++ b/projects/mercury/src/metadata/common/LinkedDataLink.styles.js @@ -1,25 +1,29 @@ const styles = theme => ({ - modalDialog: { - background: theme.palette.grey['200'], + modalWrapper: { position: 'relative', - top: 0, - width: 800, + '& .MuiBreadcrumbs-root .MuiTypography-root': { + color: theme.palette.primary.contrastText + }, + top: '10%', + left: '50%', + transform: 'translate(-50%, 0px)', + outline: 'none', + maxHeight: '80vh', + display: 'flex', + flexDirection: 'column', + width: 800 + }, + modalContent: { + background: theme.palette.primary.dark, + color: theme.palette.primary.contrastText, bgcolor: 'background.paper', border: '0px solid #000', + borderRadius: theme.shape.borderRadius, boxShadow: 0, outline: 'none', - p: 4 - }, - modalContent: { - position: 'relative', - top: '10%', - left: '50%', - transform: 'translate(-50%, 0px)', - maxHeight: '80%', - padding: 2, - backgroundColor: theme.palette.primary.main, - width: 800, - overflowY: 'auto' + overflowY: 'auto', + height: '100%', + width: '100%' }, closeButton: { float: 'right', diff --git a/projects/mercury/src/metadata/common/LinkedDataValuesList.js b/projects/mercury/src/metadata/common/LinkedDataValuesList.js index 4978e7669b..fc6ea1f857 100644 --- a/projects/mercury/src/metadata/common/LinkedDataValuesList.js +++ b/projects/mercury/src/metadata/common/LinkedDataValuesList.js @@ -5,7 +5,7 @@ import {Add, Clear} from '@mui/icons-material'; import {FixedSizeList as List} from 'react-window'; import {LABEL_URI, MAX_LIST_LENGTH, STRING_URI} from '../../constants'; -import styles from './LinkedDataValuesTable.styles'; +import styles from './LinkedDataValuesList.styles'; import StringValue from './values/StringValue'; type AddValueToListProps = { @@ -24,7 +24,7 @@ const AddValueToList = (props: AddValueToListProps) => { const isStringValue = AddComponent === StringValue; return ( - + ({ + values: { + cursor: 'default', + marginTop: 3, + fontSize: '0.875rem', + lineHeight: 1.43, + letterSpacing: '0.01071em', + '& .MuiInputBase-root': { + backgroundColor: alpha(theme.palette.primary.main, 0.15), + '&:hover': { + backgroundColor: alpha(theme.palette.primary.main, 0.25), + borderColor: theme.palette.primary.main + } + }, + '& input': { + fontSize: '0.875rem', + lineHeight: 1.43, + letterSpacing: '0.01071em', + overflow: 'hidden' + }, + '& .MuiOutlinedInput-input': { + borderRadius: theme.shape.borderRadius + }, + '& textarea': { + fontSize: '0.875rem', + lineHeight: 1.43, + letterSpacing: '0.01071em', + borderRadius: theme.shape.borderRadius + } + }, + addValue: { + marginTop: 10, + padding: 3, + borderColor: theme.palette.primary.main, + borderStyle: 'solid', + borderWidth: 1.5, + borderRadius: theme.shape.borderRadius, + backgroundColor: theme.palette.background.default, + '& .MuiGrid-item': { + paddingTop: 4, + paddingBottom: 4 + } + }, + addValueInput: { + borderRadius: theme.shape.borderRadius + } +}); + +export default styles; diff --git a/projects/mercury/src/metadata/common/LinkedDataValuesTable.styles.js b/projects/mercury/src/metadata/common/LinkedDataValuesTable.styles.js deleted file mode 100644 index 6819c27049..0000000000 --- a/projects/mercury/src/metadata/common/LinkedDataValuesTable.styles.js +++ /dev/null @@ -1,33 +0,0 @@ -const styles = theme => ({ - values: { - cursor: 'default', - marginTop: 3, - fontSize: '0.875rem', - lineHeight: 1.43, - letterSpacing: '0.01071em', - '& input': { - fontSize: '0.875rem', - lineHeight: 1.43, - letterSpacing: '0.01071em' - }, - '& textarea': { - fontSize: '0.875rem', - lineHeight: 1.43, - letterSpacing: '0.01071em' - } - }, - addValue: { - marginTop: 10, - padding: 3, - borderColor: theme.palette.grey['400'], - borderStyle: 'solid', - borderWidth: 1.5, - borderRadius: 6, - backgroundColor: theme.palette.grey['50'] - }, - addValueInput: { - backgroundColor: theme.palette.background.paper - } -}); - -export default styles; diff --git a/projects/mercury/src/metadata/common/NewLinkedDataEntityDialog.js b/projects/mercury/src/metadata/common/NewLinkedDataEntityDialog.js index 6199d9840e..6c870122c6 100644 --- a/projects/mercury/src/metadata/common/NewLinkedDataEntityDialog.js +++ b/projects/mercury/src/metadata/common/NewLinkedDataEntityDialog.js @@ -161,7 +161,7 @@ const NewLinkedDataEntityDialog = ({shape, requireIdentifier = true, onClose, on title="Close form" content="You have unsaved changes, are you sure you want to close the form?" agreeButtonText="Close form" - disagreeButtonText="back to form" + disagreeButtonText="Back to form" onAgree={() => onClose()} onDisagree={hideConfirmation} /> diff --git a/projects/mercury/src/metadata/common/__tests__/LinkedDataRelationTable.js b/projects/mercury/src/metadata/common/__tests__/LinkedDataRelationTable.js index 2503f99144..26607ac394 100644 --- a/projects/mercury/src/metadata/common/__tests__/LinkedDataRelationTable.js +++ b/projects/mercury/src/metadata/common/__tests__/LinkedDataRelationTable.js @@ -3,7 +3,7 @@ import {configure, shallow} from 'enzyme'; import Adapter from '@wojtekmaj/enzyme-adapter-react-17'; import {STRING_URI} from '../../../constants'; -import LinkedDataValuesTable from '../LinkedDataValuesList'; +import LinkedDataValuesList from '../LinkedDataValuesList'; import {LinkedDataRelationTable} from '../LinkedDataRelationTable'; // Enzyme is obsolete, the Adapter allows running our old tests. @@ -28,7 +28,7 @@ describe('LinkedDataRelationTable elements', () => { const wrapper = shallow( ); - const table = wrapper.find(LinkedDataValuesTable); + const table = wrapper.find(LinkedDataValuesList); expect(table.length).toEqual(1); diff --git a/projects/mercury/src/metadata/common/values/MarkdownValue.js b/projects/mercury/src/metadata/common/values/MarkdownValue.js index a419e3e9eb..9fd7aa6efa 100644 --- a/projects/mercury/src/metadata/common/values/MarkdownValue.js +++ b/projects/mercury/src/metadata/common/values/MarkdownValue.js @@ -6,15 +6,19 @@ import BaseInputValue from './BaseInputValue'; const MarkdownValue = props => { // Show the editor if the user chose to edit // or if there is no value yet - const [showEdit, setShowEdit] = useState(!props.entry.value); + const [showEdit, setShowEdit] = useState(true); return (
setShowEdit(true)}> - {showEdit || !props.entry.value || !props.entry.value.trim() ? ( + {showEdit ? ( setShowEdit(false)} + onBlur={() => { + if (props.entry.value.trim() !== '') { + setShowEdit(false); + } + }} type="text" /> ) : ( diff --git a/projects/mercury/src/metadata/views/MetadataView.js b/projects/mercury/src/metadata/views/MetadataView.js index a6da81abf1..5bf9085259 100644 --- a/projects/mercury/src/metadata/views/MetadataView.js +++ b/projects/mercury/src/metadata/views/MetadataView.js @@ -52,15 +52,18 @@ type MetadataViewProperties = ContextualMetadataViewProperties & { export const MetadataView = (props: MetadataViewProperties) => { const { - views, - facets, - filters, + views = [], + facets = [], + filters = [], currentViewName, metadataLabel, locationContext, classes, handleViewChangeRedirect, - pathPrefix + pathPrefix = '/metadata-views', + updateFilters, + clearFilter, + clearAllFilters } = props; usePageTitleUpdater(metadataLabel); @@ -68,7 +71,6 @@ export const MetadataView = (props: MetadataViewProperties) => { const {collections} = useContext(CollectionsContext); const {toggle, selected} = useSingleSelection(); - const {updateFilters, clearFilter, clearAllFilters} = useContext(MetadataViewContext); const [filterCandidates, setFilterCandidates] = useState([]); const [textFiltersObject, setTextFiltersObject] = useState({}); const [isClosedPanel, setIsClosedPanel] = useState(true); @@ -81,7 +83,7 @@ export const MetadataView = (props: MetadataViewProperties) => { const currentViewIndex = Math.max(0, views.map(v => v.name).indexOf(currentViewName)); const currentView = views[currentViewIndex]; - const currentViewIdColumn = currentView.columns.find(c => c.type === 'Identifier' && c.name === currentView.name); + const currentViewIdColumn = currentView?.columns.find(c => c.type === 'Identifier' && c.name === currentView.name); const changeTab = useCallback( (event, tabIndex) => { @@ -209,12 +211,11 @@ export const MetadataView = (props: MetadataViewProperties) => { if (!selected) { return ''; } - const metadataURL = window.location.host + getMetadataViewsPath(currentView.name, pathPrefix); const prefilteringQueryString = queryString.stringify({ view: currentView.name, [currentViewIdColumn.name.toLowerCase()]: selected.label }); - return metadataURL + '?' + prefilteringQueryString; + return `${window.location.host}${pathPrefix}?${prefilteringQueryString}`; }; return ( @@ -259,7 +260,7 @@ export const MetadataView = (props: MetadataViewProperties) => { )} )} - + @@ -306,7 +307,15 @@ export const MetadataView = (props: MetadataViewProperties) => { }; export const ContextualMetadataView = (props: ContextualMetadataViewProperties) => { - const {views = [], filters, loading, error} = useContext(MetadataViewContext); + const { + views = [], + filters, + loading, + error, + updateFilters, + clearFilter, + clearAllFilters + } = useContext(MetadataViewContext); const {facets = [], facetsLoading, facetsError, initialLoad} = useContext(MetadataViewFacetsContext); const {internalMetadataLabel} = useContext(InternalMetadataSourceContext); const currentViewName = getMetadataViewNameFromString(window.location.search); @@ -348,6 +357,9 @@ export const ContextualMetadataView = (props: ContextualMetadataViewProperties) locationContext={currentViewName === RESOURCES_VIEW && locationContext} currentViewName={currentViewName} handleViewChangeRedirect={handleViewChangeRedirect} + updateFilters={updateFilters} + clearFilter={clearFilter} + clearAllFilters={clearAllFilters} /> ); }; diff --git a/projects/mercury/src/metadata/views/MetadataView.styles.js b/projects/mercury/src/metadata/views/MetadataView.styles.js index d8ac4b1120..52f96d12aa 100644 --- a/projects/mercury/src/metadata/views/MetadataView.styles.js +++ b/projects/mercury/src/metadata/views/MetadataView.styles.js @@ -5,7 +5,10 @@ const styles = theme => ({ leftPanel: { marginTop: 8, paddingBottom: 10, - minWidth: 282 + minWidth: 275 + }, + overallPanelContainer: { + height: 'calc(100vh - 64px)' }, overallPanel: { width: CENTRAL_PANEL_WIDTH, @@ -15,19 +18,20 @@ const styles = theme => ({ width: '100%' }, rightPanel: { - width: RIGHT_PANEL_WIDTH + width: RIGHT_PANEL_WIDTH, + height: '100%' }, centralPanel: { overflowX: 'auto', width: '100%', - overflowY: 'hidden', - maxHeight: 'calc(100vh - 150px)' + overflowY: 'hidden' }, clearAllButtonContainer: { textAlign: 'end' }, clearAllButton: { - color: theme.palette.error.main + color: theme.palette.primary.contrastText, + background: theme.palette.primary.main }, activeFilters: { marginBottom: 10 diff --git a/projects/mercury/src/metadata/views/MetadataViewAPI.js b/projects/mercury/src/metadata/views/MetadataViewAPI.js index 778ec01420..351124cc2f 100644 --- a/projects/mercury/src/metadata/views/MetadataViewAPI.js +++ b/projects/mercury/src/metadata/views/MetadataViewAPI.js @@ -43,7 +43,8 @@ export type MetadataViewColumn = { export type MetadataViewOptions = { name: string, title: string, - columns: MetadataViewColumn[] + columns: MetadataViewColumn[], + maxDisplayCount: number }; export type MetadataViews = { diff --git a/projects/mercury/src/metadata/views/MetadataViewFacetFactory.js b/projects/mercury/src/metadata/views/MetadataViewFacetFactory.js index 20c1bb60ac..a68ed0b7d7 100644 --- a/projects/mercury/src/metadata/views/MetadataViewFacetFactory.js +++ b/projects/mercury/src/metadata/views/MetadataViewFacetFactory.js @@ -71,7 +71,7 @@ const Facet = (props: MetadataViewFacetProperties) => { const clearFiltersAction = activeFilterValues.length > 0 && ( - + ); diff --git a/projects/mercury/src/metadata/views/MetadataViewFacetFactory.styles.js b/projects/mercury/src/metadata/views/MetadataViewFacetFactory.styles.js index 3ef7905c70..94ce53dd68 100644 --- a/projects/mercury/src/metadata/views/MetadataViewFacetFactory.styles.js +++ b/projects/mercury/src/metadata/views/MetadataViewFacetFactory.styles.js @@ -7,14 +7,18 @@ const styles = theme => ({ title: { padding: 8, fontWidth: 'bold', + backgroundColor: theme.palette.primary.dark, '& .MuiCardHeader-action': { alignSelf: 'auto', margin: 0 + }, + '& .MuiIconButton-root': { + color: theme.palette.primary.contrastText } }, content: { '&:last-child': { - paddingTop: 0, + paddingTop: 8, paddingBottom: 8 }, padding: 8 diff --git a/projects/mercury/src/metadata/views/MetadataViewFacets.js b/projects/mercury/src/metadata/views/MetadataViewFacets.js index fa316d4e3d..d31d08eec2 100644 --- a/projects/mercury/src/metadata/views/MetadataViewFacets.js +++ b/projects/mercury/src/metadata/views/MetadataViewFacets.js @@ -25,10 +25,11 @@ const styles = theme => ({ width: 265 }, confirmFiltersButton: { - width: '100%' + width: '100%', + background: theme.palette.primary.main }, facetsContainer: { - maxHeight: 'calc(100vh - 212px)', + maxHeight: 'calc(100vh - 100px)', overflowY: 'auto', paddingTop: 8 }, @@ -41,13 +42,13 @@ const styles = theme => ({ marginBottom: 1, marginTop: 0, fontSize: 13, - color: theme.palette.primary.light, + color: theme.palette.primary.main, textTransform: 'uppercase' }, facet: { borderColor: theme.palette.primary.light, borderWidth: 1.8, - borderRadius: 6, + borderRadius: theme.shape.borderRadius, marginLeft: 8, marginTop: 6 } @@ -144,6 +145,7 @@ export const MetadataViewFacets = (props: MetadataViewFacetsProperties) => {