Commit dd502cc5 authored by Matija Obreza's avatar Matija Obreza
Browse files

Merge branch '101-catalog-modules' into 'master'

Resolve "Catalog modules"

Closes #101

See merge request genesys-pgr/genesys-ui!108
parents 8acf6508 480da7c9
{
"action": {
"add": "Add {{what, lowercase}}",
"applyFilters": "Apply filters",
"approve": "Approve and publish",
"back": "Back",
"approve": "Approve",
"backTo": "Back to {{where, lowercase}}",
"backToList": "Back to list",
"backToDashboard": "Back to dashboard",
"cancel": "Cancel",
"create": "Create",
"delete": "Delete",
"close": "Close",
"deleteData": "Delete data",
"collapse": "Collapse",
"delete": "Delete",
"download": "Download",
"edit": "Edit",
"login": "Login",
"logout": "Logout",
"publish": "Publish",
"saveChanges": "Save changes",
"search": "Search",
"un-publish": "Un-publish",
"viewDetails": "View details",
"applyFilters": "Apply filters",
"back": "Back",
"backToList": "Back to list",
"create": "Create",
"deleteData": "Delete data",
"manage": "Manage",
"nextStep": "Next step",
"openSidebar": "Open sidebar",
"read": "Read",
"reject": "Reject",
"remove": "Remove",
"reset": "Reset",
"return": "Return",
"save": "Save",
"saveChanges": "Save changes",
"search": "Search",
"show": "Show",
"sendToReview": "Send to review",
"unpublish": "Unpublish",
"write": "Write"
"view": "View",
"write": "Write",
"acceptAndPublish": "ACCEPT AND PUBLISH"
},
"csv": {
"autoDetect": "Auto-detect ",
......@@ -48,7 +58,8 @@
"dateSearch": "Date search",
"fromIncluding": "From including",
"lastModifiedDate": "Last modified date",
"textSearch": "Text search"
"textSearch": "Text search",
"keyword": "Keyword search"
},
"fileUploader": {
"chooseFiles": "Choose files to upload",
......@@ -56,11 +67,17 @@
"release": "Release to upload"
},
"label": {
"item": "Item",
"item_plural": "Items",
"list": "List",
"list_plural": "Lists",
"created": "Created",
"dateNotProvided": "Date not provided",
"description": "Description",
"either": "Either",
"false": "False",
"filters": "Filters",
"from": "From",
"itemEditorWarn": "Don't use the ItemsEditor for more than 100 items!",
"lastModified": "Last modified",
"lastUpdated": "Last updated",
......@@ -69,11 +86,16 @@
"newVersionAvailable": "New version available",
"no": "No",
"prettyNumber": "{{value, number}}",
"registered": "Registered",
"sortBy": "Sort By",
"status": "Status",
"stepsForDataPublication": "Steps for data publication completion",
"title": "Title",
"true": "True",
"to": "To",
"untitled": "Untitled",
"UUID": "UUID",
"version": "Version {{version, numeric}}",
"yes": "Yes",
"basicMarkdown": "Basic markdown supported",
"fullMarkdown": "Full markdown supported",
......@@ -96,5 +118,12 @@
"objectIdentityId": "ACL OID ID",
"parentObjectIdentityId": "Parent OID ID",
"updateParentOID": "Update Parent OID ID"
},
"sort": {
"name": "Name",
"title": "Title",
"owner": "Owner",
"version": "Version",
"latestEdit": "Recently modified"
}
}
This diff is collapsed.
import * as React from 'react';
import { withStyles } from '@material-ui/core/styles';
import Accession from 'model/accession/Accession';
import Card, { CardContent, CardActions } from 'ui/common/Card';
import DOI from 'ui/common/DOI';
import SciName from 'ui/genesys/SciName';
import { AccessionRef } from 'model/accession/AccessionRef';
import AccessionCard from './AccessionCard';
const styles = (theme) => ({
firstRow: {
marginBottom: '1em',
},
accessionRef: {
background: 'white', // '#c9e2cb',
},
});
const AccessionRefCard = ({ accessionRef, classes, index }:
{ accessionRef: AccessionRef, classes: any, index?: number} & React.ClassAttributes<any>) => {
const accession: Accession = accessionRef.accession;
if (accession) {
return <AccessionCard accession={ accession } index={ index } />;
}
return (
<Card className={ classes.accessionRef }>
<CardContent>
<div className={ classes.firstRow }>
<b>
{ index !== undefined && `${index + 1}. ` }
{ accessionRef.acceNumb }
{ ` • ` }
<SciName taxa={ accessionRef.genus } />
</b>
</div>
<div>
{ accessionRef.instCode }
{ ` • ` }
{ ` DOI: ` }
{ accessionRef.doi && <DOI noPrefix value={ accessionRef.doi } /> || 'N/A' }
</div>
</CardContent>
{ false &&
<CardActions>
Actions
</CardActions>
}
</Card>
);
};
export default withStyles(styles)(AccessionRefCard);
// constants
import { ADD_TO_EDIT_LIST, REMOVE_FROM_EDIT_LIST, RECEIVE_IS_EDIT_MODE, SELECT_ALL, UNSELECT_ALL } from 'constants/dashboard';
// Models
import Dataset from 'model/catalog/Dataset';
import Descriptor from 'model/catalog/Descriptor';
import DescriptorList from 'model/catalog/DescriptorList';
export const setEditMode = (payload: boolean) => (dispatch) => {
dispatch({ type: RECEIVE_IS_EDIT_MODE, payload });
};
export const selectAll = (tab: string) => (dispatch, getState) => {
let payload;
switch (tab) {
case 'descriptorlists':
payload = getState().descriptorList.dashboard.paged.content.map((item) => item.uuid);
break;
case 'descriptors':
payload = getState().descriptors.dashboard.paged.content.map((item) => item.uuid);
break;
case 'datasets':
default:
payload = getState().datasets.dashboard.paged.content.map((item) => item.uuid);
}
return dispatch({
type: SELECT_ALL,
payload,
});
};
export const unselectAll = () => ({
type: UNSELECT_ALL,
});
const addToList = (payload: Dataset | Descriptor | DescriptorList) => (dispatch) => {
dispatch({ type: ADD_TO_EDIT_LIST, payload: payload.uuid });
};
const removeFromList = (payload: Dataset | Descriptor | DescriptorList) => (dispatch) => {
dispatch({ type: REMOVE_FROM_EDIT_LIST, payload: payload.uuid });
};
export const onPageChange = () => (dispatch) => {
dispatch(setEditMode(false));
dispatch(unselectAll());
};
export const addToEditList = (item: Dataset | Descriptor | DescriptorList) => (dispatch, getState) => {
const list = getState().dashboard.selected;
if (!list.includes(item)) {
dispatch(addToList(item));
}
};
export const removeFromEditList = (item: Dataset | Descriptor | DescriptorList) => (dispatch, getState) => {
const list = getState().dashboard.selected;
if (list.includes(item)) {
dispatch(removeFromList(item));
}
};
/**
* Publish all items that are in dashboard.toEditList
* @param publishOne: (uuid: string) => Promise<any> action to publish one item
*/
export const publishAll = (publishOne) => (dispatch, getState) => {
const toPublishItems = getState().dashboard.selected;
toPublishItems.map((item) => {
publishOne(item);
dispatch(removeFromList(item));
});
dispatch(unselectAll());
};
/**
* Approve all items that are in dashboard.toEditList
* @param approveOne: (uuid: string) => Promise<any> action to approve one item
*/
export const approveAll = (approveOne) => (dispatch, getState) => {
const toApproveItems = getState().dashboard.selected;
toApproveItems.map((item) => {
approveOne(item);
dispatch(removeFromList(item));
});
dispatch(unselectAll());
};
/**
* Unpublish all items that are in dashboard.toEditList
* @param unPublishOne: (uuid: string) => Promise<any> action to unpublish one item
*/
export const unpublishAll = (unPublishOne) => (dispatch, getState) => {
const toUnpublishItems = getState().dashboard.selected;
toUnpublishItems.map((item) => {
unPublishOne(item);
dispatch(removeFromList(item));
});
dispatch(unselectAll());
};
/**
* Delete all items that are in dashboard.toEditList
* @param deleteOne: (uuid: string) => Promise<any> action to delete one item
*/
export const deleteAll = (deleteOne) => (dispatch, getState) => {
const toDeleteItems = getState().dashboard.selected;
toDeleteItems.map((item) => {
deleteOne(item);
dispatch(removeFromList(item));
});
dispatch(unselectAll());
};
import { ADD_UPDATE_DESCRIPTOR_FILTER } from 'constants/filter';
import IDescriptorFilter from 'model/catalog/DescriptorFilter';
function updateDescriptorFilterModel(filter: IDescriptorFilter) {
return (dispatch, getState) => {
return dispatch(updateDescriptor(filter));
};
}
function updateDescriptor(filter: IDescriptorFilter) {
return {
type: ADD_UPDATE_DESCRIPTOR_FILTER,
payload: {
filter,
},
};
}
export { updateDescriptorFilterModel };
import SearchService from 'service/catalog/SearchService';
import DescriptorService from 'service/catalog/DescriptorService';
import DatasetService from 'service/catalog/DatasetService';
import DescriptorListService from 'service/catalog/DescriptorListService';
import DescriptorList from 'model/catalog/DescriptorList';
import Descriptor from 'model/catalog/Descriptor';
import Page from 'model/Page';
import Dataset from 'model/catalog/Dataset';
import {
SEARCH_DATASET_PAGE,
SEARCH_DESCRIPTOR_PAGE,
SEARCH_DESCRIPTOR_LIST_PAGE,
NEW_SEARCH,
SEARCH_DATASET_SUGGESTIONS,
} from 'constants/search';
import { log } from 'utilities/debug';
const search = (search: string) => ({
type: NEW_SEARCH,
payload: { search },
});
const searchDatasetPage = (paged: Page<Dataset>) => ({
type: SEARCH_DATASET_PAGE,
payload: { paged },
});
const searchDescriptorPage = (paged: Page<Descriptor>) => ({
type: SEARCH_DESCRIPTOR_PAGE,
payload: { paged },
});
const searchDescriptorListPage = (paged: Page<DescriptorList>) => ({
type: SEARCH_DESCRIPTOR_LIST_PAGE,
payload: { paged },
});
const searchDatasetsSuggestions = (suggestions: any) => ({
type: SEARCH_DATASET_SUGGESTIONS,
payload: suggestions,
});
export function datasetSuggestions(searchQuery, filter?) {
return (dispatch, getState) => {
if (searchQuery && searchQuery.trim() !== '') {
return SearchService.datasets(searchQuery, filter)
.then((data) => {
return dispatch(searchDatasetsSuggestions(data));
})
.catch((error) => {
log('Error', error);
});
} else {
log('No search query for datasets');
return null;
}
};
}
export function searchDatasets(page?, results?, sortBy?: string[], filter?, order?) {
return (dispatch, getState) => {
dispatch(search(filter._text));
return DatasetService.datasetList(filter, { page, size: results, properties: sortBy, direction: order })
.then((paged) => {
return dispatch(searchDatasetPage(paged));
})
.catch((error) => {
log('Error', error);
});
};
}
export function searchDescriptors(page?, results?, sortBy?, filter?, order?) {
return (dispatch, getState) => {
dispatch(search(filter._text));
return DescriptorService.listDescriptors(filter, { page, size: results, properties: sortBy, direction: order })
.then((paged) => {
return dispatch(searchDescriptorPage(paged));
})
.catch((error) => {
log('Error', error);
});
};
}
export function searchDescriptorLists(page?, results?, sortBy?: string[], filter?, order?) {
return (dispatch, getState) => {
dispatch(search(filter._text));
return DescriptorListService.listDescriptorLists(filter, { page, size: results, properties: sortBy, direction: order })
.then((paged) => {
return dispatch(searchDescriptorListPage(paged));
})
.catch((error) => {
log('Error', error);
});
};
}
import * as _ from 'lodash';
import Partner from 'model/genesys/Partner';
import DescriptorList from 'model/catalog/DescriptorList';
import { RECEIVE_UUID_LABELS } from 'constants/uuidDecoder';
const receiveUuidLabels = (labels) => ({
type: RECEIVE_UUID_LABELS,
payload: labels,
});
export const loadPartnerNames = (partners: Partner[]) => (dispatch, getState) => {
const labels = _.isEmpty(getState().uuidDecoder.labels) ? new Map<string, string>() : new Map<string, string>(getState().uuidDecoder.labels);
partners.forEach((partner) => {
labels.set(partner.uuid, partner.shortName);
});
return dispatch(receiveUuidLabels(labels));
};
export const loadDescriptorListTitles = (lists: DescriptorList[]) => (dispatch, getState) => {
const labels = _.isEmpty(getState().uuidDecoder.labels) ? new Map<string, string>() : new Map<string, string>(getState().uuidDecoder.labels);
lists.forEach((list) => {
labels.set(list.uuid, list.title);
});
return dispatch(receiveUuidLabels(labels));
};
export const DASHBOARD_FILTERFORM = 'Form/DASHBOARD_FILTERFORM';
export const RECEIVE_IS_EDIT_MODE = 'dashboard/RECEIVE_IS_EDIT_MODE';
export const ADD_TO_EDIT_LIST = 'dashboard/ADD_TO_EDIT_LIST';
export const REMOVE_FROM_EDIT_LIST = 'dashboard/REMOVE_FROM_EDIT_LIST';
export const SELECT_ALL = 'dashboard/SELECT_ALL';
export const UNSELECT_ALL = 'dashboard/UNSELECT_ALL';
export const ADD_UPDATE_PARTNER_FILTER = 'App/ADD_UPDATE_PARTNER_FILTER';
export const ADD_UPDATE_DATASET_FILTER = 'App/ADD_UPDATE_DATASET_FILTER';
export const ADD_UPDATE_DESCRIPTOR_FILTER = 'App/ADD_UPDATE_DESCRIPTOR_FILTER';
export const DESCRIPTOR_FILTER_FORM = 'DESCRIPTOR_FILTER_FORM';
export const DATASET_FILTER_FORM = 'DATASET_FILTER_FORM';
export const PARTNER_FILTER_FORM = 'PARTNER_FILTER_FORM';
export const NEW_SEARCH = 'App/NEW_SEARCH';
export const SEARCH_DATASET_PAGE = 'App/SEARCH_DATASET_PAGE';
export const SEARCH_DESCRIPTOR_PAGE = 'App/SEARCH_DESCRIPTOR_PAGE';
export const SEARCH_DESCRIPTOR_LIST_PAGE = 'App/SEARCH_DESCRIPTOR_LIST_PAGE';
export const SEARCH_DATASET_SUGGESTIONS = 'App/SEARCH_DATASET_SUGGESTIONS';
export const SEARCHSUGGESTIONS_FORM = 'Form/SEARCH_SUGGESTIONS';
export const RECEIVE_UUID_LABELS = 'uuidDecoder/RECEIVE_UUID_LABELS';
import * as React from 'react';
import { connect } from 'react-redux';
import { translate } from 'react-i18next';
import Grid from '@material-ui/core/Grid';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import FormLabel from '@material-ui/core/FormLabel';
import FormControl from '@material-ui/core/FormControl';
import FormHelperText from '@material-ui/core/FormHelperText';
import Checkbox from '@material-ui/core/Checkbox';
import Radio from '@material-ui/core/Radio';
import Crop from 'model/genesys/Crop';
interface ICropSelectorProps extends React.ClassAttributes<any> {
t: any;
crops: Crop[];
fields?: any;
label: string;
input?: any;
single?: boolean;
}
const handleCheckboxChange = (fields, code) => () => {
const index = fields.getAll() ? fields.getAll().indexOf(code) : -1;
if (index === -1) {
fields.push(code);
} else {
fields.remove(index);
}
};
const handleRadioButtonChange = (input, code) => () => {
input.onChange(code);
};
const renderCheckbox = (fields, code) => (
<Checkbox
checked={ fields.getAll() && fields.getAll().indexOf(code) !== -1 }
onChange={ handleCheckboxChange(fields, code) }
value={ code }
/>
);
const renderRadioButton = (input, code) => (
<Radio
checked={ input.value === code }
onChange={ handleRadioButtonChange(input, code) }
value={ code }
/>
);
const CropSelector = ({t, crops, label, single, fields, input}: ICropSelectorProps) => crops && (
<FormControl fullWidth>
<FormLabel>{ label }</FormLabel>
<FormHelperText>{ t('crop.public.c.cropSelector.helper') }</FormHelperText>
<Grid container>
{
crops.sort((a, b) => a.name.localeCompare(b.name)).map((crop: Crop) => (
<Grid item key={ crop.shortName } xs={ 6 } md={ 4 } lg={ 3 } xl={ 2 }>
<FormControlLabel
control={
single ? renderRadioButton(input, crop.shortName)
: renderCheckbox(fields, crop.shortName)
}
label={ crop.name }
/>
</Grid>
))
}
</Grid>
</FormControl>
);
const mapStateToProps = (state) => ({
crops: state.crop.public.list,
});
export default connect(mapStateToProps, null)(translate()(CropSelector));
import { push } from 'react-router-redux';
// Actions
import { addFilterCode } from 'actions/filterCode';
import navigateTo from 'actions/navigation';
// Constants
import { DASHBOARD_REMOVE_DATASET, DASHBOARD_RECEIVE_DATASET_PAGE, CREATE_DATASET, DASHBOARD_APPEND_DATASET_PAGE,
RECEIVE_DATASET, DASHBOARD_APPEND_ACCESSIONS_PAGE, DASHBOARD_RECEIVE_ACCESSIONS_PAGE } from 'datasets/constants';
// Models
import Dataset from 'model/catalog/Dataset';
import { PublishState } from 'model/common.model';
import Page from 'model/Page';
import FilteredPage from 'model/FilteredPage';
import { AccessionRef } from 'model/accession/AccessionRef';
// Service
import DatasetService from 'service/catalog/DatasetService';
// Utility
import { log } from 'utilities/debug';
import { dereferenceReferences } from 'utilities';
const removeDataset = (dataset: Dataset) => ({
type: DASHBOARD_REMOVE_DATASET, payload: dataset,
});
const receiveDataset = (dataset: Dataset) => ({
type: RECEIVE_DATASET, payload: dataset,
});
const appendDatasetPage = (paged: Page<Dataset>) => ({
type: DASHBOARD_APPEND_DATASET_PAGE,
payload: { paged },
});
const receiveDatasetPage = (paged: Page<Dataset>) => ({