Some refactoring to aling it more with IVIS and coreui theme.
174
client/package-lock.json
generated
|
@ -1856,15 +1856,6 @@
|
|||
"readable-stream": "^2.0.6"
|
||||
}
|
||||
},
|
||||
"argparse": {
|
||||
"version": "1.0.9",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz",
|
||||
"integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"sprintf-js": "~1.0.2"
|
||||
}
|
||||
},
|
||||
"arr-diff": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
|
||||
|
@ -4516,11 +4507,13 @@
|
|||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
|
@ -4537,7 +4530,8 @@
|
|||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"bundled": true
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
|
@ -4666,6 +4660,7 @@
|
|||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
|
@ -6132,24 +6127,6 @@
|
|||
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.0.0-rc.12.tgz",
|
||||
"integrity": "sha512-0M2XxkZLx/mi3t8NVwIm1g8nHoEmM9p9UBl/G9k4+hm0kBgOVdMV/B3CY5dQ8qG8qc80NN4gDV4HQv6FTJ5q7A=="
|
||||
},
|
||||
"import-cwd": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz",
|
||||
"integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"import-from": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"import-from": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz",
|
||||
"integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"resolve-from": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"import-lazy": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz",
|
||||
|
@ -6428,12 +6405,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"is-directory": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
|
||||
"integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=",
|
||||
"dev": true
|
||||
},
|
||||
"is-dotfile": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
|
||||
|
@ -9202,6 +9173,11 @@
|
|||
"find-up": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"popper.js": {
|
||||
"version": "1.14.6",
|
||||
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.14.6.tgz",
|
||||
"integrity": "sha512-AGwHGQBKumlk/MDfrSOf0JHhJCImdDMcGNoqKmKkU+68GFazv3CQ6q9r7Ja1sKDZmYWTckY/uLyEznheTDycnA=="
|
||||
},
|
||||
"posix-character-classes": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
|
||||
|
@ -9256,122 +9232,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"postcss-load-config": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.0.0.tgz",
|
||||
"integrity": "sha512-V5JBLzw406BB8UIfsAWSK2KSwIJ5yoEIVFb4gVkXci0QdKgA24jLmHZ/ghe/GgX0lJ0/D1uUK1ejhzEY94MChQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cosmiconfig": "^4.0.0",
|
||||
"import-cwd": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"cosmiconfig": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-4.0.0.tgz",
|
||||
"integrity": "sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-directory": "^0.3.1",
|
||||
"js-yaml": "^3.9.0",
|
||||
"parse-json": "^4.0.0",
|
||||
"require-from-string": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"esprima": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
|
||||
"dev": true
|
||||
},
|
||||
"js-yaml": {
|
||||
"version": "3.12.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz",
|
||||
"integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"argparse": "^1.0.7",
|
||||
"esprima": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"parse-json": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
|
||||
"integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"error-ex": "^1.3.1",
|
||||
"json-parse-better-errors": "^1.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"postcss-loader": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz",
|
||||
"integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loader-utils": "^1.1.0",
|
||||
"postcss": "^7.0.0",
|
||||
"postcss-load-config": "^2.0.0",
|
||||
"schema-utils": "^1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-convert": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
|
||||
"integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
}
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
|
||||
"dev": true
|
||||
},
|
||||
"postcss": {
|
||||
"version": "7.0.5",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.5.tgz",
|
||||
"integrity": "sha512-HBNpviAUFCKvEh7NZhw1e8MBPivRszIiUnhrJ+sBFVSYSqubrzwX3KG51mYgcRHX8j/cAgZJedONZcm5jTBdgQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^2.4.1",
|
||||
"source-map": "^0.6.1",
|
||||
"supports-color": "^5.5.0"
|
||||
}
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"postcss-modules-extract-imports": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz",
|
||||
|
@ -10191,12 +10051,6 @@
|
|||
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
|
||||
"dev": true
|
||||
},
|
||||
"require-from-string": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
|
||||
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
|
||||
"dev": true
|
||||
},
|
||||
"require-main-filename": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
|
||||
|
@ -10763,12 +10617,6 @@
|
|||
"extend-shallow": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"sprintf-js": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
|
||||
"dev": true
|
||||
},
|
||||
"sshpk": {
|
||||
"version": "1.15.2",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz",
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
"js": "webpack",
|
||||
"watch-js": "webpack --watch",
|
||||
"css": "npm-run-all --sequential css-compile css-minify",
|
||||
"css-compile": "node-sass --output-style expanded --source-map true --source-map-contents true --precision 6 static/scss/mailtrain.scss dist/mailtrain.css",
|
||||
"css-compile": "node-sass --output-style expanded --source-map true --source-map-contents true --precision 6 src/scss/mailtrain.scss dist/mailtrain.css",
|
||||
"css-minify": "cleancss --level 1 --source-map --source-map-inline-sources --output dist/mailtrain.min.css dist/mailtrain.css",
|
||||
"watch-css": "nodemon --watch static/scss -e scss -x \"npm run css\"",
|
||||
"watch-css": "nodemon --watch src/scss -e scss -x \"npm run css\"",
|
||||
"watch": "npm-run-all --parallel watch-css watch-js",
|
||||
"build": "npm-run-all --parallel css js"
|
||||
},
|
||||
|
@ -23,6 +23,7 @@
|
|||
"@coreui/coreui": "^2.1.4",
|
||||
"@fortawesome/fontawesome-free": "^5.6.3",
|
||||
"axios": "^0.18.0",
|
||||
"bootstrap": "^4.2.1",
|
||||
"datatables.net": "^1.10.19",
|
||||
"datatables.net-bs4": "^1.10.19",
|
||||
"grapesjs": "^0.14.50",
|
||||
|
@ -35,6 +36,7 @@
|
|||
"mjml4-in-browser": "^1.0.1",
|
||||
"moment": "^2.23.0",
|
||||
"moment-timezone": "^0.5.23",
|
||||
"popper.js": "^1.14.6",
|
||||
"prop-types": "^15.6.2",
|
||||
"querystringify": "^2.1.0",
|
||||
"react": "^16.7.0",
|
||||
|
@ -69,7 +71,6 @@
|
|||
"node-sass": "^4.11.0",
|
||||
"nodemon": "^1.18.9",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"postcss-loader": "^3.0.0",
|
||||
"sass-loader": "^7.1.0",
|
||||
"style-loader": "^0.23.1",
|
||||
"url-loader": "^1.1.2",
|
||||
|
|
|
@ -1,51 +1,27 @@
|
|||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import Account from './Account';
|
||||
import Login from './Login';
|
||||
import Reset from './Forgot';
|
||||
import ResetLink from './Reset';
|
||||
import API from './API';
|
||||
import mailtrainConfig from 'mailtrainConfig';
|
||||
import React
|
||||
from 'react';
|
||||
import Account
|
||||
from './Account';
|
||||
import API
|
||||
from './API';
|
||||
|
||||
|
||||
function getMenus(t) {
|
||||
const subPaths = {
|
||||
login: {
|
||||
title: t('signIn'),
|
||||
link: '/account/login',
|
||||
panelComponent: Login,
|
||||
},
|
||||
api: {
|
||||
title: t('api'),
|
||||
link: '/account/api',
|
||||
panelComponent: API
|
||||
}
|
||||
};
|
||||
|
||||
if (mailtrainConfig.isAuthMethodLocal) {
|
||||
subPaths.forgot = {
|
||||
title: t('passwordReset-1'),
|
||||
extraParams: [':username?'],
|
||||
link: '/account/forgot',
|
||||
panelComponent: Reset
|
||||
};
|
||||
|
||||
subPaths.reset = {
|
||||
title: t('passwordReset-1'),
|
||||
extraParams: [':username', ':resetToken'],
|
||||
link: '/account/reset',
|
||||
panelComponent: ResetLink
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
'account': {
|
||||
title: t('account'),
|
||||
link: '/account',
|
||||
panelComponent: Account,
|
||||
|
||||
children: subPaths
|
||||
children: {
|
||||
api: {
|
||||
title: t('api'),
|
||||
link: '/account/api',
|
||||
panelComponent: API
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
27
client/src/lib/bootstrap-components.js
vendored
|
@ -114,7 +114,6 @@ class Button extends Component {
|
|||
class ButtonDropdown extends Component {
|
||||
static propTypes = {
|
||||
label: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
|
||||
noCaret: PropTypes.bool,
|
||||
className: PropTypes.string,
|
||||
buttonClassName: PropTypes.string,
|
||||
menuClassName: PropTypes.string
|
||||
|
@ -170,6 +169,30 @@ class ActionLink extends Component {
|
|||
}
|
||||
|
||||
|
||||
class ButtonDropdownActionLink extends Component {
|
||||
static propTypes = {
|
||||
onClickAsync: PropTypes.func,
|
||||
className: PropTypes.string,
|
||||
disabled: PropTypes.bool
|
||||
}
|
||||
|
||||
render() {
|
||||
const props = this.props;
|
||||
|
||||
let clsName = "dropdown-item ";
|
||||
if (props.disabled) {
|
||||
clsName += "disabled ";
|
||||
}
|
||||
|
||||
clsName += props.className;
|
||||
|
||||
return (
|
||||
<ActionLink className={clsName} onClickAsync={props.onClickAsync}>{props.children}</ActionLink>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@withComponentMixins([
|
||||
withTranslation,
|
||||
withErrorHandling
|
||||
|
@ -289,8 +312,8 @@ class ModalDialog extends Component {
|
|||
export {
|
||||
Button,
|
||||
ButtonDropdown,
|
||||
DropdownMenuItem,
|
||||
ActionLink,
|
||||
ButtonDropdownActionLink,
|
||||
DismissibleAlert,
|
||||
ModalDialog,
|
||||
Icon
|
||||
|
|
|
@ -262,6 +262,8 @@ class RouteContent extends Component {
|
|||
|
||||
const primaryMenuComponent = React.createElement(route.primaryMenuComponent, primaryMenuProps);
|
||||
|
||||
let content = null;
|
||||
|
||||
if (resolved) {
|
||||
const compProps = {
|
||||
match: this.props.match,
|
||||
|
@ -276,10 +278,8 @@ class RouteContent extends Component {
|
|||
panel = route.panelRender(compProps);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{primaryMenuComponent}
|
||||
|
||||
content = (
|
||||
<>
|
||||
<div className={styles.breadcrumbAndSecondaryNavbar}>
|
||||
<Breadcrumb route={route} params={params} resolved={resolved}/>
|
||||
<SecondaryNavBar route={route} params={params} resolved={resolved}/>
|
||||
|
@ -289,18 +289,33 @@ class RouteContent extends Component {
|
|||
{this.props.flashMessage}
|
||||
{panel}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<div>
|
||||
{primaryMenuComponent}
|
||||
<div className="container-fluid">
|
||||
{t('loading')}
|
||||
</div>
|
||||
content = (
|
||||
<div className="container-fluid">
|
||||
{t('loading')}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="app">
|
||||
<header className="app-header">
|
||||
{primaryMenuComponent}
|
||||
</header>
|
||||
|
||||
<div className="app-body">
|
||||
<main className="main">
|
||||
{content}
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer className="app-footer">
|
||||
<div 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('sourceOnGitHub')}</a></div>
|
||||
</footer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -350,14 +365,14 @@ export class SectionContent extends Component {
|
|||
|
||||
ensureAuthenticated() {
|
||||
if (!mailtrainConfig.isAuthenticated) {
|
||||
this.navigateTo('/account/login?next=' + encodeURIComponent(window.location.pathname));
|
||||
this.navigateTo('/login?next=' + encodeURIComponent(window.location.pathname));
|
||||
}
|
||||
}
|
||||
|
||||
errorHandler(error) {
|
||||
if (error instanceof interoperableErrors.NotLoggedInError) {
|
||||
if (window.location.pathname !== '/account/login') { // There may be multiple async requests failing at the same time. So we take the pathname only from the first one.
|
||||
this.navigateTo('/account/login?next=' + encodeURIComponent(window.location.pathname));
|
||||
if (window.location.pathname !== '/login') { // There may be multiple async requests failing at the same time. So we take the pathname only from the first one.
|
||||
this.navigateTo('/login?next=' + encodeURIComponent(window.location.pathname));
|
||||
}
|
||||
} else if (error.response && error.response.data && error.response.data.message) {
|
||||
console.error(error);
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
|
||||
import {getUrl} from "./urls";
|
||||
|
||||
__webpack_public_path__ = getUrl('mailtrain/');
|
||||
__webpack_public_path__ = getUrl('client/');
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@import "../../static/scss/variables";
|
||||
@import "../scss/variables.scss";
|
||||
|
||||
.form { // This is here to give the styles below higher priority than Bootstrap has
|
||||
:global .DayPicker {
|
||||
|
|
|
@ -9,9 +9,9 @@ import PropTypes
|
|||
|
||||
import jQuery
|
||||
from 'jquery';
|
||||
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 '../../static/jquery/jquery-ui-1.12.1.min.js';
|
||||
import '../../static/fancytree/jquery.fancytree-all.min.js';
|
||||
import '../../static/fancytree/skin-bootstrap/ui.fancytree.min.css';
|
||||
import './tree.scss';
|
||||
import axios
|
||||
from './axios';
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@import "../../static/scss/variables.scss";
|
||||
@import "../scss/variables.scss";
|
||||
|
||||
:global {
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ export default class Forget extends Component {
|
|||
const submitSuccessful = await this.validateAndSendFormValuesToURL(FormSendMethod.POST, 'rest/password-reset-send');
|
||||
|
||||
if (submitSuccessful) {
|
||||
this.navigateToWithFlashMessage('/account/login', 'success', t('ifTheUsernameEmailExistsInTheSystem'));
|
||||
this.navigateToWithFlashMessage('/login', 'success', t('ifTheUsernameEmailExistsInTheSystem'));
|
||||
} else {
|
||||
this.enableForm();
|
||||
this.setFormStatusMessage('warning', t('pleaseEnterYourUsernameEmailAndTryAgain'));
|
|
@ -106,7 +106,7 @@ export default class Login extends Component {
|
|||
|
||||
let passwordResetLink;
|
||||
if (mailtrainConfig.isAuthMethodLocal) {
|
||||
passwordResetLink = <Link to={`/account/forgot/${this.getFormValue('username')}`}>{t('forgotYourPassword?')}</Link>;
|
||||
passwordResetLink = <Link to={`/login/forgot/${this.getFormValue('username')}`}>{t('forgotYourPassword?')}</Link>;
|
||||
} else if (mailtrainConfig.externalPasswordResetLink) {
|
||||
passwordResetLink = <a href={mailtrainConfig.externalPasswordResetLink}>{t('forgotYourPassword?')}</a>;
|
||||
}
|
|
@ -114,7 +114,7 @@ export default class Account extends Component {
|
|||
});
|
||||
|
||||
if (submitSuccessful) {
|
||||
this.navigateToWithFlashMessage('/account/login', 'success', t('passwordReset-1'));
|
||||
this.navigateToWithFlashMessage('/login', 'success', t('passwordReset-1'));
|
||||
} else {
|
||||
this.enableForm();
|
||||
this.setFormStatusMessage('warning', t('thereAreErrorsInTheFormPleaseFixThemAnd'));
|
||||
|
@ -124,7 +124,7 @@ export default class Account extends Component {
|
|||
this.setFormStatusMessage('danger',
|
||||
<span>
|
||||
<strong>{t('yourPasswordCannotBeReset')}</strong>{' '}
|
||||
{t('thePasswordResetTokenHasExpired')}{' '}<Link to={`/account/forgot/${this.getFormValue('username')}`}>{t('clickHereToRequestANewPasswordResetLink')}</Link>
|
||||
{t('thePasswordResetTokenHasExpired')}{' '}<Link to={`/login/forgot/${this.getFormValue('username')}`}>{t('clickHereToRequestANewPasswordResetLink')}</Link>
|
||||
</span>
|
||||
);
|
||||
return;
|
||||
|
@ -147,7 +147,7 @@ export default class Account extends Component {
|
|||
<div>
|
||||
<Title>{t('thePasswordCannotBeReset')}</Title>
|
||||
|
||||
<p>{t('thePasswordResetTokenHasExpired')}{' '}<Link to={`/account/forgot/${this.getFormValue('username')}`}>{t('clickHereToRequestANewPasswordResetLink')}</Link></p>
|
||||
<p>{t('thePasswordResetTokenHasExpired')}{' '}<Link to={`/login/forgot/${this.getFormValue('username')}`}>{t('clickHereToRequestANewPasswordResetLink')}</Link></p>
|
||||
</div>
|
||||
);
|
||||
|
47
client/src/login/root.js
Normal file
|
@ -0,0 +1,47 @@
|
|||
'use strict';
|
||||
|
||||
import React
|
||||
from 'react';
|
||||
import Login
|
||||
from './Login';
|
||||
import Reset
|
||||
from './Forgot';
|
||||
import ResetLink
|
||||
from './Reset';
|
||||
import mailtrainConfig
|
||||
from 'mailtrainConfig';
|
||||
|
||||
|
||||
function getMenus(t) {
|
||||
const subPaths = {}
|
||||
|
||||
if (mailtrainConfig.isAuthMethodLocal) {
|
||||
subPaths.forgot = {
|
||||
title: t('passwordReset-1'),
|
||||
extraParams: [':username?'],
|
||||
link: '/login/forgot',
|
||||
panelComponent: Reset
|
||||
};
|
||||
|
||||
subPaths.reset = {
|
||||
title: t('passwordReset-1'),
|
||||
extraParams: [':username', ':resetToken'],
|
||||
link: '/login/reset',
|
||||
panelComponent: ResetLink
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
'login': {
|
||||
title: t('signIn'),
|
||||
link: '/login',
|
||||
panelComponent: Login,
|
||||
|
||||
children: subPaths
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
getMenus
|
||||
}
|
|
@ -9,6 +9,8 @@ import {I18nextProvider} from 'react-i18next';
|
|||
import i18n, {withTranslation} from './lib/i18n';
|
||||
import account
|
||||
from './account/root';
|
||||
import login
|
||||
from './login/root';
|
||||
import blacklist
|
||||
from './blacklist/root';
|
||||
import lists
|
||||
|
@ -41,6 +43,7 @@ import Home
|
|||
from "./Home";
|
||||
import {
|
||||
ActionLink,
|
||||
ButtonDropdownActionLink,
|
||||
Icon
|
||||
} from "./lib/bootstrap-components";
|
||||
import {Link} from "react-router-dom";
|
||||
|
@ -89,7 +92,7 @@ class Root extends Component {
|
|||
const label = langDesc.getLabel(t);
|
||||
|
||||
languageOptions.push(
|
||||
<ActionLink key={lng} className="dropdown-item" onClickAsync={() => i18n.changeLanguage(langDesc.longCode)}>{label}</ActionLink>
|
||||
<ButtonDropdownActionLink key={lng} onClickAsync={() => i18n.changeLanguage(langDesc.longCode)}>{label}</ButtonDropdownActionLink>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -166,6 +169,7 @@ class Root extends Component {
|
|||
panelComponent: Home,
|
||||
primaryMenuComponent: MainMenu,
|
||||
children: {
|
||||
...login.getMenus(t),
|
||||
...lists.getMenus(t),
|
||||
...reports.getMenus(t),
|
||||
...templates.getMenus(t),
|
||||
|
@ -180,15 +184,7 @@ class Root extends Component {
|
|||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Section root='/' structure={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('sourceOnGitHub')}</a></p>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<Section root='/' structure={structure}/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
51
client/src/scss/mailtrain.scss
Normal file
|
@ -0,0 +1,51 @@
|
|||
$fa-font-path: "../static-npm/fontawesome";
|
||||
|
||||
@import "./variables.scss";
|
||||
@import "node_modules/@coreui/coreui/scss/coreui.scss";
|
||||
@import "node_modules/@fortawesome/fontawesome-free/scss/fontawesome.scss";
|
||||
@import "node_modules/@fortawesome/fontawesome-free/scss/regular.scss";
|
||||
@import "node_modules/@fortawesome/fontawesome-free/scss/solid.scss";
|
||||
|
||||
.custom-select {
|
||||
-webkit-appearance: none; // This is a fix for Chrome
|
||||
}
|
||||
|
||||
body.mailtrain {
|
||||
background-color: white;
|
||||
|
||||
.app-header {
|
||||
height: auto;
|
||||
padding: 0;
|
||||
flex: none;
|
||||
border-bottom: 0px none;
|
||||
|
||||
.navbar-brand {
|
||||
width: auto;
|
||||
height: auto;
|
||||
display: inline-block;
|
||||
padding-top: $navbar-brand-padding-y;
|
||||
padding-bottom: $navbar-brand-padding-y;
|
||||
margin-right: $navbar-padding-x;
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
min-width: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.main .container-fluid {
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
.navbar-dark {
|
||||
.navbar-nav {
|
||||
.active > .nav-link:hover {
|
||||
color: $navbar-dark-active-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.gpg-text {
|
||||
font-family: monospace;
|
||||
}
|
||||
}
|
|
@ -607,7 +607,7 @@ export function getEditForm(owner, typeKey, prefix = '') {
|
|||
height="400px"
|
||||
mode="text"
|
||||
label={t('templateContentPlainText')}
|
||||
help={<Trans i18nKey="toExtractTheTextFromHtmlClickHerePlease">To extract the text from HTML click <ActionLink onClickAsync={::owner.extractPlainText}>here</ActionLink>. Please note that your existing plaintext in the field above will be overwritten. This feature uses the <a href="http://premailer.dialect.ca/api">Premailer API</a>, a third party service. Their Terms of Service and Privacy Policy apply.</Trans>}
|
||||
help={<Trans i18nKey="toExtractTheTextFromHtmlClickHerePlease">To extract the text from HTML click <ActionLink onClickAsync={::owner.extractPlainText}>here</ActionLink>. Please note that your existing plaintext in the field above will be overwritten. This feature uses the <a href="http://premailer.dialect.ca/api">Premailer API</a>, a third party service. Their Terms of Service and Privacy Policy apply.</Trans>}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 842 B After Width: | Height: | Size: 842 B |
Before Width: | Height: | Size: 844 B After Width: | Height: | Size: 844 B |
2
client/static/jquery-3.3.1.min.js
vendored
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
FIXME - remove
|
||||
@media screen and (min-width: 768px) {
|
||||
.dl-horizontal dt {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.dl-horizontal dd {
|
||||
margin-left: 220px;
|
||||
}
|
||||
}
|
||||
|
||||
h2 .glyphicon {
|
||||
font-size: .75em;
|
||||
}
|
||||
h3 .glyphicon {
|
||||
font-size: .8em;
|
||||
}
|
||||
|
||||
tbody>tr.selected {
|
||||
background-color: rgb(218, 231, 255);
|
||||
}
|
||||
|
||||
.table-hover>tbody>tr.selected:hover {
|
||||
background-color: rgb(205, 212, 226);
|
||||
}
|
||||
|
||||
.row-actions .row-action {
|
||||
padding-right: 15px;
|
||||
}
|
||||
|
||||
.row-actions .row-action:last-child {
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
$fa-font-path: "../static-npm/fontawesome";
|
||||
|
||||
@import "./variables.scss";
|
||||
@import "node_modules/@coreui/coreui/scss/coreui.scss";
|
||||
@import "node_modules/@fortawesome/fontawesome-free/scss/fontawesome.scss";
|
||||
@import "node_modules/@fortawesome/fontawesome-free/scss/regular.scss";
|
||||
@import "node_modules/@fortawesome/fontawesome-free/scss/solid.scss";
|
||||
|
||||
html {
|
||||
position: relative;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.custom-select {
|
||||
-webkit-appearance: none; // This is a fix for Chrome
|
||||
}
|
||||
|
||||
body.mailtrain {
|
||||
margin-bottom: 90px;
|
||||
background-color: white;
|
||||
|
||||
.navbar-dark {
|
||||
.navbar-nav {
|
||||
.active > .nav-link:hover {
|
||||
color: $navbar-dark-active-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
background-color: #f5f5f5;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.footer .text-muted {
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.gpg-text {
|
||||
font-family: monospace;
|
||||
}
|
||||
}
|
1120
mvis/client/package-lock.json
generated
|
@ -4,8 +4,14 @@
|
|||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build": "node ../ivis-core/client/pre-build.js && webpack",
|
||||
"watch": "node ../ivis-core/client/pre-build.js && webpack --watch"
|
||||
"js": "webpack",
|
||||
"watch-js": "webpack --watch",
|
||||
"css": "npm-run-all --sequential css-compile css-minify",
|
||||
"css-compile": "node-sass --output-style expanded --source-map true --source-map-contents true --precision 6 ../ivis-core/client/src/scss/ivis.scss ../ivis-core/client/dist/ivis.css",
|
||||
"css-minify": "cleancss --level 1 --source-map --source-map-inline-sources --output ../ivis-core/client/dist/ivis.min.css ../ivis-core/client/dist/ivis.css",
|
||||
"watch-css": "nodemon --watch ../ivis-core/client/src/scss -e scss -x \"npm run css\"",
|
||||
"watch": "node ../ivis-core/client/pre-build.js && npm-run-all --parallel watch-css watch-js",
|
||||
"build": "node ../ivis-core/client/pre-build.js && npm-run-all --parallel css js"
|
||||
},
|
||||
"author": "Tomas Bures",
|
||||
"license": "MIT",
|
||||
|
@ -18,9 +24,12 @@
|
|||
"@babel/preset-env": "^7.2.3",
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"babel-loader": "^8.0.4",
|
||||
"clean-css-cli": "^4.2.1",
|
||||
"css-loader": "^2.1.0",
|
||||
"file-loader": "^3.0.1",
|
||||
"node-sass": "^4.11.0",
|
||||
"nodemon": "^1.18.9",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"sass-loader": "^7.1.0",
|
||||
"style-loader": "^0.23.1",
|
||||
"url-loader": "^1.1.2",
|
||||
|
|
|
@ -5,7 +5,7 @@ require('./extensions-common');
|
|||
const config = require('../ivis-core/server/lib/config');
|
||||
|
||||
module.exports = {
|
||||
client: 'mysql2',
|
||||
client: 'mysql',
|
||||
connection: config.mysql,
|
||||
seeds: {
|
||||
directory: '../ivis-core/server/knex/seeds'
|
||||
|
|
118
mvis/server/package-lock.json
generated
|
@ -176,6 +176,11 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"bignumber.js": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-4.1.0.tgz",
|
||||
"integrity": "sha512-eJzYkFYy9L4JzXsbymsFn3p54D+llV27oTQ+ziJG7WFRheJcNZilgVXMG0LoZtlQSKBsJdWtLFqOD0u+U0jZKA=="
|
||||
},
|
||||
"bluebird": {
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz",
|
||||
|
@ -367,11 +372,6 @@
|
|||
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
|
||||
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
|
||||
},
|
||||
"denque": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/denque/-/denque-1.3.0.tgz",
|
||||
"integrity": "sha512-4SRaSj+PqmrS1soW5/Avd7eJIM2JJIqLLmwhRqIGleZM/8KwZq80njbSS2Iqas+6oARkSkLDHEk4mm78q3JlIg=="
|
||||
},
|
||||
"detect-file": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz",
|
||||
|
@ -611,14 +611,6 @@
|
|||
"wide-align": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"generate-function": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
|
||||
"integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
|
||||
"requires": {
|
||||
"is-property": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"get-value": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
|
||||
|
@ -693,14 +685,6 @@
|
|||
"parse-passwd": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"iconv-lite": {
|
||||
"version": "0.4.24",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
|
||||
"requires": {
|
||||
"safer-buffer": ">= 2.1.2 < 3"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||
|
@ -835,11 +819,6 @@
|
|||
"isobject": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"is-property": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
|
||||
"integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ="
|
||||
},
|
||||
"is-relative": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz",
|
||||
|
@ -949,20 +928,6 @@
|
|||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
|
||||
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
|
||||
},
|
||||
"long": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
|
||||
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz",
|
||||
"integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==",
|
||||
"requires": {
|
||||
"pseudomap": "^1.0.2",
|
||||
"yallist": "^2.1.2"
|
||||
}
|
||||
},
|
||||
"make-iterator": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz",
|
||||
|
@ -1061,36 +1026,17 @@
|
|||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
},
|
||||
"mysql2": {
|
||||
"version": "1.6.4",
|
||||
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-1.6.4.tgz",
|
||||
"integrity": "sha512-ZYbYgK06HKfxU45tYYLfwW5gKt8BslfE7FGyULNrf2K2fh+DuEX+e0QKsd2ObpZkMILefaVn8hsakVsTFqravQ==",
|
||||
"mysql": {
|
||||
"version": "2.16.0",
|
||||
"resolved": "https://registry.npmjs.org/mysql/-/mysql-2.16.0.tgz",
|
||||
"integrity": "sha512-dPbN2LHonQp7D5ja5DJXNbCLe/HRdu+f3v61aguzNRQIrmZLOeRoymBYyeThrR6ug+FqzDL95Gc9maqZUJS+Gw==",
|
||||
"requires": {
|
||||
"denque": "1.3.0",
|
||||
"generate-function": "^2.3.1",
|
||||
"iconv-lite": "^0.4.24",
|
||||
"long": "^4.0.0",
|
||||
"lru-cache": "4.1.3",
|
||||
"named-placeholders": "1.1.1",
|
||||
"seq-queue": "0.0.5",
|
||||
"bignumber.js": "4.1.0",
|
||||
"readable-stream": "2.3.6",
|
||||
"safe-buffer": "5.1.2",
|
||||
"sqlstring": "2.3.1"
|
||||
}
|
||||
},
|
||||
"named-placeholders": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "http://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.1.tgz",
|
||||
"integrity": "sha1-O3oNJiA910s6nfTJz7gnsvuQfmQ=",
|
||||
"requires": {
|
||||
"lru-cache": "2.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"lru-cache": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "http://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz",
|
||||
"integrity": "sha1-2COIrpyWC+y+oMc7uet5tsbOmus="
|
||||
}
|
||||
}
|
||||
},
|
||||
"nanomatch": {
|
||||
"version": "1.2.13",
|
||||
"resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
|
||||
|
@ -1252,10 +1198,19 @@
|
|||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
|
||||
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
|
||||
},
|
||||
"pseudomap": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
|
||||
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
|
||||
"readable-stream": {
|
||||
"version": "2.3.6",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
|
||||
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
|
||||
"requires": {
|
||||
"core-util-is": "~1.0.0",
|
||||
"inherits": "~2.0.3",
|
||||
"isarray": "~1.0.0",
|
||||
"process-nextick-args": "~2.0.0",
|
||||
"safe-buffer": "~5.1.1",
|
||||
"string_decoder": "~1.1.1",
|
||||
"util-deprecate": "~1.0.1"
|
||||
}
|
||||
},
|
||||
"rechoir": {
|
||||
"version": "0.6.2",
|
||||
|
@ -1329,16 +1284,6 @@
|
|||
"ret": "~0.1.10"
|
||||
}
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"seq-queue": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz",
|
||||
"integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4="
|
||||
},
|
||||
"set-blocking": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
|
||||
|
@ -1544,6 +1489,14 @@
|
|||
"strip-ansi": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||
"requires": {
|
||||
"safe-buffer": "~5.1.0"
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
|
@ -1727,11 +1680,6 @@
|
|||
"requires": {
|
||||
"string-width": "^1.0.2 || 2"
|
||||
}
|
||||
},
|
||||
"yallist": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
|
||||
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
"knex": "^0.16.3",
|
||||
"moment": "^2.18.1",
|
||||
"moment-timezone": "^0.5.21",
|
||||
"mysql2": "^1.3.5",
|
||||
"mysql": "^2.16.0",
|
||||
"npmlog": "^4.0.2"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -233,9 +233,10 @@ function createApp(appType) {
|
|||
}
|
||||
|
||||
useWith404Fallback('/static', express.static(path.join(__dirname, '..', 'client', 'static')));
|
||||
useWith404Fallback('/mailtrain', express.static(path.join(__dirname, '..', 'client', 'dist')));
|
||||
useWith404Fallback('/client', express.static(path.join(__dirname, '..', 'client', 'dist')));
|
||||
|
||||
useWith404Fallback('/static-npm/fontawesome', express.static(path.join(__dirname, '..', 'client', 'node_modules', '@fortawesome', 'fontawesome-free', 'webfonts')));
|
||||
useWith404Fallback('/static-npm/jquery.min.js', express.static(path.join(__dirname, '..', 'client', 'node_modules', 'jquery', 'dist', 'jquery.min.js')));
|
||||
useWith404Fallback('/static-npm/popper.min.js', express.static(path.join(__dirname, '..', 'client', 'node_modules', 'popper.js', 'dist', 'umd', 'popper.min.js')));
|
||||
useWith404Fallback('/static-npm/bootstrap.min.js', express.static(path.join(__dirname, '..', 'client', 'node_modules', 'bootstrap', 'dist', 'js', 'bootstrap.min.js')));
|
||||
useWith404Fallback('/static-npm/coreui.min.js', express.static(path.join(__dirname, '..', 'client', 'node_modules', '@coreui', 'coreui', 'dist', 'js', 'coreui.min.js')));
|
||||
|
@ -351,7 +352,7 @@ function createApp(appType) {
|
|||
|
||||
} else {
|
||||
if (err instanceof interoperableErrors.NotLoggedInError) {
|
||||
return res.redirect(getTrustedUrl('/account/login?next=' + encodeURIComponent(req.originalUrl)));
|
||||
return res.redirect(getTrustedUrl('/login?next=' + encodeURIComponent(req.originalUrl)));
|
||||
} else {
|
||||
res.status(err.status || 500);
|
||||
res.render('error', {
|
||||
|
@ -395,7 +396,7 @@ function createApp(appType) {
|
|||
// TODO: Render interoperable errors using a special client that does internationalization of the error message
|
||||
|
||||
if (err instanceof interoperableErrors.NotLoggedInError) {
|
||||
return res.redirect(getTrustedUrl('/account/login?next=' + encodeURIComponent(req.originalUrl)));
|
||||
return res.redirect(getTrustedUrl('/login?next=' + encodeURIComponent(req.originalUrl)));
|
||||
} else {
|
||||
res.status(err.status || 500);
|
||||
res.render('error', {
|
||||
|
|
|
@ -225,11 +225,16 @@ seleniumWebDriver:
|
|||
roles:
|
||||
global:
|
||||
master:
|
||||
name: Master
|
||||
name: Global Master
|
||||
admin: true
|
||||
description: All permissions
|
||||
permissions: [rebuildPermissions, createJavascriptWithROAccess, manageBlacklist, manageSettings, setupAutomation]
|
||||
rootNamespaceRole: master
|
||||
campaignsAdmin:
|
||||
name: Campaigns Admin
|
||||
description: Under the namespace in which the user is located, the user has all permissions for managing lists, templates and campaigns and the permission to send to send configurations.
|
||||
permissions: [setupAutomation]
|
||||
ownNamespaceRole: campaignsAdmin
|
||||
nobody:
|
||||
name: None
|
||||
description: No permissions
|
||||
|
@ -251,6 +256,21 @@ roles:
|
|||
mosaicoTemplate: [view, edit, delete, share, viewFiles, manageFiles]
|
||||
namespace: [view, edit, delete, share, createNamespace, createList, createCustomForm, createReport, createReportTemplate, createTemplate, createMosaicoTemplate, createSendConfiguration, createCampaign, manageUsers]
|
||||
|
||||
campaignsAdmin:
|
||||
name: Campaigns Admin
|
||||
description: Under the namespace in which the user is located, the user has all permissions for managing lists, templates and campaigns and the permission to send to send configurations.
|
||||
permissions: [view, edit, delete, share, createNamespace, createList, createCustomForm, createReport, createTemplate, createMosaicoTemplate, createCampaign]
|
||||
children:
|
||||
sendConfiguration: [viewPublic, sendWithoutOverrides, sendWithAllowedOverrides]
|
||||
list: [view, edit, delete, share, viewFields, manageFields, viewSubscriptions, manageSubscriptions, viewSegments, manageSegments, viewImports, manageImports]
|
||||
customForm: [view, edit, delete, share]
|
||||
campaign: [view, edit, delete, share, viewFiles, manageFiles, viewAttachments, manageAttachments, viewTriggers, manageTriggers, send, viewStats, fetchRss]
|
||||
template: [view, edit, delete, share, viewFiles, manageFiles]
|
||||
report: [view, edit, delete, share, execute, viewContent, viewOutput]
|
||||
reportTemplate: [view, share, execute]
|
||||
mosaicoTemplate: [view, edit, delete, share, viewFiles, manageFiles]
|
||||
namespace: [view, edit, delete, share, createNamespace, createList, createCustomForm, createReport, createTemplate, createMosaicoTemplate, createCampaign]
|
||||
|
||||
sendConfiguration:
|
||||
master:
|
||||
name: Master
|
||||
|
|
|
@ -264,7 +264,7 @@ async function getByUsername(username) {
|
|||
|
||||
async function getByUsernameIfPasswordMatch(context, username, password) {
|
||||
try {
|
||||
const user = await _getBy('username', username, ['password']);
|
||||
const user = await _getBy(context, 'username', username, ['password']);
|
||||
|
||||
if (!await bcryptCompare(password, user.password)) {
|
||||
throw new interoperableErrors.IncorrectPasswordError();
|
||||
|
@ -324,7 +324,7 @@ async function sendPasswordReset(locale, usernameOrEmail) {
|
|||
title: tUI('mailtrain', locale),
|
||||
username: user.username,
|
||||
name: user.name,
|
||||
confirmUrl: getTrustedUrl(`/account/reset/${encodeURIComponent(user.username)}/${encodeURIComponent(resetToken)}`)
|
||||
confirmUrl: getTrustedUrl(`login/reset/${encodeURIComponent(user.username)}/${encodeURIComponent(resetToken)}`)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
28
server/package-lock.json
generated
|
@ -2879,7 +2879,8 @@
|
|||
},
|
||||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"bundled": true
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
},
|
||||
"aproba": {
|
||||
"version": "1.2.0",
|
||||
|
@ -3244,7 +3245,8 @@
|
|||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.1",
|
||||
"bundled": true
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
|
@ -3292,6 +3294,7 @@
|
|||
"strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
}
|
||||
|
@ -3330,11 +3333,13 @@
|
|||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
},
|
||||
"yallist": {
|
||||
"version": "3.0.2",
|
||||
"bundled": true
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -6163,12 +6168,9 @@
|
|||
"from": "github:openpgpjs/elliptic#e187e706e11fa51bcd20e46e5119054be4e2a4a6",
|
||||
"requires": {
|
||||
"bn.js": "^4.4.0",
|
||||
"brorand": "^1.0.1",
|
||||
"hash.js": "^1.0.0",
|
||||
"hmac-drbg": "^1.0.0",
|
||||
"inherits": "^2.0.1",
|
||||
"minimalistic-assert": "^1.0.0",
|
||||
"minimalistic-crypto-utils": "^1.0.0"
|
||||
"minimalistic-assert": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"openpgp": {
|
||||
|
@ -6447,22 +6449,16 @@
|
|||
"commander": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz",
|
||||
"integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=",
|
||||
"requires": {
|
||||
"graceful-readlink": ">= 1.0.0"
|
||||
}
|
||||
"integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ="
|
||||
},
|
||||
"elliptic": {
|
||||
"version": "github:openpgpjs/elliptic#e187e706e11fa51bcd20e46e5119054be4e2a4a6",
|
||||
"from": "github:openpgpjs/elliptic#e187e706e11fa51bcd20e46e5119054be4e2a4a6",
|
||||
"requires": {
|
||||
"bn.js": "^4.4.0",
|
||||
"brorand": "^1.0.1",
|
||||
"hash.js": "^1.0.0",
|
||||
"hmac-drbg": "^1.0.0",
|
||||
"inherits": "^2.0.1",
|
||||
"minimalistic-assert": "^1.0.0",
|
||||
"minimalistic-crypto-utils": "^1.0.0"
|
||||
"minimalistic-assert": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node-fetch": {
|
||||
|
|
|
@ -21,7 +21,7 @@ function getRouter(appType) {
|
|||
reactCsrfToken: req.csrfToken(),
|
||||
mailtrainConfig: JSON.stringify(mailtrainConfig),
|
||||
scriptFiles: [
|
||||
getTrustedUrl('mailtrain/root.js')
|
||||
getTrustedUrl('client/root.js')
|
||||
],
|
||||
publicPath: getTrustedUrl()
|
||||
});
|
||||
|
|
|
@ -45,7 +45,7 @@ function getRouter(appType) {
|
|||
reactCsrfToken: req.csrfToken(),
|
||||
mailtrainConfig: JSON.stringify(mailtrainConfig),
|
||||
scriptFiles: [
|
||||
getSandboxUrl('mailtrain/ckeditor-root.js')
|
||||
getSandboxUrl('client/ckeditor-root.js')
|
||||
],
|
||||
publicPath: getSandboxUrl()
|
||||
});
|
||||
|
|
|
@ -45,7 +45,7 @@ function getRouter(appType) {
|
|||
reactCsrfToken: req.csrfToken(),
|
||||
mailtrainConfig: JSON.stringify(mailtrainConfig),
|
||||
scriptFiles: [
|
||||
getSandboxUrl('mailtrain/codeeditor-root.js')
|
||||
getSandboxUrl('client/codeeditor-root.js')
|
||||
],
|
||||
publicPath: getSandboxUrl()
|
||||
});
|
||||
|
|
|
@ -45,7 +45,7 @@ function getRouter(appType) {
|
|||
reactCsrfToken: req.csrfToken(),
|
||||
mailtrainConfig: JSON.stringify(mailtrainConfig),
|
||||
scriptFiles: [
|
||||
getSandboxUrl('mailtrain/grapesjs-root.js')
|
||||
getSandboxUrl('client/grapesjs-root.js')
|
||||
],
|
||||
publicPath: getSandboxUrl()
|
||||
});
|
||||
|
|
|
@ -201,7 +201,7 @@ function getRouter(appType) {
|
|||
reactCsrfToken: req.csrfToken(),
|
||||
mailtrainConfig: JSON.stringify(mailtrainConfig),
|
||||
scriptFiles: [
|
||||
getSandboxUrl('mailtrain/mosaico-root.js')
|
||||
getSandboxUrl('client/mosaico-root.js')
|
||||
],
|
||||
publicPath: getSandboxUrl()
|
||||
});
|
||||
|
|
|
@ -7,9 +7,9 @@ module.exports = {
|
|||
url: '/users/login',
|
||||
elementsToWaitFor: ['submitButton'],
|
||||
elements: {
|
||||
usernameInput: 'form[action="/account/login"] input[name="username"]',
|
||||
passwordInput: 'form[action="/account/login"] input[name="password"]',
|
||||
submitButton: 'form[action="/account/login"] [type=submit]'
|
||||
usernameInput: 'form[action="/login"] input[name="username"]',
|
||||
passwordInput: 'form[action="/login"] input[name="password"]',
|
||||
submitButton: 'form[action="/login"] [type=submit]'
|
||||
}
|
||||
}),
|
||||
|
||||
|
|
|
@ -12,10 +12,9 @@
|
|||
|
||||
<title>Mailtrain</title>
|
||||
|
||||
<link rel="stylesheet" href="{{publicPath}}mailtrain/mailtrain.css">
|
||||
|
||||
<script src="{{publicPath}}static/jquery-3.3.1.min.js"></script>
|
||||
<link rel="stylesheet" href="{{publicPath}}client/mailtrain.css">
|
||||
|
||||
<script src="{{publicPath}}static-npm/jquery.min.js"></script>
|
||||
<script src="{{publicPath}}static-npm/popper.min.js"></script>
|
||||
<script src="{{publicPath}}static-npm/bootstrap.min.js"></script>
|
||||
<script src="{{publicPath}}static-npm/coreui.min.js"></script>
|
||||
|
|
|
@ -12,10 +12,9 @@
|
|||
|
||||
<title>Mailtrain</title>
|
||||
|
||||
<link rel="stylesheet" href="{{publicPath}}mailtrain/mailtrain.css">
|
||||
|
||||
<script src="{{publicPath}}static/jquery-3.3.1.min.js"></script>
|
||||
<link rel="stylesheet" href="{{publicPath}}client/mailtrain.css">
|
||||
|
||||
<script src="{{publicPath}}static-npm/jquery.min.js"></script>
|
||||
<script src="{{publicPath}}static-npm/popper.min.js"></script>
|
||||
<script src="{{publicPath}}static-npm/bootstrap.min.js"></script>
|
||||
<script src="{{publicPath}}static-npm/coreui.min.js"></script>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
<title>Mailtrain</title>
|
||||
|
||||
<script src="{{publicPath}}static/jquery-3.3.1.min.js"></script>
|
||||
<script src="{{publicPath}}static-npm/jquery.min.js"></script>
|
||||
|
||||
{{#if mailtrainConfig}}
|
||||
<script>
|
||||
|
|
|
@ -14,10 +14,9 @@
|
|||
{{#if title}} | {{title}}{{/if}}
|
||||
</title>
|
||||
|
||||
<link rel="stylesheet" href="{{publicPath}}mailtrain/mailtrain.css">
|
||||
|
||||
<script src="{{publicPath}}static/jquery-3.3.1.min.js"></script>
|
||||
<link rel="stylesheet" href="{{publicPath}}client/mailtrain.css">
|
||||
|
||||
<script src="{{publicPath}}static-npm/jquery.min.js"></script>
|
||||
<script src="{{publicPath}}static-npm/popper.min.js"></script>
|
||||
<script src="{{publicPath}}static-npm/bootstrap.min.js"></script>
|
||||
<script src="{{publicPath}}static-npm/coreui.min.js"></script>
|
||||
|
|