Various fixes.

This commit is contained in:
Tomas Bures 2019-07-23 21:16:55 +05:30
parent 4e4b77ca84
commit 02360be75b
20 changed files with 3137 additions and 3124 deletions

1705
client/package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -20,16 +20,16 @@
"license": "GPL-3.0",
"homepage": "https://mailtrain.org/",
"dependencies": {
"@coreui/coreui": "^2.1.4",
"@fortawesome/fontawesome-free": "^5.6.3",
"axios": "^0.18.0",
"@coreui/coreui": "^2.1.12",
"@fortawesome/fontawesome-free": "^5.9.0",
"axios": "^0.18.1",
"bootstrap": "^4.2.1",
"clone": "^2.1.2",
"datatables.net": "^1.10.19",
"datatables.net-bs4": "^1.10.19",
"ellipsize": "^0.1.0",
"fast-deep-equal": "^2.0.1",
"grapesjs": "^0.14.49",
"grapesjs": "^0.14.62",
"grapesjs-mjml": "0.0.31",
"grapesjs-preset-newsletter": "^0.2.20",
"htmlparser2": "^3.10.1",
@ -37,51 +37,51 @@
"i18next-browser-languagedetector": "^2.2.4",
"immutable": "^4.0.0-rc.12",
"juice": "^5.2.0",
"lodash": "^4.17.11",
"mjml4-in-browser": "^1.1.1",
"lodash": "^4.17.15",
"mjml4-in-browser": "^1.1.2",
"moment": "^2.23.0",
"moment-timezone": "^0.5.25",
"moment-timezone": "^0.5.26",
"popper.js": "^1.14.6",
"prop-types": "^15.6.2",
"querystringify": "^2.1.0",
"react": "^16.7.0",
"react-ace": "^6.3.2",
"react-ace": "^6.6.0",
"react-ckeditor-component": "^1.1.0",
"react-color": "^2.17.0",
"react-color": "^2.17.3",
"react-day-picker": "^7.2.4",
"react-dnd": "^7.0.2",
"react-dnd-html5-backend": "^7.0.2",
"react-dnd": "^7.7.0",
"react-dnd-html5-backend": "^7.7.0",
"react-dnd-touch-backend": "^0.7.1",
"react-dom": "^16.7.0",
"react-dropzone": "^8.0.3",
"react-google-charts": "^3.0.10",
"react-google-charts": "^3.0.14",
"react-i18next": "^9.0.1",
"react-router-dom": "^4.3.1",
"react-sortable-tree": "^2.6.0",
"shallowequal": "^1.1.0",
"shortid": "^2.2.14",
"slugify": "^1.3.4",
"url-parse": "^1.4.4"
"url-parse": "^1.4.7"
},
"devDependencies": {
"@babel/cli": "^7.2.3",
"@babel/core": "^7.2.2",
"@babel/plugin-proposal-class-properties": "^7.2.3",
"@babel/plugin-proposal-decorators": "^7.2.3",
"@babel/cli": "^7.5.5",
"@babel/core": "^7.5.5",
"@babel/plugin-proposal-class-properties": "^7.5.5",
"@babel/plugin-proposal-decorators": "^7.4.4",
"@babel/plugin-proposal-function-bind": "^7.2.0",
"@babel/preset-env": "^7.2.3",
"@babel/preset-env": "^7.5.5",
"@babel/preset-react": "^7.0.0",
"babel-loader": "^8.0.4",
"babel-loader": "^8.0.6",
"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",
"node-sass": "^4.12.0",
"nodemon": "^1.19.1",
"npm-run-all": "^4.1.5",
"sass-loader": "^7.1.0",
"style-loader": "^0.23.1",
"url-loader": "^1.1.2",
"webpack": "^4.28.3",
"webpack-cli": "^3.2.0"
"webpack": "^4.36.1",
"webpack-cli": "^3.3.6"
}
}

View file

@ -121,21 +121,20 @@ export default class CUD extends Component {
onFormChangeBeforeValidation(mutStateData, key, oldValue, newValue) {
let match;
if (key === undefined || key === 'data_sourceCustom_type') {
if (key === 'data_sourceCustom_type') {
if (newValue) {
this.templateTypes[newValue].afterTypeChange(mutStateData);
}
}
if (key === undefined || key === 'data_sourceCustom_tag_language') {
if (key === 'data_sourceCustom_tag_language') {
if (newValue) {
const isEdit = !!this.props.entity;
const type = mutStateData.getIn(['data_sourceCustom_tag_language', 'value']);
this.templateTypes[type].afterTagLanguageChange(mutStateData, isEdit);
this.templateTypes[newValue].afterTagLanguageChange(mutStateData, isEdit);
}
}
if (key === undefined || (match = key.match(/^(lists_[0-9]+_)list$/))) {
if (key && (match = key.match(/^(lists_[0-9]+_)list$/))) {
const prefix = match[1];
mutStateData.setIn([prefix + 'segment', 'value'], null);
}

View file

@ -1052,34 +1052,38 @@ const withForm = createComponentMixin([], [], (TargetClass, InnerClass) => {
axios.post(getUrl(settings.serverValidation.url), payload)
.then(response => {
self.setState(previousState => ({
formState: previousState.formState.withMutations(mutState => {
mutState.set('isServerValidationRunning', false);
if (self.isComponentMounted()) {
self.setState(previousState => ({
formState: previousState.formState.withMutations(mutState => {
mutState.set('isServerValidationRunning', false);
mutState.update('data', stateData => stateData.withMutations(mutStateData => {
for (const attr in payload) {
mutStateData.setIn([attr, 'serverValue'], payload[attr]);
mutState.update('data', stateData => stateData.withMutations(mutStateData => {
for (const attr in payload) {
mutStateData.setIn([attr, 'serverValue'], payload[attr]);
if (payload[attr] === mutState.getIn(['data', attr, 'value'])) {
mutStateData.setIn([attr, 'serverValidated'], true);
mutStateData.setIn([attr, 'serverValidation'], response.data[attr] || true);
if (payload[attr] === mutState.getIn(['data', attr, 'value'])) {
mutStateData.setIn([attr, 'serverValidated'], true);
mutStateData.setIn([attr, 'serverValidation'], response.data[attr] || true);
}
}
}
}));
})
}));
}));
})
}));
scheduleValidateForm(self);
scheduleValidateForm(self);
}
})
.catch(error => {
console.log('Error in "validateFormState": ' + error);
if (self.isComponentMounted()) {
console.log('Error in "validateFormState": ' + error);
self.setState(previousState => ({
formState: previousState.formState.set('isServerValidationRunning', false)
}));
self.setState(previousState => ({
formState: previousState.formState.set('isServerValidationRunning', false)
}));
// TODO: It might be good not to give up immediatelly, but retry a couple of times
// scheduleValidateForm(self);
// TODO: It might be good not to give up immediatelly, but retry a couple of times
// scheduleValidateForm(self);
}
});
} else {
if (formValidateResolve) {
@ -1097,6 +1101,26 @@ const withForm = createComponentMixin([], [], (TargetClass, InnerClass) => {
}
}
const previousComponentDidMount = proto.componentDidMount;
proto.componentDidMount = function() {
this._isComponentMounted = true;
if (previousComponentDidMount) {
previousComponentDidMount.apply(this);
}
};
const previousComponentWillUnmount = proto.componentWillUnmount;
proto.componentWillUnmount = function() {
this._isComponentMounted = false;
if (previousComponentWillUnmount) {
previousComponentDidMount.apply(this);
}
};
proto.isComponentMounted = function() {
return !!this._isComponentMounted;
}
proto.initForm = function(settings) {
const state = this.state || {};
state.formState = cleanFormState;

View file

@ -108,7 +108,8 @@ const entityTypeLabels = {
'sendConfiguration': t => t('sendConfiguration'),
'report': t => t('report'),
'reportTemplate': t => t('reportTemplate'),
'mosaicoTemplate': t => t('mosaicoTemplate')
'mosaicoTemplate': t => t('mosaicoTemplate'),
'user': t => t('User')
};
function _getDependencyErrorMessage(err, t, name) {

View file

@ -37,6 +37,7 @@ const TableSelectMode = {
class Table extends Component {
constructor(props) {
super(props);
this.mounted = false;
this.selectionMap = this.getSelectionMap(props);
}
@ -184,6 +185,8 @@ class Table extends Component {
}
componentDidMount() {
this.mounted = true;
const columns = this.props.columns.slice();
// XSS protection and actions rendering
@ -364,12 +367,13 @@ class Table extends Component {
}
componentWillUnmount() {
this.mounted = false;
clearInterval(this.refreshIntervalId);
clearTimeout(this.refreshTimeoutId);
}
async notifySelection(eventCallback, newSelectionMap) {
if (eventCallback) {
if (this.mounted && eventCallback) {
const selPairs = Array.from(newSelectionMap).sort((l, r) => l[0] - r[0]);
let data = selPairs.map(entry => entry[1]);

View file

@ -33,7 +33,7 @@ class TreeTable extends Component {
constructor(props) {
super(props);
this.isComponentMounted = false;
this.mounted = false;
this.state = {
treeData: []
@ -52,9 +52,9 @@ class TreeTable extends Component {
}
refresh() {
if (this.tree) {
this.tree.reload(this.sanitizeTreeData(this.state.treeData));
this.updateSelection();
if (this.tree && !this.props.data && this.props.dataUrl) {
// noinspection JSIgnoredPromiseFromCall
this.loadData();
}
}
@ -70,7 +70,7 @@ class TreeTable extends Component {
}
}
if (this.isComponentMounted) {
if (this.mounted) {
this.setState({
treeData
});
@ -113,7 +113,7 @@ class TreeTable extends Component {
}
componentDidMount() {
this.isComponentMounted = true;
this.mounted = true;
if (!this.props.data && this.props.dataUrl) {
// noinspection JSIgnoredPromiseFromCall
@ -228,7 +228,7 @@ class TreeTable extends Component {
}
componentWillUnmount() {
this.isComponentMounted = false;
this.mounted = false;
}
updateSelection() {

View file

@ -71,7 +71,8 @@ export default class CUD extends Component {
email: '',
password: '',
password2: '',
namespace: mailtrainConfig.user.namespace
namespace: mailtrainConfig.user.namespace,
role: null
});
}
}