Draft of new Filters design

This commit is contained in:
djmaze 2021-01-18 16:47:10 +01:00
parent cd504ffa4b
commit 61c3da14b4
8 changed files with 446 additions and 114 deletions

81
dev/Model/SieveScript.js Normal file
View file

@ -0,0 +1,81 @@
import ko from 'ko';
import { AbstractModel } from 'Knoin/AbstractModel';
import { FilterModel } from 'Model/Filter';
class SieveScriptModel extends AbstractModel
{
constructor() {
super();
this.addObservables({
name: '',
nameError: false,
nameFocused: false,
active: false,
body: '',
deleteAccess: false,
canBeDeleted: false
});
this.filters = ko.observableArray([]);
this.addSubscribables({
name: sValue => this.nameError(!sValue)
});
}
setFilters() {
/*let tree = */window.Sieve.parseScript(this.body);
// this.filters = ko.observableArray(tree);
}
verify() {
if (!this.name()) {
this.nameError(true);
return false;
}
this.nameError(false);
return true;
}
toJson() {
return {
name: this.name(),
active: this.active ? '1' : '0',
body: this.body,
// filters: this.filters()
};
}
/**
* Only 'rainloop.user' script supports filters
*/
allowFilters() {
return 'rainloop.user' === this.name();
}
/**
* @static
* @param {FetchJsonScript} json
* @returns {?SieveScriptModel}
*/
static reviveFromJson(json) {
const script = super.reviveFromJson(json);
if (script) {
script.filters([]);
if (script.allowFilters() && Array.isNotEmpty(json.filters)) {
script.filters(
json.filters.map(aData => FilterModel.reviveFromJson(aData)).filter(v => v)
);
}
}
return script;
}
}
export { SieveScriptModel, SieveScriptModel as default };

View file

@ -1,13 +1,14 @@
import ko from 'ko';
import { delegateRunOnDestroy } from 'Common/UtilsUser';
import { StorageResultType, Notification } from 'Common/Enums';
import { getNotification } from 'Common/Translator';
import FilterStore from 'Stores/User/Filter';
import SieveStore from 'Stores/User/Sieve';
import Remote from 'Remote/User/Fetch';
import { FilterModel } from 'Model/Filter';
import { SieveScriptModel } from 'Model/SieveScript';
import { showScreenPopup, command } from 'Knoin/Knoin';
@ -15,6 +16,8 @@ class FiltersUserSettings {
constructor() {
this.modules = FilterStore.modules;
this.filters = FilterStore.filters;
this.sieve = SieveStore;
this.scripts = SieveStore.scripts;
ko.addObservablesTo(this, {
inited: false,
@ -94,6 +97,7 @@ class FiltersUserSettings {
Remote.filtersGet((result, data) => {
this.filters.loading(false);
this.serverError(false);
this.scripts([]);
if (StorageResultType.Success === result && data && data.Result && Array.isArray(data.Result.Filters)) {
this.inited(true);
@ -105,6 +109,17 @@ class FiltersUserSettings {
this.modules(data.Result.Capa);
this.sieve.capa(data.Result.Capa);
/*
this.scripts(
data.Result.Scripts.map(aItem => SieveScriptModel.reviveFromJson(aItem)).filter(v => v)
);
*/
Object.values(data.Result.Scripts).forEach(value => {
value = SieveScriptModel.reviveFromJson(value);
value && this.scripts.push(value)
});
this.filterRaw(data.Result.Scripts['rainloop.user.raw'].body);
this.filterRaw.capa(data.Result.Capa.join(' '));
this.filterRaw.active(data.Result.Scripts['rainloop.user.raw'].active);
@ -112,6 +127,9 @@ class FiltersUserSettings {
} else {
this.filters([]);
this.modules({});
this.sieve.capa([]);
this.filterRaw('');
this.filterRaw.capa({});
@ -126,50 +144,38 @@ class FiltersUserSettings {
}
}
deleteFilter(filter) {
this.filters.remove(filter);
delegateRunOnDestroy(filter);
}
addFilter() {
const filter = new FilterModel();
filter.generateID();
showScreenPopup(require('View/Popup/Filter'), [
filter,
addScript() {
const script = new SieveScriptModel();
showScreenPopup(require('View/Popup/SieveScript'), [
script,
() => {
this.filters.push(filter);
this.filterRaw.active(false);
if (!this.scripts[script.name]) {
this.scripts[script.name] = script.name;
}
},
false
]);
}
editFilter(filter) {
const clonedFilter = filter.cloneSelf();
showScreenPopup(require('View/Popup/Filter'), [
clonedFilter,
editScript(script) {
showScreenPopup(require('View/Popup/SieveScript'), [
script,
() => {
const filters = this.filters(),
index = filters.indexOf(filter);
if (-1 < index && filters[index]) {
delegateRunOnDestroy(filters[index]);
filters[index] = clonedFilter;
this.filters(filters);
this.haveChanges(true);
}
// TODO on save
},
true
]);
}
deleteScript() {
// TODO
}
onBuild(oDom) {
oDom.addEventListener('click', event => {
const el = event.target.closestWithin('.filter-item .e-action', oDom);
el && ko.dataFor(el) && this.editFilter(ko.dataFor(el));
const el = event.target.closestWithin('.script-item .e-action', oDom),
script = el && ko.dataFor(el);
script && this.editScript(script);
});
}

12
dev/Stores/User/Sieve.js Normal file
View file

@ -0,0 +1,12 @@
import ko from 'ko';
class SieveUserStore {
constructor() {
// capabilities
this.capa = ko.observableArray([]);
// Sieve scripts SieveScriptModel
this.scripts = ko.observableArray([]);
}
}
export default new SieveUserStore();

View file

@ -0,0 +1,169 @@
import ko from 'ko';
import { delegateRunOnDestroy } from 'Common/UtilsUser';
import { StorageResultType, Notification } from 'Common/Enums';
import { getNotification } from 'Common/Translator';
import Remote from 'Remote/User/Fetch';
import FilterStore from 'Stores/User/Filter';
import FilterModel from 'Model/Filter';
import { popup, showScreenPopup, command } from 'Knoin/Knoin';
import { AbstractViewNext } from 'Knoin/AbstractViewNext';
@popup({
name: 'View/Popup/SieveScript',
templateID: 'PopupsSieveScript'
})
class SieveScriptPopupView extends AbstractViewNext {
constructor() {
super();
this.modules = FilterStore.modules;
this.filters = FilterStore.filters;
this.script = {
filters: FilterStore.filters,
saving: () => FilterStore.filters.saving()
};
ko.addObservablesTo(this, {
isNew: true,
inited: false,
serverError: false,
serverErrorDesc: '',
haveChanges: false,
saveErrorText: ''
});
this.serverError.subscribe(value => value || this.serverErrorDesc(''), this);
this.filterRaw = FilterStore.raw;
this.filterRaw.capa = FilterStore.capa;
this.filterRaw.active = ko.observable(false);
this.filterRaw.allow = ko.observable(false);
this.filterRaw.error = ko.observable(false);
this.filterForDeletion = ko.observable(null).deleteAccessHelper();
this.filters.subscribe(() => this.haveChanges(true));
this.filterRaw.subscribe(() => {
this.haveChanges(true);
this.filterRaw.error(false);
});
this.haveChanges.subscribe(() => this.saveErrorText(''));
this.filterRaw.active.subscribe(() => {
this.haveChanges(true);
this.filterRaw.error(false);
});
}
@command((self) => self.haveChanges())
saveScriptCommand() {
if (!this.filters.saving()) {
if (this.filterRaw.active() && !this.filterRaw().trim()) {
this.filterRaw.error(true);
return false;
}
this.filters.saving(true);
this.saveErrorText('');
Remote.filtersSave(
(result, data) => {
this.filters.saving(false);
if (StorageResultType.Success === result && data && data.Result) {
this.haveChanges(false);
} else if (data && data.ErrorCode) {
this.saveErrorText(data.ErrorMessageAdditional || getNotification(data.ErrorCode));
} else {
this.saveErrorText(getNotification(Notification.CantSaveFilters));
}
},
this.filters(),
this.filterRaw(),
this.filterRaw.active()
);
}
return true;
}
deleteFilter(filter) {
this.filters.remove(filter);
delegateRunOnDestroy(filter);
}
addFilter() {
const filter = new FilterModel();
filter.generateID();
showScreenPopup(require('View/Popup/Filter'), [
filter,
() => {
this.filters.push(filter);
this.filterRaw.active(false);
},
false
]);
}
editFilter(filter) {
const clonedFilter = filter.cloneSelf();
showScreenPopup(require('View/Popup/Filter'), [
clonedFilter,
() => {
const filters = this.filters(),
index = filters.indexOf(filter);
if (-1 < index && filters[index]) {
delegateRunOnDestroy(filters[index]);
filters[index] = clonedFilter;
this.filters(filters);
this.haveChanges(true);
}
},
true
]);
}
onBuild(oDom) {
oDom.addEventListener('click', event => {
const el = event.target.closestWithin('.filter-item .e-action', oDom),
filter = el && ko.dataFor(el);
filter && this.editFilter(ko.dataFor(el));
});
}
onShow(oScript, fTrueCallback, bEdit) {
this.clearPopup();
this.fTrueCallback = fTrueCallback;
this.filters(oScript.filters());
this.isNew(!bEdit);
if (!bEdit && oScript) {
// oScript.nameFocused(true);
}
}
onShowWithDelay() {
}
clearPopup() {
this.isNew(true);
this.fTrueCallback = null;
this.filters([]);
}
}
export { SieveScriptPopupView, SieveScriptPopupView as default };