Completely removed CKEditor 5

Some fixes of bugs from testing in production env.
This commit is contained in:
Tomas Bures 2018-11-24 00:48:41 -05:00
parent d459f7cfed
commit 43c6b58793
17 changed files with 2901 additions and 440 deletions

View file

@ -14,26 +14,6 @@
"license": "GPL-3.0",
"homepage": "https://mailtrain.org/",
"dependencies": {
/*
"@ckeditor/ckeditor5-alignment": "^10.0.3",
"@ckeditor/ckeditor5-basic-styles": "^10.0.3",
"@ckeditor/ckeditor5-block-quote": "^10.1.0",
"@ckeditor/ckeditor5-core": "^11.0.1",
"@ckeditor/ckeditor5-easy-image": "^10.0.3",
"@ckeditor/ckeditor5-editor-classic": "^11.0.1",
"@ckeditor/ckeditor5-essentials": "^10.1.2",
"@ckeditor/ckeditor5-heading": "^10.1.0",
"@ckeditor/ckeditor5-image": "^11.0.0",
"@ckeditor/ckeditor5-link": "^10.0.4",
"@ckeditor/ckeditor5-list": "^11.0.2",
"@ckeditor/ckeditor5-media-embed": "^10.0.0",
"@ckeditor/ckeditor5-paragraph": "^10.0.3",
"@ckeditor/ckeditor5-react": "^1.0.0",
"@ckeditor/ckeditor5-table": "^11.0.0",
"@ckeditor/ckeditor5-theme-lark": "^11.1.0",
"@ckeditor/ckeditor5-ui": "^11.1.0",
"@ckeditor/ckeditor5-upload": "^10.0.3",
*/
"axios": "^0.18.0",
"datatables.net": "^1.10.19",
"datatables.net-bs": "^1.10.19",
@ -71,10 +51,6 @@
"@babel/plugin-proposal-function-bind": "^7.0.0",
"@babel/preset-env": "^7.0.0",
"@babel/preset-react": "^7.0.0",
/*
"@ckeditor/ckeditor5-dev-utils": "^11.0.1",
"@ckeditor/ckeditor5-dev-webpack-plugin": "^7.0.1",
*/
"babel-loader": "^8.0.4",
"css-loader": "^1.0.1",
"file-loader": "^2.0.0",

View file

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
>
<path
style="fill:#000000;fill-rule:nonzero;stroke-width:0.89999998"
d="m 4.9296875,1.5273438 c -0.549,0 -0.9902344,0.4233124 -0.9902344,0.9453124 V 8.1542969 C 3.9929718,8.1073482 4.0362288,8.0501836 4.09375,8.0078125 4.4641691,7.6414817 4.869899,7.3679645 5.2890625,7.1503906 V 2.8496094 H 17.501953 V 11.957031 L 15.234375,9.2851562 c -0.220904,-0.204796 -0.562299,-0.204796 -0.783203,0 l -2.00586,1.8535158 -0.451171,-0.421875 c 0.101968,0.808412 -0.008,1.673794 -0.398438,2.529297 -0.04665,0.163457 -0.103202,0.325377 -0.201172,0.464844 l -0.002,0.002 -0.257812,0.36914 h 6.736328 c 0.54,0 0.982422,-0.422125 0.982422,-0.953125 V 2.4726562 c 0,-0.522 -0.442422,-0.9453124 -0.982422,-0.9453124 z M 14.714844,3.8828125 C 13.350658,3.8741006 12.49215,5.3495586 13.173828,6.53125 14.349609,8.5716138 17.410156,6.8079419 16.234375,4.7675781 15.921123,4.2235411 15.342608,3.8866937 14.714844,3.8828125 Z"
id="path2"/>
<path
style="fill:#000000;fill-rule:evenodd;stroke-width:0.69999999"
d="m 6.8138243,16.679773 0.6937,-0.9912 a 0.52500478,0.52500478 0 1 1 0.8603,0.602 l -0.8036,1.148 a 0.5236,0.5236 0 0 1 -0.1519,0.1442 3.6757,3.6757 0 0 1 -5.9521,-4.1685 c 0.014,-0.0665 0.042,-0.1323 0.084,-0.1918 l 0.8029,-1.1473 a 0.525,0.525 0 1 1 0.8596,0.602 l -0.6937,0.9926 0.0042,0.0021 a 2.625,2.625 0 0 0 4.2924,3.0058 l 0.0042,0.0028 z m 3.8457997,-3.7345 a 0.5236,0.5236 0 0 1 -0.084,0.1918 l -0.8028997,1.1473 a 0.525,0.525 0 1 1 -0.8596,-0.602 l 0.602,-0.861 a 2.625,2.625 0 0 0 -4.3008,-3.0106998 l -0.602,0.8602998 a 0.52500478,0.52500478 0 0 1 -0.8603,-0.602 l 0.8036,-1.1479998 a 0.5236,0.5236 0 0 1 0.1519,-0.1442 3.6757,3.6757 0 0 1 5.9520997,4.1684998 z m -3.1940997,-1.7724 a 0.525,0.525 0 0 1 0.1288,0.7315 l -2.2085,3.1535 a 0.52500478,0.52500478 0 1 1 -0.8603,-0.602 l 2.2085,-3.1542 a 0.525,0.525 0 0 1 0.7315,-0.1288 z" />
</svg>

Before

Width:  |  Height:  |  Size: 2 KiB

View file

@ -1,193 +0,0 @@
'use strict';
import React, {Component} from 'react';
import ClassicEditorBase from '@ckeditor/ckeditor5-editor-classic/src/classiceditor';
import EssentialsPlugin from '@ckeditor/ckeditor5-essentials/src/essentials';
import BoldPlugin from '@ckeditor/ckeditor5-basic-styles/src/bold';
import UnderlinePlugin from '@ckeditor/ckeditor5-basic-styles/src/underline';
import StrikethroughPlugin from '@ckeditor/ckeditor5-basic-styles/src/strikethrough';
import CodePlugin from '@ckeditor/ckeditor5-basic-styles/src/code';
import ItalicPlugin from '@ckeditor/ckeditor5-basic-styles/src/italic';
import BlockQuotePlugin from '@ckeditor/ckeditor5-block-quote/src/blockquote';
import EasyImagePlugin from '@ckeditor/ckeditor5-easy-image/src/easyimage';
import HeadingPlugin from '@ckeditor/ckeditor5-heading/src/heading';
import ImagePlugin from '@ckeditor/ckeditor5-image/src/image';
import ImageCaptionPlugin from '@ckeditor/ckeditor5-image/src/imagecaption';
import ImageStylePlugin from '@ckeditor/ckeditor5-image/src/imagestyle';
import ImageToolbarPlugin from '@ckeditor/ckeditor5-image/src/imagetoolbar';
//import ImageUploadPlugin from '@ckeditor/ckeditor5-image/src/imageupload';
import LinkPlugin from '@ckeditor/ckeditor5-link/src/link';
import ListPlugin from '@ckeditor/ckeditor5-list/src/list';
import ParagraphPlugin from '@ckeditor/ckeditor5-paragraph/src/paragraph';
import AlignmentPlugin from '@ckeditor/ckeditor5-alignment/src/alignment';
import TablePlugin from '@ckeditor/ckeditor5-table/src/table';
import TableToolbarPlugin from '@ckeditor/ckeditor5-table/src/tabletoolbar';
import CKEditor from '@ckeditor/ckeditor5-react';
import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
import FileRepository from '@ckeditor/ckeditor5-upload/src/filerepository';
import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';
import insertImageIcon from './ckeditor-insert-image.svg';
class InsertImage extends Plugin {
init() {
const editor = this.editor;
editor.ui.componentFactory.add( 'insertImage', locale => {
const view = new ButtonView( locale );
view.set( {
label: 'Insert image',
icon: insertImageIcon,
tooltip: true
} );
// Callback executed once the image is clicked.
view.on( 'execute', () => {
let url = '';
const selectedElement = editor.model.document.selection.getSelectedElement();
if (selectedElement) {
if (selectedElement.is('element', 'image')) {
url = selectedElement.getAttribute('src');
}
}
const imageUrl = prompt('Image URL', url);
if (imageUrl) {
editor.model.change( writer => {
const imageElement = writer.createElement( 'image', {
src: imageUrl
} );
// Insert the image in the current selection location.
editor.model.insertContent( imageElement, editor.model.document.selection );
} );
}
} );
return view;
} );
}
}
/*
Upload through CKEditor is disable because files can be managed by Files tab
class UploadAdapter {
constructor(loader, url, t) {
this.loader = loader;
}
async upload() {
console.log(this.loader);
return {
default: 'http://server/default-size.image.png'
};
}
abort() {
}
}
class MailtrainUploadAdapter extends Plugin {
static get requires() {
return [ FileRepository ];
}
static get pluginName() {
return 'MailtrainUploadAdapter';
}
init() {
this.editor.plugins.get(FileRepository).createUploadAdapter = loader => new UploadAdapter(loader, this.editor.t);
}
}
*/
class ClassicEditor extends ClassicEditorBase {}
ClassicEditor.builtinPlugins = [
EssentialsPlugin,
BoldPlugin,
ItalicPlugin,
UnderlinePlugin,
StrikethroughPlugin,
CodePlugin,
BlockQuotePlugin,
HeadingPlugin,
ImagePlugin,
ImageCaptionPlugin,
ImageStylePlugin,
ImageToolbarPlugin,
//ImageUploadPlugin,
LinkPlugin,
ListPlugin,
ParagraphPlugin,
AlignmentPlugin,
TablePlugin,
TableToolbarPlugin,
//MailtrainUploadAdapter,
InsertImage
];
ClassicEditor.defaultConfig = {
toolbar: {
items: [
'heading',
'|',
'bold',
'italic',
'underline',
'strikethrough',
'code',
'|',
'alignment',
'|',
'link',
'bulletedList',
'numberedList',
'|',
'insertImage',
// 'imageUpload',
'blockQuote',
'|',
'insertTable',
'|',
'undo',
'redo'
]
},
alignment: {
options: [ 'left', 'center', 'right', 'justify' ]
},
image: {
toolbar: [
'imageStyle:full',
'imageStyle:side',
'|',
'imageTextAlternative'
]
},
table: {
contentToolbar: [ 'tableColumn', 'tableRow', 'mergeTableCells' ]
},
language: 'en'
};
export default class CKEditorWrapper extends Component {
render() {
return (
<CKEditor
editor={ ClassicEditor }
{...this.props}
/>
);
}
}

View file

@ -17,8 +17,6 @@ import ACEEditorRaw from 'react-ace';
import 'brace/theme/github';
import 'brace/ext/searchbox';
//import CKEditorRaw from './ckeditor5';
import DayPicker from 'react-day-picker';
import 'react-day-picker/lib/style.css';
import { parseDate, parseBirthday, formatDate, formatBirthday, DateFormat, birthdayYear, getDateFormatString, getBirthdayFormatString } from '../../../shared/date';

View file

@ -76,6 +76,7 @@ export default class CUD extends Component {
unsubscription_mode: UnsubscriptionMode.ONE_STEP,
namespace: mailtrainConfig.user.namespace,
to_name: '[FIRST_NAME] [LAST_NAME]',
send_configuration: null,
listunsubscribe_disabled: false
});
}
@ -90,6 +91,12 @@ export default class CUD extends Component {
state.setIn(['name', 'error'], null);
}
if (!state.getIn(['send_configuration', 'value'])) {
state.setIn(['send_configuration', 'error'], t('Send configuration must be selected'));
} else {
state.setIn(['send_configuration', 'error'], null);
}
if (state.getIn(['form', 'value']) === 'custom' && !state.getIn(['default_form', 'value'])) {
state.setIn(['default_form', 'error'], t('customFormMustBeSelected'));
} else {
@ -236,4 +243,4 @@ export default class CUD extends Component {
</div>
);
}
}
}

View file

@ -364,57 +364,6 @@ export function getTemplateTypes(t, prefix = '', entityTypeId = ResourceType.TEM
}
};
/* Excluded. It's not very useful and just eats a lot of space in the resulting JS.
templateTypes.ckeditor5 = {
typeName: t('ckEditor5'),
getTypeForm: (owner, isEdit) => null,
getHTMLEditor: owner =>
<CKEditor
id={prefix + 'ckeditor5Source'}
height="600px"
mode="html"
label={t('templateContentHtml')}/>,
exportHTMLEditorData: async owner => {
const preHtml = '<!doctype html><html><head><meta charset="utf-8"><title></title></head><body>';
const postHtml = '</body></html>';
const trustedUrlBase = getTrustedUrl();
const sandboxUrlBase = getSandboxUrl();
const publicUrlBase = getPublicUrl();
const unbasedSource = unbase(owner.getFormValue(prefix + 'ckeditor5Source'), trustedUrlBase, sandboxUrlBase, publicUrlBase, true);
const html = preHtml + unbasedSource + postHtml
return {
[prefix + 'ckeditor5Source']: unbasedSource,
[prefix + 'html']: html
}
},
initData: () => ({
[prefix + 'ckeditor5Source']: ''
}),
afterLoad: data => {
const trustedUrlBase = getTrustedUrl();
const sandboxUrlBase = getSandboxUrl();
const publicUrlBase = getPublicUrl();
const source = base(data[prefix + 'data'].source, trustedUrlBase, sandboxUrlBase, publicUrlBase);
data[prefix + 'ckeditor5Source'] = source;
},
beforeSave: data => {
data[prefix + 'data'] = {
source: data[prefix + 'ckeditor5Source'],
};
clearBeforeSave(data);
},
afterTypeChange: mutState => {
initFieldsIfMissing(mutState, 'ckeditor5');
},
validate: state => {
}
};
*/
const codeEditorSourceTypes = getCodeEditorSourceTypeOptions(t);
const codeEditorSourceTypeLabels = {};

View file

@ -1,21 +1,9 @@
const webpack = require('webpack');
const path = require('path');
/* Excluded. It's not very useful and just eats a lot of space in the resulting JS.
// The CKEditor part comes from https://ckeditor.com/docs/ckeditor5/latest/builds/guides/integration/advanced-setup.html
const CKEditorWebpackPlugin = require( '@ckeditor/ckeditor5-dev-webpack-plugin' );
const { styles } = require( '@ckeditor/ckeditor5-dev-utils' );
*/
module.exports = {
mode: 'development',
plugins: [
/*
new CKEditorWebpackPlugin( {
// See https://ckeditor.com/docs/ckeditor5/latest/features/ui-language.html
language: 'en'
} )
*/
],
entry: {
"root": ['./src/root.js'],
@ -69,22 +57,6 @@ module.exports = {
}
]
},
/*
{
test: /ckeditor5-[^/]+\/theme\/[\w-/]+\.css$/,
use: [
{
loader: 'postcss-loader',
options: styles.getPostCssConfig( {
themeImporter: {
themePath: require.resolve( '@ckeditor/ckeditor5-theme-lark' )
},
minify: true
} )
}
]
},
*/
{
test: /\.(png|jpg|gif)$/,
use: [
@ -111,17 +83,8 @@ module.exports = {
'sass-loader'
]
},
/*
{
test: /ckeditor5-[^/]+\/theme\/icons\/[^/]+\.svg|ckeditor-insert-image\.svg$/,
use: [
'raw-loader'
]
},
*/
{
test: /\.(svg|otf|woff2|woff|ttf|eot)$/,
// exclude: /ckeditor5-[^/]+\/theme\/icons\/[^/]+\.svg|ckeditor-insert-image\.svg$/,
use: [
'url-loader'
]

View file

@ -11,6 +11,7 @@ const favicon = require('serve-favicon');
const logger = require('morgan');
const cookieParser = require('cookie-parser');
const session = require('express-session');
const RedisStore = require('connect-redis')(session);
const flash = require('connect-flash');
const hbs = require('hbs');
const compression = require('compression');
@ -157,6 +158,7 @@ function createApp(appType) {
app.use(cookieParser());
app.use(session({
store: config.redis.enabled ? new RedisStore(config.redis) : false,
secret: config.www.secret,
saveUninitialized: false,
resave: false

View file

@ -48,6 +48,16 @@ enabledLanguages:
# customSubscriptionScripts: [/custom/hello-world.js]
# Enable to use Redis session cache or disable if Redis is not installed
redis:
enabled: false
host: localhost
port: 6379
db: 5
# Uncomment if your Redis installation requires a password
# password=""
# If you start out as a root user (eg. if you want to use ports lower than 1000)
# then you can downgrade the user once all services are up and running
#user: mailtrain

View file

@ -108,6 +108,7 @@ async function create(context, listId, entity, files) {
const filteredEntity = filterObject(entity, allowedKeysCreate);
filteredEntity.list = listId;
filteredEntity.settings = JSON.stringify(filteredEntity.settings);
filteredEntity.status = entity.status;
filteredEntity.mapping_type = MappingType.BASIC_SUBSCRIBE; // This is not set in the create form. It can be changed in the update form.
filteredEntity.mapping = JSON.stringify({});

View file

@ -16,7 +16,7 @@ const dependencyHelpers = require('../lib/dependency-helpers');
const UnsubscriptionMode = require('../../shared/lists').UnsubscriptionMode;
const allowedKeys = new Set(['name', 'description', 'default_form', 'public_subscribe', 'unsubscription_mode', 'contact_email', 'homepage', 'namespace', 'to_name', 'listunsubscribe_disabled']);
const allowedKeys = new Set(['name', 'description', 'default_form', 'public_subscribe', 'unsubscription_mode', 'contact_email', 'homepage', 'namespace', 'to_name', 'listunsubscribe_disabled', 'send_configuration']);
function hash(entity) {
return hasher.hash(filterObject(entity, allowedKeys));
@ -130,6 +130,7 @@ async function create(context, entity) {
' `status` tinyint(4) unsigned NOT NULL DEFAULT \'1\',\n' +
' `is_test` tinyint(4) unsigned NOT NULL DEFAULT \'0\',\n' +
' `status_change` timestamp NULL DEFAULT NULL,\n' +
' `unsubscribed` timestamp NULL DEFAULT NULL,\n' +
' `latest_open` timestamp NULL DEFAULT NULL,\n' +
' `latest_click` timestamp NULL DEFAULT NULL,\n' +
' `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n' +
@ -145,6 +146,8 @@ async function create(context, entity) {
' KEY `created` (`created`)\n' +
') ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;\n');
await shares.rebuildPermissionsTx(tx, { entityTypeId: 'list', entityId: id });
return id;
});
}

View file

@ -125,7 +125,7 @@ async function create(context, entity) {
async function updateWithConsistencyCheck(context, entity) {
await knex.transaction(async tx => {
await shares.enforceEntityPermissionTx(tx, context, 'list', entity.id, 'edit');
await shares.enforceEntityPermissionTx(tx, context, 'sendConfiguration', entity.id, 'edit');
const existing = await tx('send_configurations').where('id', entity.id).first();
if (!existing) {

2939
server/package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -50,6 +50,7 @@
"compression": "^1.7.3",
"config": "^2.0.1",
"connect-flash": "^0.1.1",
"connect-redis": "^3.4.0",
"cookie-parser": "^1.4.3",
"cors": "^2.8.5",
"crypto": "^1.0.1",
@ -94,6 +95,7 @@
"nodeify": "^1.0.1",
"nodemailer": "^4.6.8",
"nodemailer-openpgp": "^1.2.0",
"npm": "^6.4.1",
"npmlog": "^4.1.2",
"nyc": "^13.1.0",
"openpgp": "^4.2.1",

View file

@ -782,12 +782,12 @@ async function migrateSettings(knex) {
await knex('settings').del();
await knex('settings').insert([
{ key: 'uaCode', value: settings.uaCode },
{ key: 'shoutout', value: settings.shoutout },
{ key: 'adminEmail', value: settings.adminEmail },
{ key: 'defaultHomepage', value: settings.defaultHomepage },
{ key: 'pgpPassphrase', value: settings.pgpPassphrase },
{ key: 'pgpPrivateKey', value: settings.pgpPrivateKey }
{ key: 'uaCode', value: settings.uaCode || '' },
{ key: 'shoutout', value: settings.shoutout || '' },
{ key: 'adminEmail', value: settings.adminEmail || '' },
{ key: 'defaultHomepage', value: settings.defaultHomepage || '' },
{ key: 'pgpPassphrase', value: settings.pgpPassphrase || '' },
{ key: 'pgpPrivateKey', value: settings.pgpPrivateKey || '' }
]);
}
@ -1284,4 +1284,4 @@ exports.up = (knex, Promise) => (async() => {
})();
exports.down = (knex, Promise) => (async() => {
})();
})();

View file

@ -1,6 +0,0 @@
[www]
port=3000
[mysql]
user="mailtrain_test"
password="bahquaiphoor"
database="mailtrain_test"

View file

@ -3564,12 +3564,14 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@ -3584,17 +3586,20 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"core-util-is": {
"version": "1.0.2",
@ -3711,7 +3716,8 @@
"inherits": {
"version": "2.0.3",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"ini": {
"version": "1.3.5",
@ -3723,6 +3729,7 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@ -3737,6 +3744,7 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@ -3744,12 +3752,14 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"minipass": {
"version": "2.2.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.1",
"yallist": "^3.0.0"
@ -3768,6 +3778,7 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
@ -3848,7 +3859,8 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"object-assign": {
"version": "4.1.1",
@ -3860,6 +3872,7 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"wrappy": "1"
}
@ -3981,6 +3994,7 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",