mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-13 03:27:39 +03:00
Draft of new Filters design
This commit is contained in:
parent
cd504ffa4b
commit
61c3da14b4
8 changed files with 446 additions and 114 deletions
81
dev/Model/SieveScript.js
Normal file
81
dev/Model/SieveScript.js
Normal 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 };
|
||||||
|
|
@ -1,13 +1,14 @@
|
||||||
import ko from 'ko';
|
import ko from 'ko';
|
||||||
|
|
||||||
import { delegateRunOnDestroy } from 'Common/UtilsUser';
|
|
||||||
import { StorageResultType, Notification } from 'Common/Enums';
|
import { StorageResultType, Notification } from 'Common/Enums';
|
||||||
import { getNotification } from 'Common/Translator';
|
import { getNotification } from 'Common/Translator';
|
||||||
|
|
||||||
import FilterStore from 'Stores/User/Filter';
|
import FilterStore from 'Stores/User/Filter';
|
||||||
|
import SieveStore from 'Stores/User/Sieve';
|
||||||
import Remote from 'Remote/User/Fetch';
|
import Remote from 'Remote/User/Fetch';
|
||||||
|
|
||||||
import { FilterModel } from 'Model/Filter';
|
import { FilterModel } from 'Model/Filter';
|
||||||
|
import { SieveScriptModel } from 'Model/SieveScript';
|
||||||
|
|
||||||
import { showScreenPopup, command } from 'Knoin/Knoin';
|
import { showScreenPopup, command } from 'Knoin/Knoin';
|
||||||
|
|
||||||
|
|
@ -15,6 +16,8 @@ class FiltersUserSettings {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.modules = FilterStore.modules;
|
this.modules = FilterStore.modules;
|
||||||
this.filters = FilterStore.filters;
|
this.filters = FilterStore.filters;
|
||||||
|
this.sieve = SieveStore;
|
||||||
|
this.scripts = SieveStore.scripts;
|
||||||
|
|
||||||
ko.addObservablesTo(this, {
|
ko.addObservablesTo(this, {
|
||||||
inited: false,
|
inited: false,
|
||||||
|
|
@ -94,6 +97,7 @@ class FiltersUserSettings {
|
||||||
Remote.filtersGet((result, data) => {
|
Remote.filtersGet((result, data) => {
|
||||||
this.filters.loading(false);
|
this.filters.loading(false);
|
||||||
this.serverError(false);
|
this.serverError(false);
|
||||||
|
this.scripts([]);
|
||||||
|
|
||||||
if (StorageResultType.Success === result && data && data.Result && Array.isArray(data.Result.Filters)) {
|
if (StorageResultType.Success === result && data && data.Result && Array.isArray(data.Result.Filters)) {
|
||||||
this.inited(true);
|
this.inited(true);
|
||||||
|
|
@ -105,6 +109,17 @@ class FiltersUserSettings {
|
||||||
|
|
||||||
this.modules(data.Result.Capa);
|
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(data.Result.Scripts['rainloop.user.raw'].body);
|
||||||
this.filterRaw.capa(data.Result.Capa.join(' '));
|
this.filterRaw.capa(data.Result.Capa.join(' '));
|
||||||
this.filterRaw.active(data.Result.Scripts['rainloop.user.raw'].active);
|
this.filterRaw.active(data.Result.Scripts['rainloop.user.raw'].active);
|
||||||
|
|
@ -112,6 +127,9 @@ class FiltersUserSettings {
|
||||||
} else {
|
} else {
|
||||||
this.filters([]);
|
this.filters([]);
|
||||||
this.modules({});
|
this.modules({});
|
||||||
|
|
||||||
|
this.sieve.capa([]);
|
||||||
|
|
||||||
this.filterRaw('');
|
this.filterRaw('');
|
||||||
this.filterRaw.capa({});
|
this.filterRaw.capa({});
|
||||||
|
|
||||||
|
|
@ -126,50 +144,38 @@ class FiltersUserSettings {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteFilter(filter) {
|
addScript() {
|
||||||
this.filters.remove(filter);
|
const script = new SieveScriptModel();
|
||||||
delegateRunOnDestroy(filter);
|
showScreenPopup(require('View/Popup/SieveScript'), [
|
||||||
}
|
script,
|
||||||
|
|
||||||
addFilter() {
|
|
||||||
const filter = new FilterModel();
|
|
||||||
|
|
||||||
filter.generateID();
|
|
||||||
showScreenPopup(require('View/Popup/Filter'), [
|
|
||||||
filter,
|
|
||||||
() => {
|
() => {
|
||||||
this.filters.push(filter);
|
if (!this.scripts[script.name]) {
|
||||||
this.filterRaw.active(false);
|
this.scripts[script.name] = script.name;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
false
|
false
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
editFilter(filter) {
|
editScript(script) {
|
||||||
const clonedFilter = filter.cloneSelf();
|
showScreenPopup(require('View/Popup/SieveScript'), [
|
||||||
|
script,
|
||||||
showScreenPopup(require('View/Popup/Filter'), [
|
|
||||||
clonedFilter,
|
|
||||||
() => {
|
() => {
|
||||||
const filters = this.filters(),
|
// TODO on save
|
||||||
index = filters.indexOf(filter);
|
|
||||||
|
|
||||||
if (-1 < index && filters[index]) {
|
|
||||||
delegateRunOnDestroy(filters[index]);
|
|
||||||
filters[index] = clonedFilter;
|
|
||||||
|
|
||||||
this.filters(filters);
|
|
||||||
this.haveChanges(true);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
true
|
true
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deleteScript() {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
onBuild(oDom) {
|
onBuild(oDom) {
|
||||||
oDom.addEventListener('click', event => {
|
oDom.addEventListener('click', event => {
|
||||||
const el = event.target.closestWithin('.filter-item .e-action', oDom);
|
const el = event.target.closestWithin('.script-item .e-action', oDom),
|
||||||
el && ko.dataFor(el) && this.editFilter(ko.dataFor(el));
|
script = el && ko.dataFor(el);
|
||||||
|
script && this.editScript(script);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
12
dev/Stores/User/Sieve.js
Normal file
12
dev/Stores/User/Sieve.js
Normal 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();
|
||||||
169
dev/View/Popup/SieveScript.js
Normal file
169
dev/View/Popup/SieveScript.js
Normal 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 };
|
||||||
|
|
@ -64,10 +64,19 @@ class SieveStorage implements FiltersInterface
|
||||||
foreach ($aList as $name => $active) {
|
foreach ($aList as $name => $active) {
|
||||||
if ($name != self::SIEVE_FILE_NAME) {
|
if ($name != self::SIEVE_FILE_NAME) {
|
||||||
$aScripts[$name] = array(
|
$aScripts[$name] = array(
|
||||||
|
'@Object' => 'Object/SieveScript',
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
'active' => $active,
|
'active' => $active,
|
||||||
'body' => $oSieveClient->GetScript($name) // \trim() ?
|
'body' => $oSieveClient->GetScript($name) // \trim() ?
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
$aScripts[$name] = array(
|
||||||
|
'@Object' => 'Object/SieveScript',
|
||||||
|
'name' => $name,
|
||||||
|
'active' => $active,
|
||||||
|
'body' => $oSieveClient->GetScript($name), // \trim() ?
|
||||||
|
'filters' => $aFilters
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -77,12 +86,15 @@ class SieveStorage implements FiltersInterface
|
||||||
|
|
||||||
if (!isset($aList[self::SIEVE_FILE_NAME_RAW])) {
|
if (!isset($aList[self::SIEVE_FILE_NAME_RAW])) {
|
||||||
$aScripts[$name] = array(
|
$aScripts[$name] = array(
|
||||||
|
'@Object' => 'Object/SieveScript',
|
||||||
'name' => self::SIEVE_FILE_NAME_RAW,
|
'name' => self::SIEVE_FILE_NAME_RAW,
|
||||||
'active' => false,
|
'active' => false,
|
||||||
'body' => ''
|
'body' => ''
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
\ksort($aScripts);
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'RawIsAllow' => $bAllowRaw,
|
'RawIsAllow' => $bAllowRaw,
|
||||||
'Filters' => $aFilters,
|
'Filters' => $aFilters,
|
||||||
|
|
|
||||||
|
|
@ -431,6 +431,7 @@ en:
|
||||||
BUTTON_BACK: "Back"
|
BUTTON_BACK: "Back"
|
||||||
SETTINGS_FILTERS:
|
SETTINGS_FILTERS:
|
||||||
LEGEND_FILTERS: "Filters"
|
LEGEND_FILTERS: "Filters"
|
||||||
|
LEGEND_SIEVE_SCRIPT: "Sieve Script"
|
||||||
BUTTON_SAVE: "Save"
|
BUTTON_SAVE: "Save"
|
||||||
BUTTON_ADD_FILTER: "Add a Filter"
|
BUTTON_ADD_FILTER: "Add a Filter"
|
||||||
BUTTON_DELETE: "Delete"
|
BUTTON_DELETE: "Delete"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,104 @@
|
||||||
|
<div class="modal fade b-filter-script g-ui-user-select-none" data-bind="modal: modalVisibility">
|
||||||
|
<div>
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-bind="command: cancelCommand">×</button>
|
||||||
|
<h3 class="i18n" data-i18n="POPUPS_FILTER/LEGEND_SIEVE_SCRIPT"></h3>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="row" data-bind="visible: inited() && !serverError()">
|
||||||
|
<div class="span5 width100-on-mobile">
|
||||||
|
<a class="btn" data-bind="visible: filterRaw.allow, click: function () { filterRaw.active(!filterRaw.active()) },
|
||||||
|
css: {'active': filterRaw.active }, tooltip: 'SETTINGS_FILTERS/BUTTON_RAW_SCRIPT'">
|
||||||
|
<i class="icon-file-code"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row" data-bind="visible: haveChanges">
|
||||||
|
<div class="span8 width100-on-mobile">
|
||||||
|
<br />
|
||||||
|
<div class="alert g-ui-user-select-none" style="margin-bottom: 0">
|
||||||
|
<i class="icon-warning"></i>
|
||||||
|
|
||||||
|
<span class="i18n" data-i18n="SETTINGS_FILTERS/CHANGES_NEED_TO_BE_SAVED_DESC"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row" data-bind="visible: serverError">
|
||||||
|
<div class="span8 width100-on-mobile">
|
||||||
|
<div class="alert alert-error g-ui-user-select-none" style="margin-bottom: 0">
|
||||||
|
<i class="icon-warning"></i>
|
||||||
|
|
||||||
|
<span data-bind="text: serverErrorDesc"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<div class="row">
|
||||||
|
<div class="span8 width100-on-mobile">
|
||||||
|
<div class="control-group" data-bind="css: {'error': filterRaw.error}, visible: inited() && filterRaw.allow() && filterRaw.active()">
|
||||||
|
<div class="controls">
|
||||||
|
<pre style="word-break: break-word;" data-bind="visible: '' !== filterRaw.capa()">
|
||||||
|
<b class="i18n" data-i18n="SETTINGS_FILTERS/CAPABILITY_LABEL"></b>:
|
||||||
|
<span data-bind="text: filterRaw.capa"></span>
|
||||||
|
</pre>
|
||||||
|
<textarea class="span8" style="height: 300px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace;"
|
||||||
|
data-bind="value: filterRaw, valueUpdate: 'afterkeydown'"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div data-bind="visible: inited() && (!filterRaw.active() || !filterRaw.active())">
|
||||||
|
<table class="table table-hover list-table filters-list g-ui-user-select-none"
|
||||||
|
data-bind="i18nUpdate: filters">
|
||||||
|
<colgroup>
|
||||||
|
<col style="width: 30px" />
|
||||||
|
<col style="width: 16px" />
|
||||||
|
<col />
|
||||||
|
<col style="width: 140px" />
|
||||||
|
<col style="width: 1%" />
|
||||||
|
</colgroup>
|
||||||
|
<tbody data-bind="foreach: filters" style="width: 600px">
|
||||||
|
<tr class="filter-item" draggable="true" data-bind="sortableItem: { list: $root.filters }">
|
||||||
|
<td>
|
||||||
|
<span class="disabled-filter" data-bind="click: function () { $root.haveChanges(true); enabled(!enabled()); }">
|
||||||
|
<i data-bind="css: {'icon-checkbox-checked': enabled, 'icon-checkbox-unchecked': !enabled()}"></i>
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td class="drag-wrapper">
|
||||||
|
<i class="icon-braille drag-handle"></i>
|
||||||
|
</td>
|
||||||
|
<td class="e-action">
|
||||||
|
<span class="filter-name" data-bind="text: name()"></span>
|
||||||
|
|
||||||
|
<span class="filter-sub-name" data-bind="text: nameSub()"></span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a class="btn btn-small btn-small-small btn-danger pull-right button-delete button-delete-transitions" data-bind="css: {'delete-access': deleteAccess()}, click: function(oFilter) { $root.deleteFilter(oFilter); }">
|
||||||
|
<span class="i18n" data-i18n="SETTINGS_FILTERS/DELETING_ASK"></span>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span class="delete-filter" data-bind="visible: !deleteAccess() && canBeDeleted(), click: function (oFilter) { $root.filterForDeletion(oFilter); }">
|
||||||
|
<i class="icon-trash"></i>
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<a class="btn" data-bind="click: addFilter">
|
||||||
|
<i class="icon-plus"></i>
|
||||||
|
|
||||||
|
<span class="i18n" data-i18n="SETTINGS_FILTERS/BUTTON_ADD_FILTER"></span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<a class="btn buttonSave" data-bind="command: saveScriptCommand, tooltipErrorTip: saveErrorText, css: {'btn-danger': '' !== saveErrorText()}">
|
||||||
|
<i data-bind="css: {'icon-floppy': !script.saving(), 'icon-spinner animated': script.saving()}"></i>
|
||||||
|
|
||||||
|
<span class="i18n" data-i18n="SETTINGS_FILTERS/BUTTON_SAVE"></span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
@ -6,37 +6,6 @@
|
||||||
<i class="icon-spinner animated" style="margin-top: 5px" data-bind="visible: filters.loading"></i>
|
<i class="icon-spinner animated" style="margin-top: 5px" data-bind="visible: filters.loading"></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row" data-bind="visible: inited() && !serverError()">
|
|
||||||
<div class="span5 width100-on-mobile">
|
|
||||||
<a class="btn" data-bind="click: addFilter">
|
|
||||||
<i class="icon-plus"></i>
|
|
||||||
|
|
||||||
<span class="i18n" data-i18n="SETTINGS_FILTERS/BUTTON_ADD_FILTER"></span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a class="btn" data-bind="visible: filterRaw.allow, click: function () { filterRaw.active(!filterRaw.active()) },
|
|
||||||
css: {'active': filterRaw.active }, tooltip: 'SETTINGS_FILTERS/BUTTON_RAW_SCRIPT'">
|
|
||||||
<i class="icon-file-code"></i>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a class="btn hide-on-disabled-command" data-placement="bottom" data-join="top"
|
|
||||||
data-bind="command: saveChangesCommand, tooltipErrorTip: saveErrorText, css: {'btn-danger': '' !== saveErrorText()}">
|
|
||||||
<i data-bind="css: {'icon-floppy': !filters.saving(), 'icon-spinner animated': filters.saving()}"></i>
|
|
||||||
|
|
||||||
<span class="i18n" data-i18n="SETTINGS_FILTERS/BUTTON_SAVE"></span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row" data-bind="visible: haveChanges">
|
|
||||||
<div class="span8 width100-on-mobile">
|
|
||||||
<br />
|
|
||||||
<div class="alert g-ui-user-select-none" style="margin-bottom: 0">
|
|
||||||
<i class="icon-warning"></i>
|
|
||||||
|
|
||||||
<span class="i18n" data-i18n="SETTINGS_FILTERS/CHANGES_NEED_TO_BE_SAVED_DESC"></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row" data-bind="visible: serverError">
|
<div class="row" data-bind="visible: serverError">
|
||||||
<div class="span8 width100-on-mobile">
|
<div class="span8 width100-on-mobile">
|
||||||
<div class="alert alert-error g-ui-user-select-none" style="margin-bottom: 0">
|
<div class="alert alert-error g-ui-user-select-none" style="margin-bottom: 0">
|
||||||
|
|
@ -46,24 +15,10 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="span8 width100-on-mobile">
|
<div class="span8 width100-on-mobile">
|
||||||
<div class="control-group" data-bind="css: {'error': filterRaw.error}, visible: inited() && filterRaw.allow() && filterRaw.active()">
|
<table class="table table-hover list-table scripts-list g-ui-user-select-none"
|
||||||
<div class="controls">
|
data-bind="i18nUpdate: scripts">
|
||||||
<pre style="word-break: break-word;" data-bind="visible: '' !== filterRaw.capa()">
|
|
||||||
<b class="i18n" data-i18n="SETTINGS_FILTERS/CAPABILITY_LABEL"></b>:
|
|
||||||
<span data-bind="text: filterRaw.capa"></span>
|
|
||||||
</pre>
|
|
||||||
<textarea class="span8" style="height: 300px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace;"
|
|
||||||
data-bind="value: filterRaw, valueUpdate: 'afterkeydown'"></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div data-bind="visible: inited() && (!filterRaw.active() || !filterRaw.active())">
|
|
||||||
<div class="filters-list-top-padding"></div>
|
|
||||||
<table class="table table-hover list-table filters-list g-ui-user-select-none"
|
|
||||||
data-bind="i18nUpdate: filters">
|
|
||||||
<colgroup>
|
<colgroup>
|
||||||
<col style="width: 30px" />
|
<col style="width: 30px" />
|
||||||
<col style="width: 16px" />
|
<col style="width: 16px" />
|
||||||
|
|
@ -71,28 +26,21 @@
|
||||||
<col style="width: 140px" />
|
<col style="width: 140px" />
|
||||||
<col style="width: 1%" />
|
<col style="width: 1%" />
|
||||||
</colgroup>
|
</colgroup>
|
||||||
<tbody data-bind="foreach: filters" style="width: 600px">
|
<tbody data-bind="foreach: scripts">
|
||||||
<tr class="filter-item" draggable="true" data-bind="sortableItem: { list: $root.filters }">
|
<tr class="script-item">
|
||||||
<td>
|
<td>
|
||||||
<span class="disabled-filter" data-bind="click: function () { $root.haveChanges(true); enabled(!enabled()); }">
|
<span class="disabled-script" data-bind="click: function () { $root.haveChanges(true); active(!active()); }">
|
||||||
<i data-bind="css: {'icon-checkbox-checked': enabled, 'icon-checkbox-unchecked': !enabled()}"></i>
|
<i data-bind="css: {'icon-checkbox-checked': active, 'icon-checkbox-unchecked': !active()}"></i>
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td class="drag-wrapper">
|
<td class="e-action" class="script-name" data-bind="text: name()"></td>
|
||||||
<i class="icon-braille drag-handle"></i>
|
|
||||||
</td>
|
|
||||||
<td class="e-action">
|
|
||||||
<span class="filter-name" data-bind="text: name()"></span>
|
|
||||||
|
|
||||||
<span class="filter-sub-name" data-bind="text: nameSub()"></span>
|
|
||||||
</td>
|
|
||||||
<td>
|
<td>
|
||||||
<a class="btn btn-small btn-small-small btn-danger pull-right button-delete button-delete-transitions" data-bind="css: {'delete-access': deleteAccess()}, click: function(oFilter) { $root.deleteFilter(oFilter); }">
|
<a class="btn btn-small btn-small-small btn-danger pull-right button-delete button-delete-transitions" data-bind="css: {'delete-access': deleteAccess()}, click: function(oScript) { $root.deleteScript(oScript); }">
|
||||||
<span class="i18n" data-i18n="SETTINGS_FILTERS/DELETING_ASK"></span>
|
<span class="i18n" data-i18n="SETTINGS_FILTERS/DELETING_ASK"></span>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="delete-filter" data-bind="visible: !deleteAccess() && canBeDeleted(), click: function (oFilter) { $root.filterForDeletion(oFilter); }">
|
<span class="delete-script" data-bind="visible: !deleteAccess() && canBeDeleted(), click: function (oScript) { $root.filterForDeletion(oScript); }">
|
||||||
<i class="icon-trash"></i>
|
<i class="icon-trash"></i>
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
|
|
@ -102,4 +50,3 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue