Commit 9c4a4823 authored by Matija Obreza's avatar Matija Obreza
Browse files

Merge branch '234-versioned-subsets' into 'master'

Resolve "Versioned subsets"

Closes #234

See merge request genesys-pgr/genesys-ui!242
parents 814f00c9 12ca1de4
......@@ -5,6 +5,7 @@
"backTo": "Back to {{where, lowercase}}",
"backToDashboard": "Back to dashboard",
"cancel": "Cancel",
"createNewVersion": "Create new version",
"OK": "OK",
"close": "Close",
"collapse": "Collapse",
......@@ -85,6 +86,7 @@
"false": "False",
"filters": "Filters",
"from": "From",
"here": "here",
"itemEditorWarn": "Don't use the ItemsEditor for more than 100 items!",
"lastModified": "Last modified",
"lastUpdated": "Last updated",
......
......@@ -1992,7 +1992,10 @@
"institute": "Institute",
"license": "License",
"creationDate": "Creation date",
"source": "Source"
"source": "Source",
"version": "Version",
"newVersionLink": "See current version of the subset",
"currentVersion": "Current version"
},
"subsetDisplay": {
"subsetCreators": "Subset creators",
......
......@@ -21,6 +21,7 @@ class Subset implements IUserPermissions {
public creators: SubsetCreator[];
public createdBy: number;
public createdDate: Date;
public currentVersion: string;
public dateCreated: string;
public description: string;
public id: number;
......
......@@ -16,6 +16,7 @@ const URL_SET_ACCESSIONS = UrlTemplate.parse(`/api/v1/subset/set-accessions/{uui
const URL_REMATCH_ACCESSIONS = UrlTemplate.parse(`/api/v1/subset/rematch-accessions/{uuid},{version}`);
const URL_APPROVE_SUBSET = `/api/v1/subset/approve`;
const URL_CREATE = `/api/v1/subset/create`;
const URL_CREATE_NEW_VERSION = `/api/v1/subset/create-new-version`;
const URL_REVIEW_SUBSET = `/api/v1/subset/for-review`;
const URL_LIST = `/api/v1/subset/list`;
const URL_MY_SUBSETS = `/api/v1/subset/list-mine`;
......@@ -169,6 +170,27 @@ class SubsetService {
...content,
}).then(({ data }) => data as Subset);
}
/**
* createNewVersion at /api/v1/subset/create-new-version
*
* @param uuid uuid
*/
public static createNewVersion(uuid: string, xhrConfig?): Promise<Subset> {
const qs = QueryString.stringify({
uuid: uuid || undefined,
}, {});
const apiUrl = URL_CREATE_NEW_VERSION + (qs ? `?${qs}` : '');
// console.log(`Fetching from ${apiUrl}`);
const content = { /* No content in request body */ };
return axiosBackend.request({
...xhrConfig,
url: apiUrl,
method: 'POST',
...content,
}).then(({ data }) => data as Subset);
}
/**
* reviewSubset at /api/v1/subset/for-review
......
......@@ -41,6 +41,7 @@ const receiveAccessions = (accessionRefs: Page<AccessionRef>, error = null) => (
const apiLoadSubset = createApiCaller(SubsetService.get, DASHBOARD_RECEIVE_SUBSET);
const apiListSubsets = createApiCaller(SubsetService.mySubsets, DASHBOARD_APPEND_SUBSETS);
const apiListSubsetAccessions = createApiCaller(SubsetService.listAccessions, DASHBOARD_APPEND_ACCESSIONS);
const apiCreateNewVersion = createApiCaller(SubsetService.createNewVersion, DASHBOARD_RECEIVE_SUBSET);
export const loadSubset = (uuid: string) => (dispatch) => {
return dispatch(apiLoadSubset(uuid));
......@@ -67,3 +68,8 @@ const updateRoute = (paged: FilteredPage<Subset>) => (dispatch) => {
};
dispatch(navigateTo(paged.filterCode ? `/dashboard/subsets/${paged.filterCode}` : '/dashboard/subsets', qs));
};
export const createNewVersion = (uuid) => (dispatch) => {
return dispatch(apiCreateNewVersion(uuid))
.then((newVersion) => dispatch(navigateTo(`/dashboard/subsets/${newVersion.uuid}/edit`)));
};
......@@ -52,7 +52,7 @@ function dashboardSubsets(state = INITIAL_STATE, action: IReducerAction) {
return update(state, {
subset: {$set: apiCall},
paged: {$set: null},
accessionRefs: {$set: null},
accessionRefs: { $set: mustRemoveAccessions ? null : state.accessionRefs },
});
}
}
......
......@@ -30,7 +30,7 @@ function publicSubsets(state = INITIAL_STATE, action: IReducerAction) {
const {apiCall} = action.payload;
const receivedIndex = state.paged && state.paged.data ? _.findIndex(state.paged.data.content, (item) => item.uuid === apiCall.uuid) : -1;
const mustRemoveAccessions = state.subset && state.subset.data && (apiCall.uuid !== state.subset.data.uuid);
const mustRemoveAccessions = state.subset && state.subset.data && apiCall.data && (apiCall.data.uuid !== state.subset.data.uuid);
if (receivedIndex !== -1) {
return update(state, {
......@@ -45,7 +45,7 @@ function publicSubsets(state = INITIAL_STATE, action: IReducerAction) {
} else {
return update(state, {
subset: { $set: apiCall },
accessionRefs: {$set: null},
accessionRefs: { $set: mustRemoveAccessions ? null : state.accessionRefs },
});
}
}
......
......@@ -7,7 +7,10 @@
"institute": "Institute",
"license": "License",
"creationDate": "Creation date",
"source": "Source"
"source": "Source",
"version": "Version",
"newVersionLink": "See current version of the subset",
"currentVersion": "Current version"
},
"subsetDisplay": {
"subsetCreators": "Subset creators",
......
......@@ -64,6 +64,13 @@ class DisplayPage extends React.Component<IDisplayPageProps, any> {
loadMoreAccessions(uuid);
}
}
public componentWillReceiveProps(nextProps) {
const { loading, subset, uuid, loadSubset, loadMoreAccessions } = nextProps;
if (!loading && uuid && (! subset || uuid !== subset.uuid)) {
loadSubset(uuid);
loadMoreAccessions(uuid);
}
}
private loadMoreAccessions = (paged: Page<AccessionRef>) => {
const { loadMoreAccessions, subset } = this.props;
......
import * as React from 'react';
import { translate } from 'react-i18next';
import withStyles from '@material-ui/core/styles/withStyles';
import Subset from 'model/subset/Subset';
import {PublishState} from 'model/common.model';
......@@ -15,6 +16,18 @@ import McpdDate from 'ui/common/time/McpdDate';
import DashboardCardDates from 'ui/catalog/dashboard/c/DashboardCardDates';
import DashboardCardStatus from 'ui/catalog/dashboard/c/DashboardCardStatus';
import Permissions from 'ui/common/permission/Permissions';
import ActionButton from 'ui/common/buttons/ActionButton';
const styles = (theme) => ({
hasNewVersion: {
backgroundColor: '#ffe2e2 !important',
},
cardActions: {
width: '100%',
display: 'flex',
flexDirection: 'row-reverse' as 'row-reverse',
},
});
const SubsetCard = (
{ subset,
......@@ -23,8 +36,10 @@ const SubsetCard = (
actions,
index,
dataClassName,
handleCreateNewVersion,
isAdmin = false,
t,
classes,
...other
}: {
subset: Subset,
......@@ -33,8 +48,10 @@ const SubsetCard = (
actions?: any,
index: number,
dataClassName: string;
handleCreateNewVersion: (uuid: string) => void;
isAdmin?: boolean;
t: any
classes: any;
} & React.ClassAttributes<any>) => {
return (
......@@ -52,6 +69,11 @@ const SubsetCard = (
<b></b>
<Number value={ subset.accessionCount }/>
{ ` ${t('accessions.common.modelName', {count: subset.accessionCount})}` }
{ subset.currentVersion &&
<span className="float-right">
<SubsetLink uuid={ subset.currentVersion }>{ t('subsets.public.c.subsetCard.currentVersion') }</SubsetLink>
</span>
}
<DashboardCardDates item={ subset }/>
</div>
<div>
......@@ -60,15 +82,24 @@ const SubsetCard = (
</CardContent>
{ subset._permissions.manage &&
<CardActions>
<div style={ {width: '100%', display: 'flex', flexDirection: 'row-reverse'} }>
<div className={ classes.cardActions }>
<Permissions clazz={ dataClassName } id={ subset.id }/>
{ subset.state === PublishState.PUBLISHED &&
<ActionButton variant="text" title={ t('common:action.createNewVersion') } action={ () => handleCreateNewVersion(subset.uuid) }/>
}
</div>
</CardActions>
}
</Card>
) : (
<Card>
<CardHeader title={ !complete ? <SubsetLink to={ subset }/> : t('subsets.public.p.display.title') }/>
<CardHeader
className={ subset.currentVersion && classes.hasNewVersion }
title={
<span>
{ !complete ? <SubsetLink to={ subset }/> : t('subsets.public.p.display.title') }
</span>
}/>
<CardContent>
<Markdown className="mb-20" firstParagraph={ !complete } source={ subset.description }/>
<Properties>
......@@ -89,6 +120,13 @@ const SubsetCard = (
<PropertiesItem title={ t('subsets.public.c.subsetCard.source') }>
<ExternalLink link={ subset.source }/>
</PropertiesItem> }
{ subset.currentVersion &&
<PropertiesItem classes={ {propertiesRow: classes.hasNewVersion} } title={ t('subsets.public.c.subsetCard.version') }>
<span>
<SubsetLink uuid={ subset.currentVersion }>{ t('subsets.public.c.subsetCard.newVersionLink') }</SubsetLink>
</span>
</PropertiesItem>
}
</Properties>
</CardContent>
{ actions &&
......@@ -101,4 +139,4 @@ const SubsetCard = (
);
};
export default translate()(SubsetCard);
export default translate()(withStyles(styles)(SubsetCard));
......@@ -5,7 +5,7 @@ import { translate } from 'react-i18next';
import { parse } from 'query-string';
// Actions
import { loadMoreSubsets, applyFilters} from 'subsets/actions/dashboard';
import {loadMoreSubsets, applyFilters, createNewVersion} from 'subsets/actions/dashboard';
// Models
import FilteredPage from 'model/FilteredPage';
......@@ -28,6 +28,7 @@ import PrettyFilters from 'ui/common/filter/PrettyFilters';
interface IDashboardPageProps extends React.ClassAttributes<any> {
paged: FilteredPage<Subset>;
loadMoreSubsets: (page?: FilteredPage<Subset>) => void;
createNewVersion: (uuid: string) => void;
login: any;
t: any;
filterCode: string;
......@@ -90,6 +91,11 @@ class DashboardPage extends React.Component<IDashboardPageProps> {
applyFilters(filterCode || '', FilteredPage.reSort(paged, sortBy, dir));
}
protected handleCreateNewVersion = (uuid) => {
const {createNewVersion} = this.props;
createNewVersion(uuid);
}
public render() {
const {paged, login: { authorities: userRoles }, loadMoreSubsets, t} = this.props;
const renderSubset = (s: Subset, index: number) => {
......@@ -99,6 +105,7 @@ class DashboardPage extends React.Component<IDashboardPageProps> {
subset={ s }
index={ index }
isAdmin={ userRoles.findIndex((role) => role === 'ROLE_ADMINISTRATOR') !== -1 }
handleCreateNewVersion={ this.handleCreateNewVersion }
dataClassName={ this.props.dataClassName }
compact
/>
......@@ -149,6 +156,7 @@ const mapStateToProps = (state, ownProps) => ({
const mapDispatchToProps = (dispatch) => bindActionCreators({
loadMoreSubsets,
createNewVersion,
applyFilters,
}, dispatch);
......
......@@ -12,8 +12,8 @@ import GeoRegion from 'model/geo/GeoRegion';
import Article from 'model/cms/Article';
import OAuthClient from 'model/oauth/OAuthClient';
function SubsetLink({ to: subset, edit = false, children = null }
: { to: Subset, edit?: boolean, children?: any }) {
function SubsetLink({to: subset, uuid = null, edit = false, children = null}
: { to?: Subset, uuid?: string, edit?: boolean, children?: any }) {
if (subset) {
if (edit) {
......@@ -30,7 +30,11 @@ function SubsetLink({ to: subset, edit = false, children = null }
);
}
} else {
return null;
return uuid && children ? (
<Link to={ `${edit ? '/dashboard' : ''}/subsets/${uuid}${edit ? '/edit' : ''}` }>
{ children }
</Link>
) : null;
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment