Commit 7bc82b10 authored by Matija Obreza's avatar Matija Obreza
Browse files

Revised code for Controlled Vocabulary

parent 5e1a9fbc
......@@ -3,7 +3,7 @@ import { SubmissionError } from 'redux-form';
import { VocabularyService } from 'service/VocabularyService';
import {
CREATE_VOCABULARY, GET_VOCABULARY, RECEIVE_VOCABULARY, RECEIVE_VOCABULARIES, RECEIVE_MY_VOCABULARYLIST,
CREATE_VOCABULARY, RECEIVE_VOCABULARY, RECEIVE_VOCABULARIES, RECEIVE_MY_VOCABULARYLIST,
} from 'constants/vocabulary';
import { IReducerAction, Page } from 'model/common.model';
......@@ -24,15 +24,18 @@ const receiveVocabulary = (vocabulary: Vocabulary): IReducerAction => ({
// Create a new record
export const createVocabulary = () => (dispatch) => {
console.log('Create new vocabulary');
dispatch({ type: CREATE_VOCABULARY });
// return dispatch(push(`/vocabulary/edit`));
return Promise.all([
dispatch({ type: CREATE_VOCABULARY }),
dispatch(push(`/vocabulary/create`)),
]);
};
// Delete a record
export const deleteVocabulary = (vocabulary: Vocabulary) => (dispatch, getState) => {
return VocabularyService.deleteVocabulary(getState().login.access_token, vocabulary)
.then((vocabulary) => {
dispatch(push(`/vocabularies`));
dispatch(receiveVocabularyPage(null));
dispatch(push(`/vocabulary`));
})
.catch((error) => {
console.log('Error', error);
......@@ -44,8 +47,6 @@ export const loadVocabulary = (uuid: string) => (dispatch, getState) => {
console.log('Loading vocabulary', uuid);
const token = getState().login.access_token;
dispatch({ type: GET_VOCABULARY, payload: uuid });
return VocabularyService.getVocabulary(token, uuid)
// receive the current vocabulary
.then((vocabulary) => {
......@@ -57,8 +58,10 @@ export const loadVocabulary = (uuid: string) => (dispatch, getState) => {
// Edit an existing vocabulary
export const editVocabulary = (uuid: string) => (dispatch, getState) => {
dispatch(loadVocabulary(uuid));
dispatch(push(`/vocabulary/${uuid}/edit`));
return Promise.all([
dispatch(loadVocabulary(uuid)),
dispatch(push(`/vocabulary/${uuid}/edit`)),
]);
};
const showVocabulary = (uuid: string) => (dispatch) => {
......@@ -103,5 +106,5 @@ const saveVocabulary = (vocabulary: Vocabulary) => (dispatch, getState) => {
};
export {
listMyVocabularies, listVocabularies, receiveVocabulary, saveVocabulary, showVocabulary,
listMyVocabularies, listVocabularies, saveVocabulary, showVocabulary,
};
// Single record
export const CREATE_VOCABULARY = 'App/Vocabulary/CREATE_VOCABULARY';
export const VOCABULARY_FORM = 'Form/Vocabulary/VOCABULARY_FORM';
export const GET_VOCABULARY = 'App/Vocabulary/GET_VOCABULARY';
export const RECEIVE_VOCABULARY = 'App/Vocabulary/RECEIVE_VOCABULARY';
// Listing
......
......@@ -57,6 +57,9 @@ class LeftMenu extends React.Component<ILeftMenuProps, any> {
<ListItem button>
<Link to="/datasets" >Datasets</Link>
</ListItem>
<ListItem button>
<Link to="/vocabulary" >Controlled vocabularies</Link>
</ListItem>
</div>
</Drawer>
</div>
......
......@@ -61,6 +61,7 @@ class UserMenuComponent extends React.Component<IUserMenuComponentProps, any> {
>
<Link to="/dashboard"><MenuItem >My Dashboard</MenuItem></Link>
<Link to="/crops"><MenuItem>Crops</MenuItem></Link>
<Link to="/vocabulary"><MenuItem>Controlled vocabularies</MenuItem></Link>
<Link to="/gui"><MenuItem>UI Tests</MenuItem></Link>
<MenuItem onClick={ logoutRequest } >Logout</MenuItem>
</Menu>
......
......@@ -5,12 +5,13 @@ import { withStyles } from 'material-ui/styles';
import Grid from 'material-ui/Grid';
import Button from 'material-ui/Button';
import PaginationComponent from 'ui/common/pagination';
import { listVocabularies, createVocabulary } from 'actions/vocabulary';
import { Vocabulary, IVocabularyFilter } from 'model/vocabulary.model';
import { Page, Pagination } from 'model/common.model';
import PaginationComponent from 'ui/common/pagination';
import ContentHeaderWithButton from 'ui/common/heading/ContentHeaderWithButton';
import VocabularyCard from './c/VocabularyCard';
import { Page, Pagination } from 'model/common.model';
const styles = (theme) => ({
root: {
......@@ -22,9 +23,6 @@ const styles = (theme) => ({
});
interface IBrowsePageProps extends React.ClassAttributes<any> {
router: any;
classes: any;
pagination?: Pagination<IVocabularyFilter>;
paged?: Page<Vocabulary>;
listVocabularies: any;
......@@ -36,7 +34,7 @@ const sortOptions = {
lastModifiedDate: { label: 'Last modified', dir: 'DESC' },
};
class BrowsePage extends React.Component<IBrowsePageProps, any> {
class BrowsePage extends React.Component<IBrowsePageProps & any, any> {
protected static needs = [
({ location: { query: { p: pageCurrent, l: pageSize, s: pageSort, d: pageDir } } }) => listVocabularies(pageCurrent, pageSize, pageSort, {}, pageDir),
......@@ -72,7 +70,7 @@ class BrowsePage extends React.Component<IBrowsePageProps, any> {
public render() {
const {classes, paged, createVocabulary} = this.props;
return paged && (
return paged && paged.content && (
<div className={ classes.root }>
<ContentHeaderWithButton title="What do you want to do?" buttons={ <Button raised onClick={ createVocabulary }>Create vocabulary</Button> } />
<Grid container>
......
......@@ -46,7 +46,11 @@ class DisplayPage extends React.Component<IDisplayPageProps, any> {
}
public render() {
const {classes, vocabulary} = this.props;
const {classes, uuid, vocabulary} = this.props;
if (uuid && vocabulary && vocabulary.uuid !== uuid) {
return null;
}
return vocabulary && (
<div>
......@@ -67,7 +71,7 @@ class DisplayPage extends React.Component<IDisplayPageProps, any> {
</Card>
</Grid>
{ vocabulary.terms && (
{ vocabulary.terms && vocabulary.terms.length > 0 && (
<Paper className={ classes.form }>
{ vocabulary.terms.map((term) => (
<div key={ term.code }>{ term.code } &rarr; { term.title }</div>
......
......@@ -6,97 +6,123 @@ import Grid from 'material-ui/Grid';
import Paper from 'material-ui/Paper';
import {loadMyPartners} from 'actions/partner';
import {loadVocabulary, saveVocabulary} from 'actions/vocabulary';
import {loadVocabulary, saveVocabulary, deleteVocabulary} from 'actions/vocabulary';
import confirm from 'utilities/confirmAlert';
import {Vocabulary} from 'model/vocabulary.model';
import {Partner} from 'model/partner.model';
import VocabularyForm from './c/VocabularyForm';
interface IVocabularyEditPageProps extends React.ClassAttributes<any> {
classes: any;
uuid?: string;
classes: any;
uuid?: string;
loadMyPartners: () => void;
myPartners: Partner[];
loadMyPartners: () => void;
myPartners: Partner[];
vocabulary?: Vocabulary;
loadVocabulary: (uuid: string) => void;
saveVocabulary: (vocabulary: Vocabulary) => void;
vocabulary?: Vocabulary;
loadVocabulary: (uuid: string) => void;
saveVocabulary: (vocabulary: Vocabulary) => void;
deleteVocabulary: (vocabulary: Vocabulary) => void;
}
const styles = (theme) => ({
contentContainer: {
backgroundColor: '#E8E5E0',
padding: '1rem',
},
form: {
padding: '20px',
margin: '0 0 1rem 0',
},
contentContainer: {
backgroundColor: '#E8E5E0',
padding: '1rem',
},
form: {
padding: '20px',
margin: '0 0 1rem 0',
},
});
class VocabularyEditPage extends React.Component<IVocabularyEditPageProps, any> {
protected static needs = [
({params: {uuid}}) => loadVocabulary(uuid),
loadMyPartners,
];
public componentDidMount() {
const {vocabulary, myPartners, loadMyPartners, loadVocabulary, uuid} = this.props;
if (!myPartners || myPartners.length === 0) {
loadMyPartners();
}
if (uuid && (!vocabulary || vocabulary.uuid !== uuid)) {
loadVocabulary(uuid);
}
}
public onSave = (updatedVocabulary: Vocabulary) => {
const {saveVocabulary} = this.props;
if (updatedVocabulary.uuid && updatedVocabulary.version) {
delete updatedVocabulary.owner;
}
saveVocabulary(updatedVocabulary);
}
public render() {
const {classes, uuid, myPartners} = this.props;
let {vocabulary} = this.props;
if (!vocabulary && !uuid) {
vocabulary = new Vocabulary();
if (myPartners && myPartners.length > 0) {
vocabulary.owner = myPartners.length[0];
}
}
return vocabulary && (
<Grid container className={ classes.contentContainer }>
<Grid item xs={ 12 }>
<Paper className={ classes.form }>
<VocabularyForm initialValues={ vocabulary } onSubmit={ this.onSave }/>
</Paper>
</Grid>
</Grid>
);
}
protected static needs = [
({params: {uuid}}) => loadVocabulary(uuid),
loadMyPartners,
];
public componentDidMount() {
const {uuid, vocabulary, loadVocabulary, myPartners, loadMyPartners} = this.props;
if (!myPartners || myPartners.length === 0) {
loadMyPartners();
}
if (uuid && (!vocabulary || (vocabulary && vocabulary.uuid !== uuid))) {
console.log('Reloading vocabulary', uuid, vocabulary);
loadVocabulary(uuid);
}
}
public componentWillReceiveProps(nextProps) {
const {uuid, vocabulary} = nextProps;
if (uuid && (!vocabulary || (vocabulary && vocabulary.uuid !== uuid))) {
console.log('Reloading vocabulary', uuid, vocabulary);
loadVocabulary(uuid);
}
}
public onSave = (updatedVocabulary: Vocabulary) => {
const {saveVocabulary} = this.props;
if (updatedVocabulary.uuid && updatedVocabulary.version) {
delete updatedVocabulary.owner;
}
saveVocabulary(updatedVocabulary);
}
private onDelete = () => {
const { vocabulary, deleteVocabulary } = this.props;
confirm(<span>Delete <b>{ vocabulary.title }</b>?</span>, {
// description: `Note,.`,
confirmLabel: 'Delete',
abortLabel: 'Cancel',
}).then(() => {
deleteVocabulary(vocabulary);
});
}
public render() {
const {classes, uuid, myPartners} = this.props;
let {vocabulary} = this.props;
if (uuid && (vocabulary && vocabulary.uuid !== uuid)) {
console.log('Not displaying');
return null;
}
if (!vocabulary && !uuid) {
vocabulary = new Vocabulary();
}
return vocabulary && (
<Grid container className={ classes.contentContainer }>
<Grid item xs={ 12 }>
<Paper className={ classes.form }>
<VocabularyForm initialValues={ vocabulary } partners={ myPartners } onSubmit={ this.onSave } onDelete={ this.onDelete } />
</Paper>
</Grid>
</Grid>
);
}
}
const mapStateToProps = (state, ownProps) => ({
uuid: ownProps.params.uuid,
myPartners: state.partner.myPartners,
vocabulary: state.vocabulary.currentVocabulary,
uuid: ownProps.params.uuid,
myPartners: state.partner.myPartners,
vocabulary: state.vocabulary.currentVocabulary,
});
const mapDispatchToProps = (dispatch) => bindActionCreators({
loadMyPartners,
loadVocabulary,
saveVocabulary,
loadMyPartners,
loadVocabulary,
saveVocabulary,
deleteVocabulary,
}, dispatch);
const styled = withStyles(styles)(VocabularyEditPage);
......
import * as React from 'react';
import {Link} from 'react-router';
import Card, {CardHeader, CardContent} from 'material-ui/Card';
import Card, {CardHeader, CardContent, CardActions} from 'material-ui/Card';
import Divider from 'material-ui/Divider';
import {Vocabulary} from 'model/vocabulary.model';
import Markdown from 'ui/common/markdown';
import Button from 'material-ui/Button';
const VocabularyCard = ({vocabulary, className = ''}: { vocabulary: Vocabulary, className: string }) => vocabulary && (
const VocabularyCard = ({vocabulary, className = ''}: { vocabulary: Vocabulary, className?: string }) => vocabulary && (
<Card className={ className }>
<CardHeader title={
vocabulary._permissions.write ?
<Link to={ `/vocabulary/${vocabulary.uuid}/edit` }>{ vocabulary.title }</Link>
: <span>{ vocabulary.title }</span>
}/>
<CardHeader title={ <Link to={ `/vocabulary/${vocabulary.uuid}` }>{ vocabulary.title }</Link> } />
<Divider/>
<CardContent>
{ vocabulary.description && vocabulary.description.substring(0, 200) !== '' && (
<CardContent>
<Markdown source={ vocabulary.description.substring(0, 200) + '...' } />
</CardContent>
{ vocabulary.description &&
<CardContent>
{ vocabulary.description.substring(0, 200) !== '' && (
<Markdown source={ vocabulary.description.substring(0, 200) + '...' } />
) }
</CardContent>
</CardContent>
}
<CardActions>
<Link to={ `/vocabulary/${vocabulary.uuid}` }><Button>View details</Button></Link>
{ vocabulary._permissions.write &&
<Link to={ `/vocabulary/${vocabulary.uuid}/edit` }><Button>Edit</Button></Link>
}
</CardActions>
</Card>
);
......
import * as React from 'react';
import { connect } from 'react-redux';
import {Field, reduxForm} from 'redux-form';
import {Link} from 'react-router';
import {VOCABULARY_FORM} from 'constants/vocabulary';
import { VocabularyTerm } from 'model/vocabulary.model';
......@@ -10,6 +11,7 @@ import {MarkdownField} from 'ui/common/markdown';
import Heading from 'ui/common/heading';
import ItemsEditor from 'ui/common/ItemsEditor';
import SelectPartner from 'ui/catalog/partner/SelectPartner';
import Button from 'material-ui/Button';
import Grid from 'material-ui/Grid';
......@@ -25,7 +27,7 @@ const TermEditor = (member, index, fields) => (
class VocabularyForm extends React.Component<any, any> {
public render() {
const {error, handleSubmit, initialValues} = this.props;
const {error, handleSubmit, initialValues, onDelete, partners} = this.props;
const onAddMember = () => {
console.log('Adding new term');
......@@ -45,6 +47,12 @@ class VocabularyForm extends React.Component<any, any> {
<form onSubmit={ handleSubmit }>
<Heading title="Vocabulary details" level={ 2 } />
<Field required name="owner"
editable={ ! (initialValues.uuid && initialValues.version) }
label="Owner of the vocabulary" placeholder="Partner"
partners={ partners }
component={ SelectPartner }
/>
<Field required name="title"
label="Vocabulary title" placeholder="Color of magic"
component={ TextField }
......@@ -69,8 +77,13 @@ class VocabularyForm extends React.Component<any, any> {
<Heading title="Vocabulary terms" level={ 3 }/>
<ItemsEditor name="terms" itemLabel="Vocabulary term" addItem={ onAddMember } removeItem={ onRemoveMember } component={ TermEditor } />
<div>{ error && <strong>{ error }</strong> }</div>
{ error && (
<div className="error">{ error }</div>
) }
<Button raised type="submit" >Save changes</Button>
{ (initialValues._permissions && initialValues._permissions.delete) && <Button onClick={ onDelete } type="button">Delete</Button> }
<Link to="/vocabulary"><Button type="button">Back to list</Button></Link>
</form>
</div>
);
......
......@@ -122,8 +122,8 @@ export default(
<Route component={ AuthorizedRouteComponent } authorities={ [ROLE_ADMINISTRATOR] }>
<Route path="create" component={ VocabularyEditPage }/>
<Route path=":uuid/edit" component={ VocabularyEditPage }/>
<Route path=":uuid" component={ VocabularyDisplayPage }/>
</Route>
<Route path=":uuid" component={ VocabularyDisplayPage }/>
</Route>
</Route>
......
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