Commit 12ec1698 authored by Matija Obreza's avatar Matija Obreza
Browse files

Merge branch 'genesys-server-425-ui-part' into 'master'

Versioned Datasets: update - UI part

See merge request genesys-pgr/genesys-ui!264
parents 6ece18c7 c1059c70
...@@ -1078,7 +1078,10 @@ ...@@ -1078,7 +1078,10 @@
}, },
"c": { "c": {
"card": { "card": {
"evaluationPeriod": "Evaluation period" "evaluationPeriod": "Evaluation period",
"version": "Version",
"newVersionLink": "See current version of the subset",
"currentVersion": "Current version"
}, },
"datasetDisplay": { "datasetDisplay": {
"accessionsEvaluated": "Accessions evaluated", "accessionsEvaluated": "Accessions evaluated",
......
...@@ -31,6 +31,7 @@ export { createDataset }; ...@@ -31,6 +31,7 @@ export { createDataset };
// Wrapped API Calls // Wrapped API Calls
const apiMyDatasets = createApiCaller(DatasetService.myDatasets, DASHBOARD_APPEND_DATASET_PAGE); const apiMyDatasets = createApiCaller(DatasetService.myDatasets, DASHBOARD_APPEND_DATASET_PAGE);
const apiListAccessions = createApiCaller(DatasetService.listAccessions, DASHBOARD_APPEND_ACCESSIONS_PAGE); const apiListAccessions = createApiCaller(DatasetService.listAccessions, DASHBOARD_APPEND_ACCESSIONS_PAGE);
const apiCreateNewVersion = createApiCaller(DatasetService.createNewVersion, RECEIVE_DATASET);
export const apiGetDataset = createApiCaller(DatasetService.getDataset, RECEIVE_DATASET); export const apiGetDataset = createApiCaller(DatasetService.getDataset, RECEIVE_DATASET);
export const apiRejectDataset = createApiCaller(DatasetService.rejectDataset, RECEIVE_DATASET); export const apiRejectDataset = createApiCaller(DatasetService.rejectDataset, RECEIVE_DATASET);
...@@ -71,6 +72,10 @@ export const loadDataset = (uuid: string) => (dispatch) => { ...@@ -71,6 +72,10 @@ export const loadDataset = (uuid: string) => (dispatch) => {
return dispatch(apiGetDataset(uuid)); return dispatch(apiGetDataset(uuid));
}; };
export const createNewVersion = (uuid) => (dispatch) => {
return dispatch(apiCreateNewVersion(uuid))
.then((newVersion) => dispatch(navigateTo(`/dashboard/datasets/${newVersion.uuid}/edit`)));
};
function publishDataset(datasetUuid: string) { function publishDataset(datasetUuid: string) {
return (dispatch, getState) => { return (dispatch, getState) => {
......
...@@ -62,6 +62,7 @@ function datasetsDashboard(state = INITIAL_STATE, action: { type?: string, paylo ...@@ -62,6 +62,7 @@ function datasetsDashboard(state = INITIAL_STATE, action: { type?: string, paylo
return update(state, { return update(state, {
dataset: { $set: apiCall }, dataset: { $set: apiCall },
paged: apiCall.loading ? { $set: state.paged } : { $set: null }, paged: apiCall.loading ? { $set: state.paged } : { $set: null },
accessionRefs: { $set: mustRemoveAccessions ? null : state.accessionRefs },
}); });
} }
} }
......
...@@ -35,7 +35,7 @@ function datasetsPublic(state = INITIAL_STATE, action: { type?: string, payload? ...@@ -35,7 +35,7 @@ function datasetsPublic(state = INITIAL_STATE, action: { type?: string, payload?
const {apiCall} = action.payload; const {apiCall} = action.payload;
const receivedIndex = state.paged && state.paged.data ? _.findIndex(state.paged.data.content, (item) => item.uuid === apiCall.uuid) : -1; const receivedIndex = state.paged && state.paged.data ? _.findIndex(state.paged.data.content, (item) => item.uuid === apiCall.uuid) : -1;
const mustRemoveAccessions = state.dataset && state.dataset.data && (apiCall.uuid !== state.dataset.data.uuid); const mustRemoveAccessions = state.dataset && state.dataset.data && apiCall.data && (apiCall.uuid !== state.dataset.data.uuid);
if (receivedIndex !== -1) { if (receivedIndex !== -1) {
return update(state, { return update(state, {
...@@ -50,6 +50,7 @@ function datasetsPublic(state = INITIAL_STATE, action: { type?: string, payload? ...@@ -50,6 +50,7 @@ function datasetsPublic(state = INITIAL_STATE, action: { type?: string, payload?
} else { } else {
return update(state, { return update(state, {
dataset: { $set: apiCall }, dataset: { $set: apiCall },
accessionRefs: { $set: mustRemoveAccessions ? null : state.accessionRefs },
}); });
} }
} }
......
...@@ -147,7 +147,10 @@ ...@@ -147,7 +147,10 @@
}, },
"c": { "c": {
"card": { "card": {
"evaluationPeriod": "Evaluation period" "evaluationPeriod": "Evaluation period",
"version": "Version",
"newVersionLink": "See current version of the subset",
"currentVersion": "Current version"
}, },
"datasetDisplay": { "datasetDisplay": {
"accessionsEvaluated": "Accessions evaluated", "accessionsEvaluated": "Accessions evaluated",
......
...@@ -61,6 +61,14 @@ class DatasetDetail extends React.Component<IDatasetDetailProps, any> { ...@@ -61,6 +61,14 @@ class DatasetDetail extends React.Component<IDatasetDetailProps, any> {
} }
} }
public componentWillReceiveProps(nextProps) {
const { loading, dataset, uuid, loadDataset, loadMoreAccessions } = nextProps;
if (!loading && uuid && (! dataset || uuid !== dataset.uuid)) {
loadDataset(uuid);
loadMoreAccessions(uuid);
}
}
private loadMoreAccessions = (paged: Page<AccessionRef>) => { private loadMoreAccessions = (paged: Page<AccessionRef>) => {
const { loadMoreAccessions, dataset } = this.props; const { loadMoreAccessions, dataset } = this.props;
loadMoreAccessions(dataset.uuid, paged); loadMoreAccessions(dataset.uuid, paged);
......
...@@ -40,6 +40,7 @@ import PagedLoader from 'ui/common/PagedLoader'; ...@@ -40,6 +40,7 @@ import PagedLoader from 'ui/common/PagedLoader';
import AccessionRefCard from 'accessions/ui/c/AccessionRefCard'; import AccessionRefCard from 'accessions/ui/c/AccessionRefCard';
import Number from 'ui/common/Number'; import Number from 'ui/common/Number';
import DownloadDialog from 'ui/common/download-dialog'; import DownloadDialog from 'ui/common/download-dialog';
import {DatasetLink} from 'ui/genesys/Links';
const styles = (theme) => ({ const styles = (theme) => ({
root: { root: {
...@@ -129,6 +130,9 @@ const styles = (theme) => ({ ...@@ -129,6 +130,9 @@ const styles = (theme) => ({
marginRight: '0', marginRight: '0',
}, },
}, },
hasNewVersion: {
backgroundColor: '#ffe2e2 !important',
},
}); });
interface IDetailInfoProps extends React.ClassAttributes<any> { interface IDetailInfoProps extends React.ClassAttributes<any> {
...@@ -264,7 +268,7 @@ class DetailInfo extends React.Component<IDetailInfoProps, any> { ...@@ -264,7 +268,7 @@ class DetailInfo extends React.Component<IDetailInfoProps, any> {
<Grid container spacing={ 0 }> <Grid container spacing={ 0 }>
<Grid item xs={ 12 } className="p-10" id="dataset-top"> <Grid item xs={ 12 } className="p-10" id="dataset-top">
<Card className={ classes.card } square> <Card className={ classes.card } square>
<CardHeader className={ classes.cardHeader } <CardHeader className={ dataset.currentVersion && classes.hasNewVersion }
title={ t('datasets.public.p.display.title') } title={ t('datasets.public.p.display.title') }
subheader={ <small>{ dataset.versionTag }</small> }/> subheader={ <small>{ dataset.versionTag }</small> }/>
<CardContent className={ classes.cardContent }> <CardContent className={ classes.cardContent }>
...@@ -291,6 +295,13 @@ class DetailInfo extends React.Component<IDetailInfoProps, any> { ...@@ -291,6 +295,13 @@ class DetailInfo extends React.Component<IDetailInfoProps, any> {
<PropertiesItem title={ t('datasets.public.c.datasetDisplay.properties.evaluationEnd') }> <PropertiesItem title={ t('datasets.public.c.datasetDisplay.properties.evaluationEnd') }>
<McpdDate value={ dataset.endDate }/> <McpdDate value={ dataset.endDate }/>
</PropertiesItem> </PropertiesItem>
{ dataset.currentVersion &&
<PropertiesItem classes={ {propertiesRow: classes.hasNewVersion} } title={ t('datasets.public.c.card.version') }>
<span>
<DatasetLink uuid={ dataset.currentVersion }>{ t('datasets.public.c.card.newVersionLink') }</DatasetLink>
</span>
</PropertiesItem>
}
</Properties> </Properties>
</CardContent> </CardContent>
{ publishDataset && (dataset._permissions.write || dataset._permissions.delete) && ( { publishDataset && (dataset._permissions.write || dataset._permissions.delete) && (
......
...@@ -3,12 +3,27 @@ import { connect } from 'react-redux'; ...@@ -3,12 +3,27 @@ import { connect } from 'react-redux';
import { bindActionCreators } from 'redux'; import { bindActionCreators } from 'redux';
import BaseMyDataPage from 'ui/catalog/dashboard/MyDataPage'; import BaseMyDataPage from 'ui/catalog/dashboard/MyDataPage';
import { approveDataset, deleteDataset, loadMoreDatasets, unpublishDataset, publishDataset } from 'datasets/actions/dashboard'; import { approveDataset, deleteDataset, loadMoreDatasets, unpublishDataset, publishDataset, createNewVersion } from 'datasets/actions/dashboard';
import Dataset from 'model/catalog/Dataset'; import Dataset from 'model/catalog/Dataset';
import { DatasetLink } from 'ui/catalog/Links'; import { DatasetLink } from 'ui/genesys/Links';
import { PublishState } from 'model/common.model'; import { PublishState } from 'model/common.model';
import ActionButton from 'ui/common/buttons/ActionButton';
const renderDataLink = ({ row, children }) => (<DatasetLink to={ row } edit={ row.state === PublishState.DRAFT && row._permissions.write }>{ children }</DatasetLink>); const renderDataLink = ({ row, children, needCurrent, t }) => (
<span>
{ needCurrent ? <DatasetLink uuid={ row.currentVersion }>{ t('datasets.public.c.card.currentVersion') }</DatasetLink>
: <DatasetLink to={ row } edit={ row.state === PublishState.DRAFT && row._permissions.write }>{ children }</DatasetLink>
}
</span>
);
const renderActions = ({ row, handleCreateNewVersion, t }) => (
<div>
{ row.state === PublishState.PUBLISHED &&
<ActionButton variant="text" title={ t('common:action.createNewVersion') } action={ () => handleCreateNewVersion(row.uuid) }/>
}
</div>
);
class DashboardPage extends BaseMyDataPage<Dataset> {} class DashboardPage extends BaseMyDataPage<Dataset> {}
...@@ -18,6 +33,7 @@ const mapStateToProps = (state, ownProps) => ({ ...@@ -18,6 +33,7 @@ const mapStateToProps = (state, ownProps) => ({
dataClassName: Dataset.clazz, dataClassName: Dataset.clazz,
filterCode: ownProps.match.params.filterCode, filterCode: ownProps.match.params.filterCode,
renderDataLink, renderDataLink,
renderActions,
}); });
const mapDispatchToProps = (dispatch) => bindActionCreators({ const mapDispatchToProps = (dispatch) => bindActionCreators({
...@@ -26,6 +42,7 @@ const mapDispatchToProps = (dispatch) => bindActionCreators({ ...@@ -26,6 +42,7 @@ const mapDispatchToProps = (dispatch) => bindActionCreators({
publishOne: publishDataset, publishOne: publishDataset,
approveOne: approveDataset, approveOne: approveDataset,
unpublishOne: unpublishDataset, unpublishOne: unpublishDataset,
createNewVersion: (uuid) => dispatch(createNewVersion(uuid)),
}, dispatch); }, dispatch);
export default connect(mapStateToProps, mapDispatchToProps)(DashboardPage); export default connect(mapStateToProps, mapDispatchToProps)(DashboardPage);
...@@ -23,6 +23,7 @@ class Dataset implements IUserPermissions { ...@@ -23,6 +23,7 @@ class Dataset implements IUserPermissions {
public createdDate: Date; public createdDate: Date;
public creators: DatasetCreator[]; public creators: DatasetCreator[];
public crops: string[]; public crops: string[];
public currentVersion: string;
public description: string; public description: string;
public descriptorCount: number; public descriptorCount: number;
public descriptors: Descriptor[]; public descriptors: Descriptor[];
......
...@@ -42,6 +42,7 @@ const URL_DELETE_LOCATION = UrlTemplate.parse(`/api/v1/dataset/{uuid}/location/d ...@@ -42,6 +42,7 @@ const URL_DELETE_LOCATION = UrlTemplate.parse(`/api/v1/dataset/{uuid}/location/d
const URL_LIST_LOCATION = UrlTemplate.parse(`/api/v1/dataset/{uuid}/location/list`); const URL_LIST_LOCATION = UrlTemplate.parse(`/api/v1/dataset/{uuid}/location/list`);
const URL_UPDATE_LOCATION = UrlTemplate.parse(`/api/v1/dataset/{uuid}/location/update`); const URL_UPDATE_LOCATION = UrlTemplate.parse(`/api/v1/dataset/{uuid}/location/update`);
const URL_LOAD_LOCATION_BY_UUID = UrlTemplate.parse(`/api/v1/dataset/{uuid}/location/{locationUuid}`); const URL_LOAD_LOCATION_BY_UUID = UrlTemplate.parse(`/api/v1/dataset/{uuid}/location/{locationUuid}`);
const URL_CREATE_NEW_VERSION = `/api/v1/dataset/create-new-version`;
/* /*
* Defined in Swagger as 'dataset' * Defined in Swagger as 'dataset'
...@@ -137,6 +138,28 @@ class DatasetService { ...@@ -137,6 +138,28 @@ class DatasetService {
}).then(({ data }) => data as Dataset); }).then(({ data }) => data as Dataset);
} }
/**
* createNewVersion at /api/v1/dataset/create-new-version
*
* @param uuid uuid
*/
public static createNewVersion(uuid: string, xhrConfig?): Promise<Dataset> {
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 Dataset);
}
/** /**
* reviewDataset at /api/v1/dataset/for-review * reviewDataset at /api/v1/dataset/for-review
* *
......
...@@ -33,6 +33,8 @@ interface IDataPublishedContainerProps extends React.ClassAttributes<any> { ...@@ -33,6 +33,8 @@ interface IDataPublishedContainerProps extends React.ClassAttributes<any> {
listMyData: any; listMyData: any;
dataClassName: string; dataClassName: string;
renderDataLink: any; renderDataLink: any;
renderActions: any;
createNewVersion: (uuid: string) => void;
addToEditList: (item: any) => void; addToEditList: (item: any) => void;
removeFromEditList: (item: any) => void; removeFromEditList: (item: any) => void;
onPageChange: () => void; onPageChange: () => void;
...@@ -117,7 +119,7 @@ class BaseMyDataPage<T> extends React.Component<T & IDataPublishedContainerProps ...@@ -117,7 +119,7 @@ class BaseMyDataPage<T> extends React.Component<T & IDataPublishedContainerProps
} }
public render() { public render() {
const { tab, filterComponent, basePath, addToEditList, removeFromEditList, isEditMode, setEditMode, editList, paged, dataClassName, renderDataLink, title } = this.props; const { tab, filterComponent, basePath, addToEditList, removeFromEditList, isEditMode, setEditMode, editList, paged, dataClassName, renderDataLink, renderActions, createNewVersion, title } = this.props;
const actionHandlers = this.getActionHandlers(); const actionHandlers = this.getActionHandlers();
const Filters = filterComponent ? filterComponent : DashboardFilters; const Filters = filterComponent ? filterComponent : DashboardFilters;
...@@ -132,6 +134,8 @@ class BaseMyDataPage<T> extends React.Component<T & IDataPublishedContainerProps ...@@ -132,6 +134,8 @@ class BaseMyDataPage<T> extends React.Component<T & IDataPublishedContainerProps
onFilter={ this.onFilter } onFilter={ this.onFilter }
dataClassName={ dataClassName } dataClassName={ dataClassName }
renderDataLink={ renderDataLink } renderDataLink={ renderDataLink }
renderActions={ renderActions }
createNewVersion={ createNewVersion }
paged={ paged } paged={ paged }
onSortChange={ this.onSortChange } onSortChange={ this.onSortChange }
setEditState={ setEditMode } setEditState={ setEditMode }
......
...@@ -35,6 +35,11 @@ const styles = () => ({ ...@@ -35,6 +35,11 @@ const styles = () => ({
}, },
/*tslint:enable*/ /*tslint:enable*/
}, },
cardActions: {
width: '100%',
display: 'flex',
flexDirection: 'row-reverse' as 'row-reverse',
},
}); });
class DashboardCard extends React.Component<any> { class DashboardCard extends React.Component<any> {
...@@ -61,7 +66,7 @@ class DashboardCard extends React.Component<any> { ...@@ -61,7 +66,7 @@ class DashboardCard extends React.Component<any> {
} }
public render() { public render() {
const { item, tab, index, isEditMode, DataLink, dataClassName, t, classes } = this.props; const { item, tab, index, isEditMode, DataLink, dataClassName, createNewVersion, Actions, t, classes } = this.props;
const { inEditList } = this.state; const { inEditList } = this.state;
return ( return (
...@@ -93,6 +98,11 @@ class DashboardCard extends React.Component<any> { ...@@ -93,6 +98,11 @@ class DashboardCard extends React.Component<any> {
{ ` ${t('descriptors.common.modelName', {count: item.descriptorCount})} ` } { ` ${t('descriptors.common.modelName', {count: item.descriptorCount})} ` }
</span> </span>
} }
{ item.currentVersion &&
<span className="float-right">
<DataLink row={ item } needCurrent t={ t }/>
</span>
}
</div> </div>
<DashboardCardDates item={ item }/> <DashboardCardDates item={ item }/>
</div> </div>
...@@ -108,7 +118,10 @@ class DashboardCard extends React.Component<any> { ...@@ -108,7 +118,10 @@ class DashboardCard extends React.Component<any> {
onChange={ this.onCheckboxChange } onChange={ this.onCheckboxChange }
style={ !isEditMode ? { opacity: 0 } : {} } style={ !isEditMode ? { opacity: 0 } : {} }
/> />
{ item._permissions.manage && <Permissions clazz={ dataClassName } id={ item.id }/> } <div className={ classes.cardActions }>
{ item._permissions.manage && <Permissions clazz={ dataClassName } id={ item.id }/> }
{ Actions && <Actions row={ item } handleCreateNewVersion={ createNewVersion } t={ t } /> }
</div>
</CardActions> </CardActions>
</Card> </Card>
); );
......
...@@ -32,6 +32,8 @@ interface IMyDataCardsProps extends React.Props<any> { ...@@ -32,6 +32,8 @@ interface IMyDataCardsProps extends React.Props<any> {
onFilter: (filter) => void; onFilter: (filter) => void;
dataClassName: string; dataClassName: string;
renderDataLink: any; renderDataLink: any;
renderActions: any;
createNewVersion: (uuid: string) => void;
pagination: any; pagination: any;
promiseListData: any; promiseListData: any;
deleteAllAction: any; deleteAllAction: any;
...@@ -74,6 +76,8 @@ class MyDataCards extends React.Component<IMyDataCardsProps> { ...@@ -74,6 +76,8 @@ class MyDataCards extends React.Component<IMyDataCardsProps> {
removeFromEditAction={ this.props.removeFromEditList } removeFromEditAction={ this.props.removeFromEditList }
dataClassName={ this.props.dataClassName } dataClassName={ this.props.dataClassName }
DataLink={ this.props.renderDataLink } DataLink={ this.props.renderDataLink }
Actions={ this.props.renderActions }
createNewVersion={ this.props.createNewVersion }
/> />
) )
......
...@@ -3,6 +3,7 @@ import { Link } from 'react-router-dom'; ...@@ -3,6 +3,7 @@ import { Link } from 'react-router-dom';
import Markdown from 'ui/common/markdown'; import Markdown from 'ui/common/markdown';
import Subset from 'model/subset/Subset'; import Subset from 'model/subset/Subset';
import Dataset from 'model/catalog/Dataset';
import Accession from 'model/accession/Accession'; import Accession from 'model/accession/Accession';
import FaoInstitute from 'model/genesys/FaoInstitute'; import FaoInstitute from 'model/genesys/FaoInstitute';
import MaterialRequest from 'model/request/MaterialRequest'; import MaterialRequest from 'model/request/MaterialRequest';
...@@ -137,16 +138,20 @@ const RegionLink = ({ region, children }: { region: GeoRegion, children?: any }) ...@@ -137,16 +138,20 @@ const RegionLink = ({ region, children }: { region: GeoRegion, children?: any })
); );
}; };
const DatasetLink = ({ to: dataset, edit = false, children = null } const DatasetLink = ({ to: dataset, uuid = null, edit = false, children = null }
: { to: any, edit?: boolean, children?: any }) => { : { to?: Dataset, uuid?: string, edit?: boolean, children?: any }) => {
if (dataset) { if (dataset) {
return ( return (
<Link to={ `/datasets/${dataset.uuid}` }> <Link to={ `${edit ? '/dashboard' : ''}/datasets/${dataset.uuid}${edit ? '/edit' : '' }` }>
{ children || <Markdown basic source={ dataset.title } /> } { children || <Markdown basic source={ dataset.title } /> }
</Link> </Link>
); );
} else { } else {
return null; return uuid && children ? (
<Link to={ `${edit ? '/dashboard' : ''}/datasets/${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