Obsoleting some old files
Transition to SPA-style client Basis for Mosaico template editor
This commit is contained in:
parent
7750232716
commit
c85f2d4440
942 changed files with 86311 additions and 967 deletions
24
client/src/Home.js
Normal file
24
client/src/Home.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
'use strict';
|
||||
|
||||
import React, {Component} from 'react';
|
||||
import {translate} from 'react-i18next';
|
||||
import { requiresAuthenticatedUser } from './lib/page';
|
||||
|
||||
@translate()
|
||||
@requiresAuthenticatedUser
|
||||
export default class List extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
render() {
|
||||
const t = this.props.t;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>{t('Welcome to Mailtrain...')}</h2>
|
||||
<div>TODO: some dashboard</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -59,13 +59,11 @@ export default class Login extends Component {
|
|||
this.setFormStatusMessage('info', t('Verifying credentials ...'));
|
||||
|
||||
const submitSuccessful = await this.validateAndSendFormValuesToURL(FormSendMethod.POST, '/rest/login');
|
||||
/* FIXME, once we turn Mailtrain to single-page application, we should receive authenticated config (from client-helpers.js:getAuthenticatedConfig)
|
||||
as part of login response. Then we should integrate it in the mailtrainConfig global variable. */
|
||||
|
||||
if (submitSuccessful) {
|
||||
const nextUrl = qs.parse(this.props.location.search).next || '/';
|
||||
|
||||
/* FIXME, once we turn Mailtrain to single-page application, this should become navigateTo */
|
||||
/* This ensures we get config for the authenticated user */
|
||||
window.location = nextUrl;
|
||||
} else {
|
||||
this.setFormStatusMessage('warning', t('Please enter your credentials and try again.'));
|
||||
|
|
|
@ -14,7 +14,7 @@ import API from './API';
|
|||
import mailtrainConfig from 'mailtrainConfig';
|
||||
|
||||
|
||||
const getStructure = t => {
|
||||
function getMenus(t) {
|
||||
const subPaths = {
|
||||
login: {
|
||||
title: t('Sign in'),
|
||||
|
@ -45,27 +45,16 @@ const getStructure = t => {
|
|||
}
|
||||
|
||||
return {
|
||||
'': {
|
||||
title: t('Home'),
|
||||
externalLink: '/',
|
||||
children: {
|
||||
account: {
|
||||
title: t('Account'),
|
||||
link: '/account',
|
||||
panelComponent: Account,
|
||||
'account': {
|
||||
title: t('Account'),
|
||||
link: '/account',
|
||||
panelComponent: Account,
|
||||
|
||||
children: subPaths
|
||||
}
|
||||
}
|
||||
children: subPaths
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default function() {
|
||||
ReactDOM.render(
|
||||
<I18nextProvider i18n={ i18n }><Section root='/account/login' structure={getStructure}/></I18nextProvider>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
export default {
|
||||
getMenus
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -8,27 +8,16 @@ import i18n from "../lib/i18n";
|
|||
import {Section} from "../lib/page";
|
||||
import List from "./List";
|
||||
|
||||
const getStructure = t => {
|
||||
function getMenus(t) {
|
||||
return {
|
||||
'': {
|
||||
title: t('Home'),
|
||||
externalLink: '/',
|
||||
children: {
|
||||
'blacklist': {
|
||||
title: t('Blacklist'),
|
||||
link: '/blacklist',
|
||||
panelComponent: List,
|
||||
}
|
||||
}
|
||||
'blacklist': {
|
||||
title: t('Blacklist'),
|
||||
link: '/blacklist',
|
||||
panelComponent: List,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default function() {
|
||||
ReactDOM.render(
|
||||
<I18nextProvider i18n={ i18n }><Section root='/blacklist' structure={getStructure}/></I18nextProvider>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
export default {
|
||||
getMenus
|
||||
}
|
||||
|
|
|
@ -217,6 +217,12 @@ class RouteContent extends Component {
|
|||
return <Redirect to={link}/>;
|
||||
|
||||
} else {
|
||||
const primaryMenuProps = {
|
||||
location: this.props.location
|
||||
};
|
||||
|
||||
const primaryMenuComponent = React.createElement(route.primaryMenuComponent, primaryMenuProps);
|
||||
|
||||
if (resolved) {
|
||||
const compProps = {
|
||||
match: this.props.match,
|
||||
|
@ -233,17 +239,29 @@ class RouteContent extends Component {
|
|||
|
||||
return (
|
||||
<div>
|
||||
{primaryMenuComponent}
|
||||
|
||||
<div>
|
||||
<SecondaryNavBar className="hidden-xs pull-right" route={route} params={params} resolved={resolved}/>
|
||||
<Breadcrumb route={route} params={params} resolved={resolved}/>
|
||||
<SecondaryNavBar className="visible-xs" route={route} params={params} resolved={resolved}/>
|
||||
</div>
|
||||
{this.props.flashMessage}
|
||||
{panel}
|
||||
|
||||
<div className="container-fluid">
|
||||
{this.props.flashMessage}
|
||||
{panel}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
return <div>{t('Loading...')}</div>;
|
||||
return (
|
||||
<div>
|
||||
{primaryMenuComponent}
|
||||
<div className="container-fluid">
|
||||
{t('Loading...')}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -257,36 +275,11 @@ class SectionContent extends Component {
|
|||
super(props);
|
||||
|
||||
this.state = {
|
||||
flashMessageText: ''
|
||||
}
|
||||
|
||||
this.historyUnlisten = props.history.listen((location, action) => {
|
||||
this.closeFlashMessage();
|
||||
})
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------
|
||||
/* FIXME - remove this once we migrate fully to React
|
||||
This part transforms the flash notice rendered by the server to flash notice managed by React client.
|
||||
It is used primarily for the login info, but there may be some other cases.
|
||||
*/
|
||||
const alrt = jQuery('.container>.alert');
|
||||
alrt.find('button').remove();
|
||||
|
||||
const alrtText = alrt.text();
|
||||
if (alrtText) {
|
||||
this.state.flashMessageText = alrtText;
|
||||
|
||||
const severityRegex = /alert-([^ ]*)/;
|
||||
const match = alrt.attr('class').match(severityRegex);
|
||||
|
||||
if (match) {
|
||||
this.state.flashMessageSeverity = match[1];
|
||||
}
|
||||
}
|
||||
|
||||
alrt.remove();
|
||||
// -------------------------------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
|
@ -327,14 +320,13 @@ class SectionContent extends Component {
|
|||
ensureAuthenticated() {
|
||||
if (!mailtrainConfig.isAuthenticated) {
|
||||
/* FIXME, once we turn Mailtrain to single-page application, this should become navigateTo */
|
||||
window.location = '/account/login?next=' + encodeURIComponent(this.props.root);
|
||||
this.navigateTo('/account/login?next=' + encodeURIComponent(window.location.pathname));
|
||||
}
|
||||
}
|
||||
|
||||
errorHandler(error) {
|
||||
if (error instanceof interoperableErrors.NotLoggedInError) {
|
||||
/* FIXME, once we turn Mailtrain to single-page application, this should become navigateTo */
|
||||
window.location = '/account/login?next=' + encodeURIComponent(this.props.root);
|
||||
this.navigateTo('/account/login?next=' + encodeURIComponent(window.location.pathname));
|
||||
} else if (error.response && error.response.data && error.response.data.message) {
|
||||
console.error(error);
|
||||
this.navigateToWithFlashMessage(this.props.root, 'danger', error.response.data.message);
|
||||
|
|
|
@ -6,9 +6,9 @@ import { translate } from 'react-i18next';
|
|||
import PropTypes from 'prop-types';
|
||||
|
||||
import jQuery from 'jquery';
|
||||
import '../../public/jquery/jquery-ui-1.12.1.min.js';
|
||||
import '../../public/fancytree/jquery.fancytree-all.min.js';
|
||||
import '../../public/fancytree/skin-bootstrap/ui.fancytree.min.css';
|
||||
import '../../vendor/jquery/jquery-ui-1.12.1.min.js';
|
||||
import '../../vendor/fancytree/jquery.fancytree-all.min.js';
|
||||
import '../../vendor/fancytree/skin-bootstrap/ui.fancytree.min.css';
|
||||
import './tree.css';
|
||||
import axios from './axios';
|
||||
|
||||
|
|
|
@ -20,178 +20,168 @@ import SegmentsCUD from './segments/CUD';
|
|||
import Share from '../shares/Share';
|
||||
|
||||
|
||||
const getStructure = t => {
|
||||
function getMenus(t) {
|
||||
return {
|
||||
'': {
|
||||
title: t('Home'),
|
||||
externalLink: '/',
|
||||
'lists': {
|
||||
title: t('Lists'),
|
||||
link: '/lists',
|
||||
panelComponent: ListsList,
|
||||
children: {
|
||||
'lists': {
|
||||
title: t('Lists'),
|
||||
link: '/lists',
|
||||
panelComponent: ListsList,
|
||||
children: {
|
||||
':listId([0-9]+)': {
|
||||
title: resolved => t('List "{{name}}"', {name: resolved.list.name}),
|
||||
':listId([0-9]+)': {
|
||||
title: resolved => t('List "{{name}}"', {name: resolved.list.name}),
|
||||
resolve: {
|
||||
list: params => `/rest/lists/${params.listId}`
|
||||
},
|
||||
link: params => `/lists/${params.listId}/subscriptions`,
|
||||
navs: {
|
||||
subscriptions: {
|
||||
title: t('Subscribers'),
|
||||
resolve: {
|
||||
list: params => `/rest/lists/${params.listId}`
|
||||
segments: params => `/rest/segments/${params.listId}`,
|
||||
},
|
||||
link: params => `/lists/${params.listId}/subscriptions`,
|
||||
navs: {
|
||||
subscriptions: {
|
||||
title: t('Subscribers'),
|
||||
resolve: {
|
||||
segments: params => `/rest/segments/${params.listId}`,
|
||||
},
|
||||
link: params => `/lists/${params.listId}/subscriptions`,
|
||||
visible: resolved => resolved.list.permissions.includes('viewSubscriptions'),
|
||||
panelRender: props => <SubscriptionsList list={props.resolved.list} segments={props.resolved.segments} segmentId={qs.parse(props.location.search).segment} />,
|
||||
children: {
|
||||
':subscriptionId([0-9]+)': {
|
||||
title: resolved => resolved.subscription.email,
|
||||
resolve: {
|
||||
subscription: params => `/rest/subscriptions/${params.listId}/${params.subscriptionId}`,
|
||||
fieldsGrouped: params => `/rest/fields-grouped/${params.listId}`
|
||||
},
|
||||
link: params => `/lists/${params.listId}/subscriptions/${params.subscriptionId}/edit`,
|
||||
navs: {
|
||||
':action(edit|delete)': {
|
||||
title: t('Edit'),
|
||||
link: params => `/lists/${params.listId}/subscriptions/${params.subscriptionId}/edit`,
|
||||
panelRender: props => <SubscriptionsCUD action={props.match.params.action} entity={props.resolved.subscription} list={props.resolved.list} fieldsGrouped={props.resolved.fieldsGrouped} />
|
||||
}
|
||||
}
|
||||
},
|
||||
create: {
|
||||
title: t('Create'),
|
||||
resolve: {
|
||||
fieldsGrouped: params => `/rest/fields-grouped/${params.listId}`
|
||||
},
|
||||
panelRender: props => <SubscriptionsCUD action="create" list={props.resolved.list} fieldsGrouped={props.resolved.fieldsGrouped} />
|
||||
}
|
||||
} },
|
||||
':action(edit|delete)': {
|
||||
title: t('Edit'),
|
||||
link: params => `/lists/${params.listId}/edit`,
|
||||
visible: resolved => resolved.list.permissions.includes('edit'),
|
||||
panelRender: props => <ListsCUD action={props.match.params.action} entity={props.resolved.list} />
|
||||
},
|
||||
fields: {
|
||||
title: t('Fields'),
|
||||
link: params => `/lists/${params.listId}/fields/`,
|
||||
visible: resolved => resolved.list.permissions.includes('manageFields'),
|
||||
panelRender: props => <FieldsList list={props.resolved.list} />,
|
||||
children: {
|
||||
':fieldId([0-9]+)': {
|
||||
title: resolved => t('Field "{{name}}"', {name: resolved.field.name}),
|
||||
resolve: {
|
||||
field: params => `/rest/fields/${params.listId}/${params.fieldId}`,
|
||||
fields: params => `/rest/fields/${params.listId}`
|
||||
},
|
||||
link: params => `/lists/${params.listId}/fields/${params.fieldId}/edit`,
|
||||
navs: {
|
||||
':action(edit|delete)': {
|
||||
title: t('Edit'),
|
||||
link: params => `/lists/${params.listId}/fields/${params.fieldId}/edit`,
|
||||
panelRender: props => <FieldsCUD action={props.match.params.action} entity={props.resolved.field} list={props.resolved.list} fields={props.resolved.fields} />
|
||||
}
|
||||
}
|
||||
},
|
||||
create: {
|
||||
title: t('Create'),
|
||||
resolve: {
|
||||
fields: params => `/rest/fields/${params.listId}`
|
||||
},
|
||||
panelRender: props => <FieldsCUD action="create" list={props.resolved.list} fields={props.resolved.fields} />
|
||||
}
|
||||
}
|
||||
},
|
||||
segments: {
|
||||
title: t('Segments'),
|
||||
link: params => `/lists/${params.listId}/segments`,
|
||||
visible: resolved => resolved.list.permissions.includes('manageSegments'),
|
||||
panelRender: props => <SegmentsList list={props.resolved.list} />,
|
||||
children: {
|
||||
':segmentId([0-9]+)': {
|
||||
title: resolved => t('Segment "{{name}}"', {name: resolved.segment.name}),
|
||||
resolve: {
|
||||
segment: params => `/rest/segments/${params.listId}/${params.segmentId}`,
|
||||
fields: params => `/rest/fields/${params.listId}`
|
||||
},
|
||||
link: params => `/lists/${params.listId}/segments/${params.segmentId}/edit`,
|
||||
navs: {
|
||||
':action(edit|delete)': {
|
||||
title: t('Edit'),
|
||||
link: params => `/lists/${params.listId}/segments/${params.segmentId}/edit`,
|
||||
panelRender: props => <SegmentsCUD action={props.match.params.action} entity={props.resolved.segment} list={props.resolved.list} fields={props.resolved.fields} />
|
||||
}
|
||||
}
|
||||
},
|
||||
create: {
|
||||
title: t('Create'),
|
||||
resolve: {
|
||||
fields: params => `/rest/fields/${params.listId}`
|
||||
},
|
||||
panelRender: props => <SegmentsCUD action="create" list={props.resolved.list} fields={props.resolved.fields} />
|
||||
}
|
||||
}
|
||||
},
|
||||
share: {
|
||||
title: t('Share'),
|
||||
link: params => `/lists/${params.listId}/share`,
|
||||
visible: resolved => resolved.list.permissions.includes('share'),
|
||||
panelRender: props => <Share title={t('Share')} entity={props.resolved.list} entityTypeId="list" />
|
||||
}
|
||||
}
|
||||
},
|
||||
create: {
|
||||
title: t('Create'),
|
||||
panelRender: props => <ListsCUD action="create" />
|
||||
},
|
||||
forms: {
|
||||
title: t('Custom Forms'),
|
||||
link: '/lists/forms',
|
||||
panelComponent: FormsList,
|
||||
visible: resolved => resolved.list.permissions.includes('viewSubscriptions'),
|
||||
panelRender: props => <SubscriptionsList list={props.resolved.list} segments={props.resolved.segments} segmentId={qs.parse(props.location.search).segment} />,
|
||||
children: {
|
||||
':formsId([0-9]+)': {
|
||||
title: resolved => t('Custom Forms "{{name}}"', {name: resolved.forms.name}),
|
||||
':subscriptionId([0-9]+)': {
|
||||
title: resolved => resolved.subscription.email,
|
||||
resolve: {
|
||||
forms: params => `/rest/forms/${params.formsId}`
|
||||
subscription: params => `/rest/subscriptions/${params.listId}/${params.subscriptionId}`,
|
||||
fieldsGrouped: params => `/rest/fields-grouped/${params.listId}`
|
||||
},
|
||||
link: params => `/lists/forms/${params.formsId}/edit`,
|
||||
link: params => `/lists/${params.listId}/subscriptions/${params.subscriptionId}/edit`,
|
||||
navs: {
|
||||
':action(edit|delete)': {
|
||||
title: t('Edit'),
|
||||
link: params => `/lists/forms/${params.formsId}/edit`,
|
||||
visible: resolved => resolved.forms.permissions.includes('edit'),
|
||||
panelRender: props => <FormsCUD action={props.match.params.action} entity={props.resolved.forms} />
|
||||
},
|
||||
share: {
|
||||
title: t('Share'),
|
||||
link: params => `/lists/forms/${params.formsId}/share`,
|
||||
visible: resolved => resolved.forms.permissions.includes('share'),
|
||||
panelRender: props => <Share title={t('Share')} entity={props.resolved.forms} entityTypeId="customForm" />
|
||||
link: params => `/lists/${params.listId}/subscriptions/${params.subscriptionId}/edit`,
|
||||
panelRender: props => <SubscriptionsCUD action={props.match.params.action} entity={props.resolved.subscription} list={props.resolved.list} fieldsGrouped={props.resolved.fieldsGrouped} />
|
||||
}
|
||||
}
|
||||
},
|
||||
create: {
|
||||
title: t('Create'),
|
||||
panelRender: props => <FormsCUD action="create" />
|
||||
resolve: {
|
||||
fieldsGrouped: params => `/rest/fields-grouped/${params.listId}`
|
||||
},
|
||||
panelRender: props => <SubscriptionsCUD action="create" list={props.resolved.list} fieldsGrouped={props.resolved.fieldsGrouped} />
|
||||
}
|
||||
} },
|
||||
':action(edit|delete)': {
|
||||
title: t('Edit'),
|
||||
link: params => `/lists/${params.listId}/edit`,
|
||||
visible: resolved => resolved.list.permissions.includes('edit'),
|
||||
panelRender: props => <ListsCUD action={props.match.params.action} entity={props.resolved.list} />
|
||||
},
|
||||
fields: {
|
||||
title: t('Fields'),
|
||||
link: params => `/lists/${params.listId}/fields/`,
|
||||
visible: resolved => resolved.list.permissions.includes('manageFields'),
|
||||
panelRender: props => <FieldsList list={props.resolved.list} />,
|
||||
children: {
|
||||
':fieldId([0-9]+)': {
|
||||
title: resolved => t('Field "{{name}}"', {name: resolved.field.name}),
|
||||
resolve: {
|
||||
field: params => `/rest/fields/${params.listId}/${params.fieldId}`,
|
||||
fields: params => `/rest/fields/${params.listId}`
|
||||
},
|
||||
link: params => `/lists/${params.listId}/fields/${params.fieldId}/edit`,
|
||||
navs: {
|
||||
':action(edit|delete)': {
|
||||
title: t('Edit'),
|
||||
link: params => `/lists/${params.listId}/fields/${params.fieldId}/edit`,
|
||||
panelRender: props => <FieldsCUD action={props.match.params.action} entity={props.resolved.field} list={props.resolved.list} fields={props.resolved.fields} />
|
||||
}
|
||||
}
|
||||
},
|
||||
create: {
|
||||
title: t('Create'),
|
||||
resolve: {
|
||||
fields: params => `/rest/fields/${params.listId}`
|
||||
},
|
||||
panelRender: props => <FieldsCUD action="create" list={props.resolved.list} fields={props.resolved.fields} />
|
||||
}
|
||||
}
|
||||
},
|
||||
segments: {
|
||||
title: t('Segments'),
|
||||
link: params => `/lists/${params.listId}/segments`,
|
||||
visible: resolved => resolved.list.permissions.includes('manageSegments'),
|
||||
panelRender: props => <SegmentsList list={props.resolved.list} />,
|
||||
children: {
|
||||
':segmentId([0-9]+)': {
|
||||
title: resolved => t('Segment "{{name}}"', {name: resolved.segment.name}),
|
||||
resolve: {
|
||||
segment: params => `/rest/segments/${params.listId}/${params.segmentId}`,
|
||||
fields: params => `/rest/fields/${params.listId}`
|
||||
},
|
||||
link: params => `/lists/${params.listId}/segments/${params.segmentId}/edit`,
|
||||
navs: {
|
||||
':action(edit|delete)': {
|
||||
title: t('Edit'),
|
||||
link: params => `/lists/${params.listId}/segments/${params.segmentId}/edit`,
|
||||
panelRender: props => <SegmentsCUD action={props.match.params.action} entity={props.resolved.segment} list={props.resolved.list} fields={props.resolved.fields} />
|
||||
}
|
||||
}
|
||||
},
|
||||
create: {
|
||||
title: t('Create'),
|
||||
resolve: {
|
||||
fields: params => `/rest/fields/${params.listId}`
|
||||
},
|
||||
panelRender: props => <SegmentsCUD action="create" list={props.resolved.list} fields={props.resolved.fields} />
|
||||
}
|
||||
}
|
||||
},
|
||||
share: {
|
||||
title: t('Share'),
|
||||
link: params => `/lists/${params.listId}/share`,
|
||||
visible: resolved => resolved.list.permissions.includes('share'),
|
||||
panelRender: props => <Share title={t('Share')} entity={props.resolved.list} entityTypeId="list" />
|
||||
}
|
||||
}
|
||||
},
|
||||
create: {
|
||||
title: t('Create'),
|
||||
panelRender: props => <ListsCUD action="create" />
|
||||
},
|
||||
forms: {
|
||||
title: t('Custom Forms'),
|
||||
link: '/lists/forms',
|
||||
panelComponent: FormsList,
|
||||
children: {
|
||||
':formsId([0-9]+)': {
|
||||
title: resolved => t('Custom Forms "{{name}}"', {name: resolved.forms.name}),
|
||||
resolve: {
|
||||
forms: params => `/rest/forms/${params.formsId}`
|
||||
},
|
||||
link: params => `/lists/forms/${params.formsId}/edit`,
|
||||
navs: {
|
||||
':action(edit|delete)': {
|
||||
title: t('Edit'),
|
||||
link: params => `/lists/forms/${params.formsId}/edit`,
|
||||
visible: resolved => resolved.forms.permissions.includes('edit'),
|
||||
panelRender: props => <FormsCUD action={props.match.params.action} entity={props.resolved.forms} />
|
||||
},
|
||||
share: {
|
||||
title: t('Share'),
|
||||
link: params => `/lists/forms/${params.formsId}/share`,
|
||||
visible: resolved => resolved.forms.permissions.includes('share'),
|
||||
panelRender: props => <Share title={t('Share')} entity={props.resolved.forms} entityTypeId="customForm" />
|
||||
}
|
||||
}
|
||||
},
|
||||
create: {
|
||||
title: t('Create'),
|
||||
panelRender: props => <FormsCUD action="create" />
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default function() {
|
||||
ReactDOM.render(
|
||||
<I18nextProvider i18n={ i18n }><Section root='/lists' structure={getStructure}/></I18nextProvider>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
export default {
|
||||
getMenus
|
||||
}
|
||||
|
|
75
client/src/mosaico/root.js
Normal file
75
client/src/mosaico/root.js
Normal file
|
@ -0,0 +1,75 @@
|
|||
'use strict';
|
||||
|
||||
import React, {Component} from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import {
|
||||
I18nextProvider,
|
||||
translate
|
||||
} from 'react-i18next';
|
||||
import i18n from '../lib/i18n';
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
@translate()
|
||||
class MosaicoEditor extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
//structure: PropTypes.oneOfType([PropTypes.object, PropTypes.func]).isRequired,
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const basePath = '/public/mosaico';
|
||||
|
||||
if (!Mosaico.isCompatible()) {
|
||||
alert('Update your browser!');
|
||||
return;
|
||||
}
|
||||
|
||||
const plugins = window.mosaicoPlugins;
|
||||
|
||||
plugins.unshift(vm => {
|
||||
// This is a fix for the use of hardcoded path in Mosaico
|
||||
vm.logoPath = basePath + '/img/mosaico32.png'
|
||||
});
|
||||
|
||||
const config = {
|
||||
imgProcessorBackend: basePath+'/img/',
|
||||
emailProcessorBackend: basePath+'/dl/',
|
||||
titleToken: "MOSAICO Responsive Email Designer",
|
||||
fileuploadConfig: {
|
||||
url: basePath+'/upload/'
|
||||
},
|
||||
strings: window.mosaicoLanguageStrings
|
||||
};
|
||||
|
||||
const metadata = undefined;
|
||||
const model = undefined;
|
||||
const template = basePath + '/templates/versafix-1/index.html';
|
||||
|
||||
Mosaico.start(config, template, metadata, model, plugins);
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default function() {
|
||||
ReactDOM.render(
|
||||
<I18nextProvider i18n={ i18n }><MosaicoEditor /></I18nextProvider>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
};
|
||||
|
||||
|
|
@ -10,52 +10,44 @@ import CUD from './CUD';
|
|||
import List from './List';
|
||||
import Share from '../shares/Share';
|
||||
|
||||
const getStructure = t => ({
|
||||
'': {
|
||||
title: t('Home'),
|
||||
externalLink: '/',
|
||||
children: {
|
||||
namespaces: {
|
||||
title: t('Namespaces'),
|
||||
link: '/namespaces',
|
||||
panelComponent: List,
|
||||
children: {
|
||||
':namespaceId([0-9]+)': {
|
||||
title: resolved => t('Namespace "{{name}}"', {name: resolved.namespace.name}),
|
||||
resolve: {
|
||||
namespace: params => `/rest/namespaces/${params.namespaceId}`
|
||||
function getMenus(t) {
|
||||
return {
|
||||
namespaces: {
|
||||
title: t('Namespaces'),
|
||||
link: '/namespaces',
|
||||
panelComponent: List,
|
||||
children: {
|
||||
':namespaceId([0-9]+)': {
|
||||
title: resolved => t('Namespace "{{name}}"', {name: resolved.namespace.name}),
|
||||
resolve: {
|
||||
namespace: params => `/rest/namespaces/${params.namespaceId}`
|
||||
},
|
||||
link: params => `/namespaces/${params.namespaceId}/edit`,
|
||||
navs: {
|
||||
':action(edit|delete)': {
|
||||
title: t('Edit'),
|
||||
link: params => `/namespaces/${params.namespaceId}/edit`,
|
||||
visible: resolved => resolved.namespace.permissions.includes('edit'),
|
||||
panelRender: props => <CUD action={props.match.params.action} entity={props.resolved.namespace} />
|
||||
},
|
||||
link: params => `/namespaces/${params.namespaceId}/edit`,
|
||||
navs: {
|
||||
':action(edit|delete)': {
|
||||
title: t('Edit'),
|
||||
link: params => `/namespaces/${params.namespaceId}/edit`,
|
||||
visible: resolved => resolved.namespace.permissions.includes('edit'),
|
||||
panelRender: props => <CUD action={props.match.params.action} entity={props.resolved.namespace} />
|
||||
},
|
||||
share: {
|
||||
title: t('Share'),
|
||||
link: params => `/namespaces/${params.namespaceId}/share`,
|
||||
visible: resolved => resolved.namespace.permissions.includes('share'),
|
||||
panelRender: props => <Share title={t('Share')} entity={props.resolved.namespace} entityTypeId="namespace" />
|
||||
}
|
||||
share: {
|
||||
title: t('Share'),
|
||||
link: params => `/namespaces/${params.namespaceId}/share`,
|
||||
visible: resolved => resolved.namespace.permissions.includes('share'),
|
||||
panelRender: props => <Share title={t('Share')} entity={props.resolved.namespace} entityTypeId="namespace" />
|
||||
}
|
||||
},
|
||||
create: {
|
||||
title: t('Create'),
|
||||
panelRender: props => <CUD action="create" />
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
create: {
|
||||
title: t('Create'),
|
||||
panelRender: props => <CUD action="create" />
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export default function() {
|
||||
ReactDOM.render(
|
||||
<I18nextProvider i18n={ i18n }><Section root='/namespaces' structure={getStructure}/></I18nextProvider>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
export default {
|
||||
getMenus
|
||||
}
|
||||
|
|
|
@ -17,106 +17,93 @@ import { ReportState } from '../../../shared/reports';
|
|||
import mailtrainConfig from 'mailtrainConfig';
|
||||
|
||||
|
||||
const getStructure = t => {
|
||||
const subPaths = {};
|
||||
|
||||
function getMenus(t) {
|
||||
return {
|
||||
'': {
|
||||
title: t('Home'),
|
||||
externalLink: '/',
|
||||
'reports': {
|
||||
title: t('Reports'),
|
||||
link: '/reports',
|
||||
panelComponent: ReportsList,
|
||||
children: {
|
||||
'reports': {
|
||||
title: t('Reports'),
|
||||
link: '/reports',
|
||||
panelComponent: ReportsList,
|
||||
children: {
|
||||
':reportId([0-9]+)': {
|
||||
title: resolved => t('Report "{{name}}"', {name: resolved.report.name}),
|
||||
resolve: {
|
||||
report: params => `/rest/reports/${params.reportId}`
|
||||
},
|
||||
':reportId([0-9]+)': {
|
||||
title: resolved => t('Report "{{name}}"', {name: resolved.report.name}),
|
||||
resolve: {
|
||||
report: params => `/rest/reports/${params.reportId}`
|
||||
},
|
||||
link: params => `/reports/${params.reportId}/edit`,
|
||||
navs: {
|
||||
':action(edit|delete)': {
|
||||
title: t('Edit'),
|
||||
link: params => `/reports/${params.reportId}/edit`,
|
||||
visible: resolved => resolved.report.permissions.includes('edit'),
|
||||
panelRender: props => <ReportsCUD action={props.match.params.action} entity={props.resolved.report} />
|
||||
},
|
||||
view: {
|
||||
title: t('View'),
|
||||
link: params => `/reports/${params.reportId}/view`,
|
||||
visible: resolved => resolved.report.permissions.includes('viewContent') && resolved.report.state === ReportState.FINISHED && resolved.report.mime_type === 'text/html',
|
||||
panelRender: props => (<ReportsView {...props} />),
|
||||
},
|
||||
download: {
|
||||
title: t('Download'),
|
||||
externalLink: params => `/reports/${params.reportId}/download`,
|
||||
visible: resolved => resolved.report.permissions.includes('viewContent') && resolved.report.state === ReportState.FINISHED && resolved.report.mime_type === 'text/csv'
|
||||
},
|
||||
output: {
|
||||
title: t('Output'),
|
||||
link: params => `/reports/${params.reportId}/output`,
|
||||
visible: resolved => resolved.report.permissions.includes('viewOutput'),
|
||||
panelRender: props => (<ReportsOutput {...props} />)
|
||||
},
|
||||
share: {
|
||||
title: t('Share'),
|
||||
link: params => `/reports/${params.reportId}/share`,
|
||||
visible: resolved => resolved.report.permissions.includes('share'),
|
||||
panelRender: props => <Share title={t('Share')} entity={props.resolved.report} entityTypeId="report" />
|
||||
}
|
||||
}
|
||||
},
|
||||
create: {
|
||||
title: t('Create'),
|
||||
panelRender: props => <ReportsCUD action="create" />
|
||||
},
|
||||
'templates': {
|
||||
title: t('Templates'),
|
||||
link: '/reports/templates',
|
||||
panelComponent: ReportTemplatesList,
|
||||
children: {
|
||||
':templateId([0-9]+)': {
|
||||
title: resolved => t('Template "{{name}}"', {name: resolved.template.name}),
|
||||
resolve: {
|
||||
template: params => `/rest/report-templates/${params.templateId}`
|
||||
},
|
||||
link: params => `/reports/templates/${params.templateId}/edit`,
|
||||
navs: {
|
||||
':action(edit|delete)': {
|
||||
title: t('Edit'),
|
||||
link: params => `/reports/${params.reportId}/edit`,
|
||||
visible: resolved => resolved.report.permissions.includes('edit'),
|
||||
panelRender: props => <ReportsCUD action={props.match.params.action} entity={props.resolved.report} />
|
||||
},
|
||||
view: {
|
||||
title: t('View'),
|
||||
link: params => `/reports/${params.reportId}/view`,
|
||||
visible: resolved => resolved.report.permissions.includes('viewContent') && resolved.report.state === ReportState.FINISHED && resolved.report.mime_type === 'text/html',
|
||||
panelRender: props => (<ReportsView {...props} />),
|
||||
},
|
||||
download: {
|
||||
title: t('Download'),
|
||||
externalLink: params => `/reports/${params.reportId}/download`,
|
||||
visible: resolved => resolved.report.permissions.includes('viewContent') && resolved.report.state === ReportState.FINISHED && resolved.report.mime_type === 'text/csv'
|
||||
},
|
||||
output: {
|
||||
title: t('Output'),
|
||||
link: params => `/reports/${params.reportId}/output`,
|
||||
visible: resolved => resolved.report.permissions.includes('viewOutput'),
|
||||
panelRender: props => (<ReportsOutput {...props} />)
|
||||
link: params => `/reports/templates/${params.templateId}/edit`,
|
||||
visible: resolved => mailtrainConfig.globalPermissions.includes('createJavascriptWithROAccess') && resolved.template.permissions.includes('edit'),
|
||||
panelRender: props => <ReportTemplatesCUD action={props.match.params.action} entity={props.resolved.template} />
|
||||
},
|
||||
share: {
|
||||
title: t('Share'),
|
||||
link: params => `/reports/${params.reportId}/share`,
|
||||
visible: resolved => resolved.report.permissions.includes('share'),
|
||||
panelRender: props => <Share title={t('Share')} entity={props.resolved.report} entityTypeId="report" />
|
||||
link: params => `/reports/templates/${params.templateId}/share`,
|
||||
visible: resolved => resolved.template.permissions.includes('share'),
|
||||
panelRender: props => <Share title={t('Share')} entity={props.resolved.template} entityTypeId="reportTemplate" />
|
||||
}
|
||||
}
|
||||
},
|
||||
create: {
|
||||
title: t('Create'),
|
||||
panelRender: props => <ReportsCUD action="create" />
|
||||
},
|
||||
'templates': {
|
||||
title: t('Templates'),
|
||||
link: '/reports/templates',
|
||||
panelComponent: ReportTemplatesList,
|
||||
children: {
|
||||
':templateId([0-9]+)': {
|
||||
title: resolved => t('Template "{{name}}"', {name: resolved.template.name}),
|
||||
resolve: {
|
||||
template: params => `/rest/report-templates/${params.templateId}`
|
||||
},
|
||||
link: params => `/reports/templates/${params.templateId}/edit`,
|
||||
navs: {
|
||||
':action(edit|delete)': {
|
||||
title: t('Edit'),
|
||||
link: params => `/reports/templates/${params.templateId}/edit`,
|
||||
visible: resolved => mailtrainConfig.globalPermissions.includes('createJavascriptWithROAccess') && resolved.template.permissions.includes('edit'),
|
||||
panelRender: props => <ReportTemplatesCUD action={props.match.params.action} entity={props.resolved.template} />
|
||||
},
|
||||
share: {
|
||||
title: t('Share'),
|
||||
link: params => `/reports/templates/${params.templateId}/share`,
|
||||
visible: resolved => resolved.template.permissions.includes('share'),
|
||||
panelRender: props => <Share title={t('Share')} entity={props.resolved.template} entityTypeId="reportTemplate" />
|
||||
}
|
||||
}
|
||||
},
|
||||
create: {
|
||||
title: t('Create'),
|
||||
extraParams: [':wizard?'],
|
||||
panelRender: props => <ReportTemplatesCUD action="create" wizard={props.match.params.wizard} />
|
||||
}
|
||||
}
|
||||
extraParams: [':wizard?'],
|
||||
panelRender: props => <ReportTemplatesCUD action="create" wizard={props.match.params.wizard} />
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default function() {
|
||||
ReactDOM.render(
|
||||
<I18nextProvider i18n={ i18n }><Section root='/reports' structure={getStructure}/></I18nextProvider>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
getMenus
|
||||
}
|
||||
|
|
166
client/src/root.js
Normal file
166
client/src/root.js
Normal file
|
@ -0,0 +1,166 @@
|
|||
'use strict';
|
||||
|
||||
import React, {Component} from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import {
|
||||
I18nextProvider,
|
||||
translate
|
||||
} from 'react-i18next';
|
||||
import i18n from './lib/i18n';
|
||||
|
||||
import account from './account/root';
|
||||
import blacklist from './blacklist/root';
|
||||
import lists from './lists/root';
|
||||
import namespaces from './namespaces/root';
|
||||
import reports from './reports/root';
|
||||
import templates from './templates/root';
|
||||
import users from './users/root';
|
||||
import {Section} from "./lib/page";
|
||||
|
||||
import mailtrainConfig from 'mailtrainConfig';
|
||||
import Home from "./Home";
|
||||
import {
|
||||
ActionLink,
|
||||
Icon
|
||||
} from "./lib/bootstrap-components";
|
||||
import {Link} from "react-router-dom";
|
||||
import axios from './lib/axios';
|
||||
|
||||
|
||||
@translate()
|
||||
class Root extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
const t = props.t;
|
||||
const self = this;
|
||||
|
||||
const topLevelMenuKeys = ['lists', 'templates', 'reports'];
|
||||
|
||||
class MainMenu extends Component {
|
||||
render() {
|
||||
const path = this.props.location.pathname;
|
||||
const topLevelMenu = [];
|
||||
const topLevelItems = self.structure[''].children;
|
||||
for (const entryKey of topLevelMenuKeys) {
|
||||
const entry = topLevelItems[entryKey];
|
||||
const link = entry.link || entry.externalLink;
|
||||
|
||||
if (link && path.startsWith(link)) {
|
||||
topLevelMenu.push(<li key={entryKey} className="active"><Link to={link}>{entry.title} <span className="sr-only">{t('(current)')}</span></Link></li>);
|
||||
} else {
|
||||
topLevelMenu.push(<li key={entryKey}><Link to={link}>{entry.title}</Link></li>);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<nav className="navbar navbar-default navbar-static-top">
|
||||
<div className="container-fluid">
|
||||
<div className="navbar-header">
|
||||
<button type="button" className="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
|
||||
<span className="sr-only">{t('Toggle navigation')}</span>
|
||||
<span className="icon-bar"></span>
|
||||
<span className="icon-bar"></span>
|
||||
<span className="icon-bar"></span>
|
||||
</button>
|
||||
<Link className="navbar-brand" to="/"><i className="glyphicon glyphicon-envelope"></i> Mailtrain</Link>
|
||||
</div>
|
||||
|
||||
{mailtrainConfig.isAuthenticated &&
|
||||
<div className="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
|
||||
<ul className="nav navbar-nav">
|
||||
{topLevelMenu}
|
||||
|
||||
<li className="dropdown">
|
||||
<a href="#" className="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{t('Administration')}<span className="caret"></span></a>
|
||||
<ul className="dropdown-menu">
|
||||
<li>
|
||||
<Link to="/users"><Icon icon='cog'/> {t('Users')}</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link to="/namespaces"><Icon icon='cog'/> {t('Namespaces')}</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link to="/settings"><Icon icon='cog'/> {t('Settings')}</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link to="/blacklist"><Icon icon='ban-circle'/> {t('Blacklist')}</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link to="/account/api"><Icon icon='retweet'/> {t('API')}</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<ul className="nav navbar-nav navbar-right">
|
||||
<li className="dropdown">
|
||||
<a href="#" className="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
|
||||
<span className="glyphicon glyphicon-user" aria-hidden="true"></span> {mailtrainConfig.user.username}<span className="caret"></span>
|
||||
</a>
|
||||
<ul className="dropdown-menu">
|
||||
<li>
|
||||
<Link to="/account"><Icon icon='user'/> {t('Account')}</Link>
|
||||
</li>
|
||||
<li>
|
||||
<ActionLink onClickAsync={::self.logout}><Icon icon='log-out'/> {t('Log out')}</ActionLink>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
this.structure = {
|
||||
'': {
|
||||
title: t('Home'),
|
||||
link: '/',
|
||||
panelComponent: Home,
|
||||
primaryMenuComponent: MainMenu,
|
||||
children: {
|
||||
...lists.getMenus(t),
|
||||
...reports.getMenus(t),
|
||||
...templates.getMenus(t),
|
||||
...namespaces.getMenus(t),
|
||||
...users.getMenus(t),
|
||||
...blacklist.getMenus(t),
|
||||
...account.getMenus(t),
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
async logout() {
|
||||
await axios.post('/rest/logout');
|
||||
window.location = '/';
|
||||
}
|
||||
|
||||
render() {
|
||||
const t = this.props.t;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Section root='/' structure={this.structure}/>
|
||||
|
||||
<footer className="footer">
|
||||
<div className="container-fluid">
|
||||
<p className="text-muted">© 2018 <a href="https://mailtrain.org">Mailtrain.org</a>, <a href="mailto:info@mailtrain.org">info@mailtrain.org</a>. <a href="https://github.com/Mailtrain-org/mailtrain">{t('Source on GitHub')}</a></p>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default function() {
|
||||
ReactDOM.render(<I18nextProvider i18n={ i18n }><Root/></I18nextProvider>,document.getElementById('root'));
|
||||
};
|
||||
|
||||
|
|
@ -167,6 +167,7 @@ export default class CUD extends Component {
|
|||
{this.state.showMergeTagReference &&
|
||||
<div style={{marginTop: '15px'}}>
|
||||
<Trans><p>Merge tags are tags that are replaced before sending out the message. The format of the merge tag is the following: <code>[TAG_NAME]</code> or <code>[TAG_NAME/fallback]</code> where <code>fallback</code> is an optional text value used when <code>TAG_NAME</code> is empty.</p></Trans>
|
||||
<Trans><p>You can use any of the standard merge tags below. In addition to that every custom field has its own merge tag. Check the fields of the list you are going to send to.</p></Trans>
|
||||
<table className="table table-bordered table-condensed table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
|
@ -211,30 +212,6 @@ export default class CUD extends Component {
|
|||
<Trans>Email address</Trans>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
[FIRST_NAME]
|
||||
</th>
|
||||
<td>
|
||||
<Trans>First name</Trans>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
[LAST_NAME]
|
||||
</th>
|
||||
<td>
|
||||
<Trans>Last name</Trans>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
[FULL_NAME]
|
||||
</th>
|
||||
<td>
|
||||
<Trans>Full name (first and last name combined)</Trans>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
[SUBSCRIPTION_ID]
|
||||
|
@ -261,8 +238,6 @@ export default class CUD extends Component {
|
|||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<Trans><p>In addition to that any custom field can have its own merge tag.</p></Trans>
|
||||
</div>}
|
||||
</AlignedRow>
|
||||
|
||||
|
|
|
@ -11,54 +11,43 @@ import TemplatesList from './List';
|
|||
import Share from '../shares/Share';
|
||||
|
||||
|
||||
const getStructure = t => {
|
||||
function getMenus(t) {
|
||||
return {
|
||||
'': {
|
||||
title: t('Home'),
|
||||
externalLink: '/',
|
||||
'templates': {
|
||||
title: t('Templates'),
|
||||
link: '/templates',
|
||||
panelComponent: TemplatesList,
|
||||
children: {
|
||||
'templates': {
|
||||
title: t('Templates'),
|
||||
link: '/templates',
|
||||
panelComponent: TemplatesList,
|
||||
children: {
|
||||
':templateId([0-9]+)': {
|
||||
title: resolved => t('Template "{{name}}"', {name: resolved.template.name}),
|
||||
resolve: {
|
||||
template: params => `/rest/templates/${params.templateId}`
|
||||
},
|
||||
':templateId([0-9]+)': {
|
||||
title: resolved => t('Template "{{name}}"', {name: resolved.template.name}),
|
||||
resolve: {
|
||||
template: params => `/rest/templates/${params.templateId}`
|
||||
},
|
||||
link: params => `/templates/${params.templateId}/edit`,
|
||||
navs: {
|
||||
':action(edit|delete)': {
|
||||
title: t('Edit'),
|
||||
link: params => `/templates/${params.templateId}/edit`,
|
||||
navs: {
|
||||
':action(edit|delete)': {
|
||||
title: t('Edit'),
|
||||
link: params => `/templates/${params.templateId}/edit`,
|
||||
visible: resolved => resolved.template.permissions.includes('edit'),
|
||||
panelRender: props => <TemplatesCUD action={props.match.params.action} entity={props.resolved.template} />
|
||||
},
|
||||
share: {
|
||||
title: t('Share'),
|
||||
link: params => `/templates/${params.templateId}/share`,
|
||||
visible: resolved => resolved.template.permissions.includes('share'),
|
||||
panelRender: props => <Share title={t('Share')} entity={props.resolved.template} entityTypeId="template" />
|
||||
}
|
||||
}
|
||||
visible: resolved => resolved.template.permissions.includes('edit'),
|
||||
panelRender: props => <TemplatesCUD action={props.match.params.action} entity={props.resolved.template} />
|
||||
},
|
||||
create: {
|
||||
title: t('Create'),
|
||||
panelRender: props => <TemplatesCUD action="create" />
|
||||
share: {
|
||||
title: t('Share'),
|
||||
link: params => `/templates/${params.templateId}/share`,
|
||||
visible: resolved => resolved.template.permissions.includes('share'),
|
||||
panelRender: props => <Share title={t('Share')} entity={props.resolved.template} entityTypeId="template" />
|
||||
}
|
||||
}
|
||||
},
|
||||
create: {
|
||||
title: t('Create'),
|
||||
panelRender: props => <TemplatesCUD action="create" />
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default function() {
|
||||
ReactDOM.render(
|
||||
<I18nextProvider i18n={ i18n }><Section root='/templates' structure={getStructure}/></I18nextProvider>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
getMenus
|
||||
}
|
||||
|
|
|
@ -10,52 +10,41 @@ import CUD from './CUD';
|
|||
import List from './List';
|
||||
import UserShares from '../shares/UserShares';
|
||||
|
||||
const getStructure = t => {
|
||||
function getMenus(t) {
|
||||
return {
|
||||
'': {
|
||||
title: t('Home'),
|
||||
externalLink: '/',
|
||||
'users': {
|
||||
title: t('Users'),
|
||||
link: '/users',
|
||||
panelComponent: List,
|
||||
children: {
|
||||
users: {
|
||||
title: t('Users'),
|
||||
link: '/users',
|
||||
panelComponent: List,
|
||||
children: {
|
||||
':userId([0-9]+)': {
|
||||
title: resolved => t('User "{{name}}"', {name: resolved.user.name}),
|
||||
resolve: {
|
||||
user: params => `/rest/users/${params.userId}`
|
||||
},
|
||||
':userId([0-9]+)': {
|
||||
title: resolved => t('User "{{name}}"', {name: resolved.user.name}),
|
||||
resolve: {
|
||||
user: params => `/rest/users/${params.userId}`
|
||||
},
|
||||
link: params => `/users/${params.userId}/edit`,
|
||||
navs: {
|
||||
':action(edit|delete)': {
|
||||
title: t('Edit'),
|
||||
link: params => `/users/${params.userId}/edit`,
|
||||
navs: {
|
||||
':action(edit|delete)': {
|
||||
title: t('Edit'),
|
||||
link: params => `/users/${params.userId}/edit`,
|
||||
panelRender: props => <CUD action={props.match.params.action} entity={props.resolved.user} />
|
||||
},
|
||||
shares: {
|
||||
title: t('Shares'),
|
||||
link: params => `/users/${params.userId}/shares`,
|
||||
panelRender: props => <UserShares user={props.resolved.user} />
|
||||
}
|
||||
}
|
||||
},
|
||||
create: {
|
||||
title: t('Create'),
|
||||
panelRender: props => <CUD action="create" />
|
||||
panelRender: props => <CUD action={props.match.params.action} entity={props.resolved.user} />
|
||||
},
|
||||
shares: {
|
||||
title: t('Shares'),
|
||||
link: params => `/users/${params.userId}/shares`,
|
||||
panelRender: props => <UserShares user={props.resolved.user} />
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
create: {
|
||||
title: t('Create'),
|
||||
panelRender: props => <CUD action="create" />
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export default function() {
|
||||
ReactDOM.render(
|
||||
<I18nextProvider i18n={ i18n }><Section root='/users' structure={getStructure}/></I18nextProvider>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
export default {
|
||||
getMenus
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue