Commit 5a40f946 authored by Viacheslav Pavlov's avatar Viacheslav Pavlov
Browse files

Merge branch '196-add-user-button' into 'master'

Resolve "Add user button"

Closes #199 and #196

See merge request genesys-pgr/genesys-ui!210
parents f0a6629b a7d0bcd6
......@@ -783,11 +783,11 @@
"p": {
"browse": {
"title": "Browse articles",
"create": "Create new article"
"article": "Article"
},
"browseActivityPost": {
"title": "Browse activity posts",
"create": "Create new activity post"
"activityPost": "Activity post"
},
"edit": {
"articleSaved": "Article saved",
......@@ -863,8 +863,7 @@
},
"browse": {
"title": "Crop list",
"subTitle": "Genesys crops directory",
"createCrop": "Create crop"
"subTitle": "Genesys crops directory"
}
}
},
......@@ -1647,11 +1646,11 @@
"title": "KPI management"
},
"dimensionDialog": {
"button": "Add dimension",
"name": "dimension",
"title": "Dimension info"
},
"executionDialog": {
"button": "Add execution",
"name": "execution",
"title": "Execution info"
},
"executionDisplay": {
......@@ -1664,7 +1663,7 @@
"nothingToLoad": "No runs match entered date"
},
"parameterDialog": {
"button": "Add parameter",
"name": "parameter",
"title": "Parameter info"
}
}
......@@ -1778,7 +1777,7 @@
},
"repositoryBrowser": {
"viewGallery": "View gallery",
"createGallery": "Create gallery",
"gallery": "gallery",
"createGalleryAlert": "Image gallery at {{folderPath, string}} could not be created.",
"deleteFolder": "Delete folder",
"deleteFolderAlert": "Folder {{folderPath, string}} could not be deleted.",
......@@ -1792,7 +1791,7 @@
},
"createFolder": {
"createDialogTitle": "Create new folder",
"createBtn": "Create new folder"
"folder": "folder"
}
},
"c": {
......@@ -2195,6 +2194,7 @@
}
},
"common": {
"modelName": "User",
"email": "Email",
"emailAddress": "E-mail address",
"oAuthClientModelName": "OAuth client",
......@@ -2300,7 +2300,6 @@
},
"p": {
"browse": {
"create": "Create vocabulary",
"title": "Browse vocabularies",
"update": "Update vocabularies"
},
......
......@@ -26,11 +26,11 @@
"p": {
"browse": {
"title": "Browse articles",
"create": "Create new article"
"article": "Article"
},
"browseActivityPost": {
"title": "Browse activity posts",
"create": "Create new activity post"
"activityPost": "Activity post"
},
"edit": {
"articleSaved": "Article saved",
......
import * as React from 'react';
import { Link } from 'react-router-dom';
import { translate } from 'react-i18next';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
......@@ -18,8 +17,8 @@ import PagedLoader from 'ui/common/PagedLoader';
import PageTitle from 'ui/common/PageTitle';
import ActivityPostFilters from './c/ActivityPostFilters';
import ContentHeaderWithButton from 'ui/common/heading/ContentHeaderWithButton';
import Button from '@material-ui/core/Button/Button';
import ActivityPostCard from './c/ActivityPostCard';
import CreateNewButton from 'ui/common/buttons/CreateNewButton';
class ActivityPostBrowsePage extends BrowsePageTemplate<ActivityPost> {
......@@ -41,11 +40,6 @@ class ActivityPostBrowsePage extends BrowsePageTemplate<ActivityPost> {
<PageTitle title={ t('cms.admin.p.browseActivityPost.title') }/>
<ContentHeaderWithButton
title={ t('cms.admin.p.browseActivityPost.title') }
buttons={
<Link to="/admin/content/activity-post/edit">
<Button variant="contained">{ t('cms.admin.p.browseActivityPost.create') }</Button>
</Link>
}
/>
<PageContents className="pt-1rem container-spacing-horizontal">
{ !paged ? <Loading/> :
......@@ -57,6 +51,10 @@ class ActivityPostBrowsePage extends BrowsePageTemplate<ActivityPost> {
/>
}
</PageContents>
<CreateNewButton
title="cms.admin.p.browse.activityPost"
path="/admin/content/activity-post/edit"
/>
</PageLayout>
);
}
......
......@@ -107,7 +107,7 @@ class ActivityPostEditPage extends React.Component<IArticleEditPageProps, any> {
return (
<div>
<PageTitle title={ activityPost.title.split(/<\w>|<\/\w>/).join('') }/>
<PageTitle title={ activityPost.title ? activityPost.title.split(/<\w>|<\/\w>/).join('') : t('cms.admin.p.edit.activityPostPageTitle') }/>
<ContentHeaderWithButton
title={ <span dangerouslySetInnerHTML={ { __html: activityPost.title } }/> }
classes={ { subHeader: classes.customSubHeader } }
......
import * as React from 'react';
import { Link } from 'react-router-dom';
import { translate } from 'react-i18next';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
......@@ -13,13 +12,13 @@ import Article from 'model/cms/Article';
// UI
import BrowsePageTemplate, { IBrowsePageProps } from 'ui/pages/_base/BrowsePage';
import PageLayout, { PageContents } from 'ui/layout/PageLayout';
import ContentHeader from 'ui/common/heading/ContentHeader';
import Loading from 'ui/common/Loading';
import PagedLoader from 'ui/common/PagedLoader';
import ArticleFilters from './c/ArticleFilters';
import ArticleCard from './c/ArticleCard';
import ContentHeaderWithButton from 'ui/common/heading/ContentHeaderWithButton';
import CreateNewButton from 'ui/common/buttons/CreateNewButton';
import PageTitle from 'ui/common/PageTitle';
import Button from '@material-ui/core/Button/Button';
class BrowsePage extends BrowsePageTemplate<Article> {
......@@ -39,14 +38,7 @@ class BrowsePage extends BrowsePageTemplate<Article> {
<ArticleFilters initialValues={ paged && paged.filter || {} } onSubmit={ this.myApplyFilters }/>
}>
<PageTitle title={ t('cms.admin.p.browse.title') }/>
<ContentHeaderWithButton
title={ t('cms.admin.p.browse.title') }
buttons={
<Link to="/admin/content/edit">
<Button variant="contained">{ t('cms.admin.p.browse.create') }</Button>
</Link>
}
/>
<ContentHeader title={ t('cms.admin.p.browse.title') }/>
<PageContents className="pt-1rem container-spacing-horizontal">
{ !paged ? <Loading/> :
<PagedLoader
......@@ -57,6 +49,10 @@ class BrowsePage extends BrowsePageTemplate<Article> {
/>
}
</PageContents>
<CreateNewButton
title="cms.admin.p.browse.activityPost"
path="/admin/content/edit"
/>
</PageLayout>
);
}
......
......@@ -21,8 +21,7 @@
},
"browse": {
"title": "Crop list",
"subTitle": "Genesys crops directory",
"createCrop": "Create crop"
"subTitle": "Genesys crops directory"
}
}
},
......
......@@ -14,10 +14,9 @@ import PageLayout, { PageContents } from 'ui/layout/PageLayout';
import ContentHeader from 'ui/common/heading/ContentHeader';
import CropCard from 'crop/ui/c/CropCard';
import GridContainer from 'ui/layout/GridContainer';
import ContentHeaderWithButton from 'ui/common/heading/ContentHeaderWithButton';
import ActionButton from 'ui/common/buttons/ActionButton';
import Authorize from 'ui/common/authorized/Authorize';
import PageTitle from 'ui/common/PageTitle';
import CreateNewButton from 'ui/common/buttons/CreateNewButton';
interface IBrowsePageProps extends React.ClassAttributes<any> {
crops: CropDetails[];
......@@ -39,20 +38,17 @@ class BrowsePage extends React.Component<IBrowsePageProps> {
<PageLayout>
<PageTitle title={ t('crop.public.p.browse.title') } />
<ContentHeader title={ t('crop.public.p.browse.title') } subTitle={ t('crop.public.p.browse.subTitle') } />
<Authorize role="ROLE_ADMINISTRATOR">
<ContentHeaderWithButton
isSecondary
buttons={
<div>
<ActionButton title={ t('crop.public.p.browse.createCrop') } action={ this.addNewCropHandle }/>
</div>
}/>
</Authorize>
<PageContents className="pt-1rem">
<GridContainer>
{ crops && crops.sort((a, b) => a.name.localeCompare(b.name)).map((crop) => <CropCard key={ crop.shortName } crop={ crop } compact />) }
</GridContainer>
</PageContents>
<Authorize role="ROLE_ADMINISTRATOR">
<CreateNewButton
title="crop.common.modelName"
action={ this.addNewCropHandle }
/>
</Authorize>
</PageLayout>
);
}
......
......@@ -11,6 +11,8 @@ import {
ADMIN_RECEIVE_EXEC_RUNS, ADMIN_APPEND_EXEC_RUNS,
ADMIN_RECEIVE_EXEC_DET, ADMIN_REMOVE_DIM,
ADMIN_REMOVE_PARAM, ADMIN_RECEIVE_EXEC_CHANGES,
ADMIN_TOGGLE_PARAM_MODAL, ADMIN_TOGGLE_DIM_MODAL,
ADMIN_TOGGLE_EXEC_MODAL,
} from 'kpi/constants';
// model
......@@ -94,6 +96,10 @@ export const loadMoreExecutionRuns = (executionName: string, page: number) => (d
});
};
export const toggleExecutionModal = (open: boolean): IReducerAction => ({
type: ADMIN_TOGGLE_EXEC_MODAL, payload: open,
});
export const listDimensions = (page: IPageRequest) => (dispatch) => {
KpiService.listDimensions(page).then((data) => {
dispatch(receiveDimensions(ensureDimensionType(data)));
......@@ -148,10 +154,14 @@ const removeDimension = (dimension: Dimension<any>): IReducerAction => ({
type: ADMIN_REMOVE_DIM, payload: dimension,
});
const receiveDimension = (dimension: Dimension<any>): IReducerAction => ({
export const receiveDimension = (dimension: Dimension<any>): IReducerAction => ({
type: ADMIN_RECEIVE_DIM, payload: dimension,
});
export const toggleDimensionModal = (open: boolean): IReducerAction => ({
type: ADMIN_TOGGLE_DIM_MODAL, payload: open,
});
export const listParameters = (page: IPageRequest) => (dispatch) => {
KpiService.listParameters(page).then((data) => {
dispatch(receiveParameters(data));
......@@ -176,7 +186,7 @@ export const deleteParameter = (parameter: KPIParameter) => (dispatch) => {
.then((parameter) => dispatch(removeParameter(parameter)));
};
const receiveParameter = (parameter: KPIParameter): IReducerAction => ({
export const receiveParameter = (parameter: KPIParameter): IReducerAction => ({
type: ADMIN_RECEIVE_PARAM, payload: parameter,
});
......@@ -193,3 +203,7 @@ export const loadExecutionChanges = (name, {days = null, to = null, from = null}
return KpiService.executionRunDiffs(name, days, from, to)
.then((changes) => dispatch(receiveExecutionChanges(changes)));
};
export const toggleParameterModal = (open: boolean): IReducerAction => ({
type: ADMIN_TOGGLE_PARAM_MODAL, payload: open,
});
......@@ -21,12 +21,15 @@ export const ADMIN_RECEIVE_EXEC_LASTRUN = 'kpi/admin/RECEIVE_LASTRUN';
export const ADMIN_RECEIVE_EXEC_RUNS = 'kpi/admin/RECEIVE_EXEC_RUNS';
export const ADMIN_APPEND_EXEC_RUNS = 'kpi/admin/APPEND_EXEC_RUNS';
export const ADMIN_RECEIVE_EXEC_CHANGES = 'kpi/admin/RECEIVE_EXEC_CHANGES';
export const ADMIN_TOGGLE_EXEC_MODAL = 'kpi/admin/TOGGLE_EXEC_MODAL';
export const ADMIN_RECEIVE_PARAMS = 'kpi/admin/RECEIVE_PARAMS';
export const ADMIN_RECEIVE_PARAM = 'kpi/admin/RECEIVE_PARAM';
export const ADMIN_REMOVE_PARAM = 'kpi/admin/REMOVE_PARAM';
export const ADMIN_TOGGLE_PARAM_MODAL = 'kpi/admin/TOGGLE_PARAM_MODAL';
export const ADMIN_RECEIVE_DIM = 'kpi/admin/RECEIVE_DIM';
export const ADMIN_REMOVE_DIM = 'kpi/admin/REMOVE_DIM';
export const ADMIN_RECEIVE_DIMS = 'kpi/admin/RECEIVE_DIMS';
export const ADMIN_TOGGLE_DIM_MODAL = 'kpi/admin/TOGGLE_DIM_MODAL';
......@@ -15,6 +15,9 @@ import {
ADMIN_REMOVE_DIM,
ADMIN_REMOVE_EXEC,
ADMIN_REMOVE_PARAM,
ADMIN_TOGGLE_PARAM_MODAL,
ADMIN_TOGGLE_DIM_MODAL,
ADMIN_TOGGLE_EXEC_MODAL,
} from 'kpi/constants';
import Execution from 'model/kpi/Execution';
import Page from 'model/Page';
......@@ -26,28 +29,34 @@ const INITIAL_STATE: {
page: Page<Execution>,
details: Execution,
changes: any,
modalIsOpen: boolean,
},
dim: {
page: Page<Dimension<any>>,
details: Dimension<any>,
modalIsOpen: boolean,
},
param: {
page: Page<KPIParameter>,
details: KPIParameter,
modalIsOpen: boolean,
},
} = {
exec: {
page: {},
details: new Execution(),
changes: null,
modalIsOpen: false,
},
dim: {
page: null,
details: null,
modalIsOpen: false,
},
param: {
page: null,
details: null,
modalIsOpen: false,
},
};
......@@ -84,7 +93,6 @@ export default function admin(state = INITIAL_STATE, action: IReducerAction) {
details: {
execution: {$set: execution},
},
changes: {$set: null},
},
});
} else {
......@@ -153,6 +161,13 @@ export default function admin(state = INITIAL_STATE, action: IReducerAction) {
},
});
}
case ADMIN_TOGGLE_EXEC_MODAL: {
return update(state, {
exec: {
modalIsOpen: {$set: action.payload},
},
});
}
case ADMIN_RECEIVE_DIMS: {
return update(state, {
dim: { page: { $set: action.payload } },
......@@ -207,6 +222,13 @@ export default function admin(state = INITIAL_STATE, action: IReducerAction) {
},
});
}
case ADMIN_TOGGLE_DIM_MODAL: {
return update(state, {
dim: {
modalIsOpen: {$set: action.payload},
},
});
}
case ADMIN_RECEIVE_PARAMS: {
return update(state, {
param: { page: { $set: action.payload } },
......@@ -270,6 +292,13 @@ export default function admin(state = INITIAL_STATE, action: IReducerAction) {
});
}
case ADMIN_TOGGLE_PARAM_MODAL: {
return update(state, {
param: {
modalIsOpen: {$set: action.payload},
},
});
}
default:
return state;
}
......
......@@ -88,11 +88,11 @@
"title": "KPI management"
},
"dimensionDialog": {
"button": "Add dimension",
"name": "dimension",
"title": "Dimension info"
},
"executionDialog": {
"button": "Add execution",
"name": "execution",
"title": "Execution info"
},
"executionDisplay": {
......@@ -105,7 +105,7 @@
"nothingToLoad": "No runs match entered date"
},
"parameterDialog": {
"button": "Add parameter",
"name": "parameter",
"title": "Parameter info"
}
}
......
......@@ -5,7 +5,16 @@ import { translate } from 'react-i18next';
// import { parse } from 'query-string';
// Actions
import { listDimensions, listExecutions, listParameters } from 'kpi/actions/admin';
import {
clearDimDetails,
clearParameterDetails,
listDimensions,
listExecutions,
listParameters,
toggleParameterModal,
toggleDimensionModal,
toggleExecutionModal,
} from 'kpi/actions/admin';
// Models
import Page from 'model/Page';
......@@ -26,6 +35,10 @@ import ExecutionDialog from './ExecutionDialog';
import ParameterCard from './c/ParameterCard';
import DimensionCard from './c/DimensionCard';
import ExecutionCard from './c/ExecutionCard';
import CreateNewButton from 'ui/common/buttons/CreateNewButton';
import ParameterIcon from '@material-ui/icons/Code';
import DimensionIcon from '@material-ui/icons/ShowChart';
import ExecutionIcon from '@material-ui/icons/ListAlt';
interface IDashboardProps extends React.ClassAttributes<any> {
classes: any;
......@@ -33,8 +46,13 @@ interface IDashboardProps extends React.ClassAttributes<any> {
execs: Page<Execution>;
listExecutions: any;
toggleExecutionModal: (open: boolean) => void;
clearParameterDetails: () => void;
toggleParameterModal: (open: boolean) => void;
params: Page<KPIParameter>;
listParameters: any;
clearDimDetails: () => void;
toggleDimensionModal: (open: boolean) => void;
dims: Page<Dimension<any>>;
listDimensions: any;
}
......@@ -62,19 +80,49 @@ class Dashboard extends React.Component<IDashboardProps, any> {
}
}
public openParameterDialog() {
const { clearParameterDetails, toggleParameterModal } = this.props;
clearParameterDetails();
toggleParameterModal(true);
}
public openDimensionDialog() {
const { clearDimDetails, toggleDimensionModal } = this.props;
clearDimDetails();
toggleDimensionModal(true);
}
public openExecutionDialog() {
this.props.toggleExecutionModal(true);
}
public render() {
const { t, execs, params, dims } = this.props;
const stillLoading = ! execs && ! params && ! dims;
const addActions = [
{
title: 'kpi.admin.p.parameterDialog.name',
action: () => this.openParameterDialog(),
icon: <ParameterIcon/>,
},
{
title: 'kpi.admin.p.dimensionDialog.name',
action: () => this.openDimensionDialog(),
icon: <DimensionIcon/>,
},
{
title: 'kpi.admin.p.executionDialog.name',
action: () => this.openExecutionDialog(),
icon: <ExecutionIcon/>,
},
];
return (
<div>
<PageTitle title={ t(`kpi.admin.p.dashboard.title`) }/>
<ContentHeaderWithButton title={ t(`kpi.admin.p.dashboard.title`) } buttons={ <div>
<ParameterDialog/>
<DimensionDialog/>
<ExecutionDialog/>
</div> }/>
<ContentHeaderWithButton title={ t(`kpi.admin.p.dashboard.title`) }/>
<PageContents className="pt-1rem">
<Grid container spacing={ 0 }>
<Grid item xs={ 12 }>
......@@ -107,6 +155,10 @@ class Dashboard extends React.Component<IDashboardProps, any> {
</Grid>
</Grid>
</PageContents>
<ParameterDialog/>
<DimensionDialog/>
<ExecutionDialog execution={ null }/>
<CreateNewButton actions={ addActions } addTitle/>
</div>
);
}
......@@ -122,7 +174,13 @@ const mapDispatchToProps = (dispatch) => bindActionCreators({
listExecutions,
listParameters,
listDimensions,
clearParameterDetails,
clearDimDetails,
toggleParameterModal,
toggleDimensionModal,
toggleExecutionModal,
}, dispatch);
export default connect(mapStateToProps, mapDispatchToProps)((translate()(Dashboard)));
......@@ -4,104 +4,70 @@ import { bindActionCreators } from 'redux';
import {translate} from 'react-i18next';
// actions
import {clearDimDetails, deleteDimension, loadDimension, saveDimension} from 'kpi/actions/admin';
import {
clearDimDetails,
deleteDimension,
loadDimension,
saveDimension,
toggleDimensionModal,
} from 'kpi/actions/admin';
// model
import Dimension from 'model/kpi/Dimension';
import {withStyles} from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';
import Dialog from '@material-ui/core/Dialog';
import DialogContent from '@material-ui/core/DialogContent';
import DialogTitle from '@material-ui/core/DialogTitle';
import DimensionForm from './c/dimensionForm';
/*tslint:disable*/
const styles = (theme) => ({
createButton: {
[theme.breakpoints.down('sm')]: {
width: '100%',
margin: '8px 0',
},
},
});
/*tslint:enable*/
interface IDimensionDialogProps extends React.ClassAttributes<any> {
loadDimension: (name: string) => void;
saveDimension: (dimension: Dimension<any>) => void;
clearDimDetails: () => void;
deleteDimension: (dimension: Dimension<any>) => void;
classes: any;
dimName: string;
dimTitle: string;
toggleDimensionModal: (open: boolean) => void;
dimension: Dimension<any>;
useLink: boolean;
variant?: 'text' | 'outlined' | 'contained' | 'contained' | 'fab' | 'extendedFab';
t: any;
isOpen: boolean;
}
class DimensionDialog extends React.Component<IDimensionDialogProps, any> {
public state = {
open: false,
};
private handleCreate = () => {
const {clearDimDetails} = this.props;
clearDimDetails();
this.show();
}
private show = () => {
const {dimName, dimension, loadDimension} = this.props;