mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-08-29 12:09:20 +03:00
Split Sieve/Filters code from app.js so that i can work on the new Sieve GUI
This commit is contained in:
parent
ec6a79d9d6
commit
d6dc4d291c
23 changed files with 460 additions and 490 deletions
204
dev/Sieve/View/Filter.js
Normal file
204
dev/Sieve/View/Filter.js
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
import { FilterAction } from 'Sieve/Model/Filter';
|
||||
import { FilterConditionField, FilterConditionType } from 'Sieve/Model/FilterCondition';
|
||||
/*
|
||||
import { SettingsUserStore } from 'Stores/User/Settings';
|
||||
*/
|
||||
|
||||
import {
|
||||
capa,
|
||||
i18n,
|
||||
koComputable
|
||||
} from 'Sieve/Utils';
|
||||
|
||||
const
|
||||
// import { defaultOptionsAfterRender } from 'Common/Utils';
|
||||
defaultOptionsAfterRender = (domItem, item) =>
|
||||
domItem && item && undefined !== item.disabled
|
||||
&& domItem.classList.toggle('disabled', domItem.disabled = item.disabled),
|
||||
|
||||
// import { folderListOptionsBuilder } from 'Common/Folders';
|
||||
/**
|
||||
* @param {Array=} aDisabled
|
||||
* @param {Array=} aHeaderLines
|
||||
* @param {Function=} fRenameCallback
|
||||
* @returns {Array}
|
||||
*/
|
||||
folderListOptionsBuilder = (
|
||||
aDisabled,
|
||||
aHeaderLines,
|
||||
fRenameCallback
|
||||
) => {
|
||||
const
|
||||
aResult = [],
|
||||
sDeepPrefix = '\u00A0\u00A0\u00A0',
|
||||
showUnsubscribed = true/*!SettingsUserStore.hideUnsubscribed()*/,
|
||||
|
||||
foldersWalk = folders => {
|
||||
folders.forEach(oItem => {
|
||||
if (showUnsubscribed || oItem.hasSubscriptions() || !oItem.exists) {
|
||||
aResult.push({
|
||||
id: oItem.fullName,
|
||||
name:
|
||||
sDeepPrefix.repeat(oItem.deep) +
|
||||
fRenameCallback(oItem),
|
||||
system: false,
|
||||
disabled: !oItem.selectable() || aDisabled.includes(oItem.fullName)
|
||||
});
|
||||
}
|
||||
|
||||
if (oItem.subFolders.length) {
|
||||
foldersWalk(oItem.subFolders());
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
fRenameCallback = fRenameCallback || (oItem => oItem.name());
|
||||
Array.isArray(aDisabled) || (aDisabled = []);
|
||||
|
||||
Array.isArray(aHeaderLines) && aHeaderLines.forEach(line =>
|
||||
aResult.push({
|
||||
id: line[0],
|
||||
name: line[1],
|
||||
system: false,
|
||||
disabled: false
|
||||
})
|
||||
);
|
||||
|
||||
// FolderUserStore.folderList()
|
||||
foldersWalk(window.Sieve.folderList() || []);
|
||||
|
||||
return aResult;
|
||||
};
|
||||
|
||||
export class FilterPopupView extends rl.pluginPopupView {
|
||||
constructor() {
|
||||
super('Filter');
|
||||
|
||||
this.addObservables({
|
||||
isNew: true,
|
||||
filter: null,
|
||||
allowMarkAsRead: false,
|
||||
selectedFolderValue: ''
|
||||
});
|
||||
|
||||
this.defaultOptionsAfterRender = defaultOptionsAfterRender;
|
||||
this.folderSelectList = koComputable(() =>
|
||||
folderListOptionsBuilder(
|
||||
[rl.settings.get('SieveAllowFileintoInbox') ? '' : 'INBOX'],
|
||||
[['', '']],
|
||||
item => item ? item.localName() : ''
|
||||
)
|
||||
);
|
||||
|
||||
this.selectedFolderValue.subscribe(() => this.filter().actionValueError(false));
|
||||
|
||||
['actionTypeOptions','fieldOptions','typeOptions','typeOptionsSize','typeOptionsBody'].forEach(
|
||||
key => this[key] = ko.observableArray()
|
||||
);
|
||||
|
||||
this.populateOptions();
|
||||
}
|
||||
|
||||
saveFilter() {
|
||||
if (FilterAction.MoveTo === this.filter().actionType()) {
|
||||
this.filter().actionValue(this.selectedFolderValue());
|
||||
}
|
||||
|
||||
if (this.filter().verify()) {
|
||||
this.fTrueCallback();
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
|
||||
populateOptions() {
|
||||
this.actionTypeOptions([]);
|
||||
|
||||
let i18nFilter = key => i18n('POPUPS_FILTER/SELECT_' + key);
|
||||
|
||||
this.fieldOptions([
|
||||
{ id: FilterConditionField.From, name: i18n('GLOBAL/FROM') },
|
||||
{ id: FilterConditionField.Recipient, name: i18nFilter('FIELD_RECIPIENTS') },
|
||||
{ id: FilterConditionField.Subject, name: i18n('GLOBAL/SUBJECT') },
|
||||
{ id: FilterConditionField.Size, name: i18nFilter('FIELD_SIZE') },
|
||||
{ id: FilterConditionField.Header, name: i18nFilter('FIELD_HEADER') }
|
||||
]);
|
||||
|
||||
this.typeOptions([
|
||||
{ id: FilterConditionType.Contains, name: i18nFilter('TYPE_CONTAINS') },
|
||||
{ id: FilterConditionType.NotContains, name: i18nFilter('TYPE_NOT_CONTAINS') },
|
||||
{ id: FilterConditionType.EqualTo, name: i18nFilter('TYPE_EQUAL_TO') },
|
||||
{ id: FilterConditionType.NotEqualTo, name: i18nFilter('TYPE_NOT_EQUAL_TO') }
|
||||
]);
|
||||
|
||||
// this.actionTypeOptions.push({id: FilterAction.None,
|
||||
// name: i18n('GLOBAL/NONE')});
|
||||
if (capa) {
|
||||
this.allowMarkAsRead(capa.includes('imap4flags'));
|
||||
|
||||
if (capa.includes('fileinto')) {
|
||||
this.actionTypeOptions.push({
|
||||
id: FilterAction.MoveTo,
|
||||
name: i18nFilter('ACTION_MOVE_TO')
|
||||
});
|
||||
this.actionTypeOptions.push({
|
||||
id: FilterAction.Forward,
|
||||
name: i18nFilter('ACTION_FORWARD_TO')
|
||||
});
|
||||
}
|
||||
|
||||
if (capa.includes('reject')) {
|
||||
this.actionTypeOptions.push({ id: FilterAction.Reject, name: i18nFilter('ACTION_REJECT') });
|
||||
}
|
||||
|
||||
if (capa.includes('vacation')) {
|
||||
this.actionTypeOptions.push({
|
||||
id: FilterAction.Vacation,
|
||||
name: i18nFilter('ACTION_VACATION_MESSAGE')
|
||||
});
|
||||
}
|
||||
|
||||
if (capa.includes('body')) {
|
||||
this.fieldOptions.push({ id: FilterConditionField.Body, name: i18nFilter('FIELD_BODY') });
|
||||
}
|
||||
|
||||
if (capa.includes('regex')) {
|
||||
this.typeOptions.push({ id: FilterConditionType.Regex, name: 'Regex' });
|
||||
}
|
||||
}
|
||||
|
||||
this.actionTypeOptions.push({ id: FilterAction.Discard, name: i18nFilter('ACTION_DISCARD') });
|
||||
|
||||
this.typeOptionsSize([
|
||||
{ id: FilterConditionType.Over, name: i18nFilter('TYPE_OVER') },
|
||||
{ id: FilterConditionType.Under, name: i18nFilter('TYPE_UNDER') }
|
||||
]);
|
||||
|
||||
this.typeOptionsBody([
|
||||
{ id: FilterConditionType.Text, name: i18nFilter('TYPE_TEXT') },
|
||||
{ id: FilterConditionType.Raw, name: i18nFilter('TYPE_RAW') }
|
||||
]);
|
||||
}
|
||||
|
||||
removeCondition(oConditionToDelete) {
|
||||
this.filter().removeCondition(oConditionToDelete);
|
||||
}
|
||||
|
||||
beforeShow(oFilter, fTrueCallback, bEdit) {
|
||||
// onShow(oFilter, fTrueCallback, bEdit) {
|
||||
this.isNew(!bEdit);
|
||||
|
||||
this.fTrueCallback = fTrueCallback;
|
||||
this.filter(oFilter);
|
||||
|
||||
this.selectedFolderValue(oFilter.actionValue());
|
||||
|
||||
bEdit || oFilter.nameFocused(true);
|
||||
|
||||
this.populateOptions();
|
||||
}
|
||||
|
||||
afterShow() {
|
||||
this.isNew() && this.filter().nameFocused(true);
|
||||
}
|
||||
}
|
||||
136
dev/Sieve/View/Script.js
Normal file
136
dev/Sieve/View/Script.js
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
import { FilterModel } from 'Sieve/Model/Filter';
|
||||
import { SieveScriptModel } from 'Sieve/Model/Script';
|
||||
|
||||
import { FilterPopupView } from 'Sieve/View/Filter';
|
||||
|
||||
//import { parseScript } from 'Sieve/Parser';
|
||||
|
||||
import {
|
||||
capa,
|
||||
scripts,
|
||||
getNotification,
|
||||
Remote
|
||||
} from 'Sieve/Utils';
|
||||
|
||||
export class SieveScriptPopupView extends rl.pluginPopupView {
|
||||
constructor() {
|
||||
super('SieveScript');
|
||||
|
||||
this.addObservables({
|
||||
saveError: false,
|
||||
saveErrorText: '',
|
||||
rawActive: false,
|
||||
allowToggle: false,
|
||||
script: null
|
||||
});
|
||||
|
||||
this.sieveCapabilities = capa.join(' ');
|
||||
this.saving = false;
|
||||
|
||||
this.filterForDeletion = ko.observable(null).askDeleteHelper();
|
||||
}
|
||||
|
||||
saveScript() {
|
||||
let self = this,
|
||||
script = self.script();
|
||||
if (!self.saving/* && script.hasChanges()*/) {
|
||||
if (!script.verify()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!script.exists() && scripts.find(item => item.name() === script.name())) {
|
||||
script.nameError(true);
|
||||
return;
|
||||
}
|
||||
|
||||
self.saving = true;
|
||||
self.saveError(false);
|
||||
|
||||
if (self.allowToggle()) {
|
||||
script.body(script.filtersToRaw());
|
||||
}
|
||||
|
||||
Remote.request('FiltersScriptSave',
|
||||
(iError, data) => {
|
||||
self.saving = false;
|
||||
|
||||
if (iError) {
|
||||
self.saveError(true);
|
||||
self.saveErrorText((data && data.ErrorMessageAdditional) || getNotification(iError));
|
||||
} else {
|
||||
script.exists() || scripts.push(script);
|
||||
script.exists(true);
|
||||
script.hasChanges(false);
|
||||
}
|
||||
},
|
||||
script.toJson()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
deleteFilter(filter) {
|
||||
this.script().filters.remove(filter);
|
||||
}
|
||||
|
||||
addFilter() {
|
||||
/* this = SieveScriptModel */
|
||||
const filter = new FilterModel();
|
||||
filter.generateID();
|
||||
FilterPopupView.showModal([
|
||||
filter,
|
||||
() => this.filters.push(filter)
|
||||
]);
|
||||
}
|
||||
|
||||
editFilter(filter) {
|
||||
const clonedFilter = filter.cloneSelf();
|
||||
FilterPopupView.showModal([
|
||||
clonedFilter,
|
||||
() => {
|
||||
const script = this.script(),
|
||||
filters = script.filters(),
|
||||
index = filters.indexOf(filter);
|
||||
if (-1 < index) {
|
||||
// script.filters.splice(index, 1, clonedFilter);
|
||||
filters[index] = clonedFilter;
|
||||
script.filters(filters);
|
||||
}
|
||||
},
|
||||
true
|
||||
]);
|
||||
}
|
||||
|
||||
toggleFiltersRaw() {
|
||||
let script = this.script(), notRaw = !this.rawActive();
|
||||
if (notRaw) {
|
||||
script.body(script.filtersToRaw());
|
||||
script.hasChanges(script.hasChanges());
|
||||
}
|
||||
this.rawActive(notRaw);
|
||||
}
|
||||
|
||||
onBuild(oDom) {
|
||||
oDom.addEventListener('click', event => {
|
||||
const el = event.target.closestWithin('td.e-action', oDom),
|
||||
filter = el && ko.dataFor(el);
|
||||
filter && this.editFilter(filter);
|
||||
});
|
||||
}
|
||||
|
||||
beforeShow(oScript) {
|
||||
// onShow(oScript) {
|
||||
oScript = oScript || new SieveScriptModel();
|
||||
let raw = !oScript.allowFilters();
|
||||
this.script(oScript);
|
||||
this.rawActive(raw);
|
||||
this.allowToggle(!raw);
|
||||
this.saveError(false);
|
||||
|
||||
/*
|
||||
// TODO: Sieve GUI
|
||||
let tree = parseScript(oScript.body(), oScript.name());
|
||||
console.dir(tree);
|
||||
console.log(tree.join('\r\n'));
|
||||
*/
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue