Some refactoring to aling it more with IVIS and coreui theme.

This commit is contained in:
Tomas Bures 2019-01-05 23:56:16 +01:00
parent 397f85dac4
commit c1731bf09f
50 changed files with 1427 additions and 2351 deletions

174
client/package-lock.json generated
View file

@ -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",

View file

@ -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",

View file

@ -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
}
}
}
};
}

View file

@ -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

View file

@ -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">&copy; 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);

View file

@ -2,4 +2,4 @@
import {getUrl} from "./urls";
__webpack_public_path__ = getUrl('mailtrain/');
__webpack_public_path__ = getUrl('client/');

View file

@ -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 {

View file

@ -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';

View file

@ -1,4 +1,4 @@
@import "../../static/scss/variables.scss";
@import "../scss/variables.scss";
:global {

View file

@ -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'));

View file

@ -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>;
}

View file

@ -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
View 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
}

View file

@ -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">&copy; 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}/>
);
}
}

View 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;
}
}

View file

@ -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>
);

View file

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 842 B

After

Width:  |  Height:  |  Size: 842 B

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 844 B

After

Width:  |  Height:  |  Size: 844 B

Before After
Before After

File diff suppressed because one or more lines are too long

View file

@ -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;
}
}