mirror of
https://github.com/remittor/zapret-openwrt.git
synced 2025-12-13 23:16:51 +03:00
356 lines
12 KiB
JavaScript
356 lines
12 KiB
JavaScript
'use strict';
|
|
'require baseclass';
|
|
'require fs';
|
|
'require rpc';
|
|
'require ui';
|
|
'require uci';
|
|
|
|
document.head.append(E('style', {'type': 'text/css'},
|
|
`
|
|
.label-status {
|
|
display: inline;
|
|
margin: 0 2px 0 0 !important;
|
|
padding: 2px 4px;
|
|
-webkit-border-radius: 3px;
|
|
-moz-border-radius: 3px;
|
|
border-radius: 3px;
|
|
font-weight: bold;
|
|
color: #fff !important;
|
|
}
|
|
.starting {
|
|
background-color: #9c994c !important;
|
|
}
|
|
.running {
|
|
background-color: #2ea256 !important;
|
|
}
|
|
.updating {
|
|
background-color: #1e82ff !important;
|
|
}
|
|
.stopped {
|
|
background-color: #8a8a8a !important;
|
|
}
|
|
.error {
|
|
background-color: #ff4e54 !important;
|
|
}
|
|
`));
|
|
|
|
return baseclass.extend({
|
|
appName : 'zapret',
|
|
execPath : '/opt/zapret/init.d/openwrt/zapret',
|
|
hostsUserFN : '/opt/zapret/ipset/zapret-hosts-user.txt',
|
|
iplstUserFN : '/opt/zapret/ipset/zapret-ip-user.txt',
|
|
|
|
infoLabelStarting : '<span class="label-status starting">' + _('Starting') + '</span>',
|
|
infoLabelRunning : '<span class="label-status running">' + _('Enabled') + '</span>',
|
|
infoLabelUpdating : '<span class="label-status updating">' + _('Updating') + '</span>',
|
|
infoLabelStopped : '<span class="label-status stopped">' + _('Disabled') + '</span>',
|
|
infoLabelError : '<span class="label-status error">' + _('Error') + '</span>',
|
|
|
|
callInitStatus: rpc.declare({
|
|
object: 'luci',
|
|
method: 'getInitList',
|
|
params: [ 'name' ],
|
|
expect: { '': {} }
|
|
}),
|
|
|
|
callInitAction: rpc.declare({
|
|
object: 'luci',
|
|
method: 'setInitAction',
|
|
params: [ 'name', 'action' ],
|
|
expect: { result: false }
|
|
}),
|
|
|
|
getInitStatus: function(name) {
|
|
return this.callInitStatus(name).then(res => {
|
|
if (res) {
|
|
return res[name].enabled;
|
|
} else {
|
|
throw _('Command failed');
|
|
}
|
|
}).catch(e => {
|
|
ui.addNotification(null, E('p', _('Failed to get %s init status: %s').format(name, e)));
|
|
});
|
|
},
|
|
|
|
handleServiceAction: function(name, action) {
|
|
return this.callInitAction(name, action).then(success => {
|
|
if (!success) {
|
|
throw _('Command failed');
|
|
}
|
|
return true;
|
|
}).catch(e => {
|
|
ui.addNotification(null, E('p', _('Service action failed "%s %s": %s').format(name, action, e)));
|
|
});
|
|
},
|
|
|
|
normalizeValue: function(v) {
|
|
return (v && typeof(v) === 'string') ? v.trim().replace(/\r?\n/g, '') : v;
|
|
},
|
|
|
|
makeStatusString: function(app_status_code, fwtype, bllist_preset) {
|
|
let app_status_label;
|
|
let spinning = '';
|
|
/*
|
|
switch(app_status_code) {
|
|
case 0:
|
|
app_status_label = this.infoLabelRunning;
|
|
break;
|
|
case 2:
|
|
app_status_label = this.infoLabelStopped;
|
|
break;
|
|
case 3:
|
|
app_status_label = this.infoLabelStarting;
|
|
spinning = ' spinning';
|
|
break;
|
|
case 4:
|
|
app_status_label = this.infoLabelUpdating;
|
|
spinning = ' spinning';
|
|
break;
|
|
default:
|
|
app_status_label = this.infoLabelError;
|
|
return `<table class="table">
|
|
<tr class="tr">
|
|
<td class="td left" style="min-width:33%%">
|
|
${_('Status')}:
|
|
</td>
|
|
<td class="td left">
|
|
${app_status_label}
|
|
</td>
|
|
</tr>
|
|
</table>`;
|
|
}
|
|
*/
|
|
return `<table class="table">
|
|
<tr class="tr">
|
|
<td class="td left" style="min-width:33%%">
|
|
${_('Status')}:
|
|
</td>
|
|
<td class="td left%s">
|
|
%s %s
|
|
</td>
|
|
</tr>
|
|
<tr class="tr">
|
|
<td class="td left">
|
|
${_('FW type')}:
|
|
</td>
|
|
<td class="td left">
|
|
%s
|
|
</td>
|
|
</tr>
|
|
<tr class="tr">
|
|
<td class="td left">
|
|
${_('Blacklist update mode')}:
|
|
</td>
|
|
<td class="td left">
|
|
%s
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
`.format(
|
|
spinning,
|
|
app_status_label,
|
|
'',
|
|
fwtype,
|
|
_('user entries only')
|
|
);
|
|
},
|
|
|
|
fileEditDialog: baseclass.extend({
|
|
__init__: function(file, title, desc, aux = null, rows = 10, callback, file_exists = false) {
|
|
this.file = file;
|
|
this.title = title;
|
|
this.desc = desc;
|
|
this.aux = aux;
|
|
this.rows = rows,
|
|
this.callback = callback;
|
|
this.file_exists = file_exists;
|
|
},
|
|
|
|
load: function() {
|
|
return L.resolveDefault(fs.read(this.file), '');
|
|
},
|
|
|
|
render: function(content) {
|
|
let descr = this.desc;
|
|
if (this.aux)
|
|
descr += '<br />' + this.aux;
|
|
ui.showModal(this.title, [
|
|
E('div', { 'class': 'cbi-section' }, [
|
|
E('div', { 'class': 'cbi-section-descr' }, descr),
|
|
E('div', { 'class': 'cbi-section' },
|
|
E('p', {},
|
|
E('textarea', {
|
|
'id': 'widget.modal_content',
|
|
'class': 'cbi-input-textarea',
|
|
'style': 'width:100% !important',
|
|
'rows': this.rows,
|
|
'wrap': 'off',
|
|
'spellcheck': 'false',
|
|
},
|
|
content)
|
|
)
|
|
),
|
|
]),
|
|
E('div', { 'class': 'right' }, [
|
|
E('button', {
|
|
'class': 'btn',
|
|
'click': ui.hideModal,
|
|
}, _('Dismiss')),
|
|
' ',
|
|
E('button', {
|
|
'id': 'btn_save',
|
|
'class': 'btn cbi-button-positive important',
|
|
'click': ui.createHandlerFn(this, this.handleSave),
|
|
}, _('Save')),
|
|
]),
|
|
]);
|
|
},
|
|
|
|
handleSave: function(ev) {
|
|
let txt = document.getElementById('widget.modal_content');
|
|
let value = txt.value.trim().replace(/\r\n/g, '\n') + '\n';
|
|
|
|
return fs.write(this.file, value).then(async rc => {
|
|
txt.value = value;
|
|
ui.addNotification(null, E('p', _('Contents have been saved.')), 'info');
|
|
if (this.callback) {
|
|
return this.callback(rc);
|
|
}
|
|
}).catch(e => {
|
|
ui.addNotification(null, E('p', _('Unable to save the contents') + ': %s'.format(e.message)));
|
|
}).finally(() => {
|
|
ui.hideModal();
|
|
});
|
|
},
|
|
|
|
error: function(e) {
|
|
if (!this.file_exists && e instanceof Error && e.name === 'NotFoundError') {
|
|
return this.render();
|
|
} else {
|
|
ui.showModal(this.title, [
|
|
E('div', { 'class': 'cbi-section' },
|
|
E('p', {}, _('Unable to read the contents') + ': %s'.format(e.message))
|
|
),
|
|
E('div', { 'class': 'right' },
|
|
E('button', {
|
|
'class': 'btn',
|
|
'click': ui.hideModal,
|
|
}, _('Dismiss'))
|
|
),
|
|
]);
|
|
}
|
|
},
|
|
|
|
show: function() {
|
|
ui.showModal(null,
|
|
E('p', { 'class': 'spinning' }, _('Loading'))
|
|
);
|
|
this.load().then(content => {
|
|
ui.hideModal();
|
|
return this.render(content);
|
|
}).catch(e => {
|
|
ui.hideModal();
|
|
return this.error(e);
|
|
});
|
|
},
|
|
}),
|
|
|
|
longstrEditDialog: baseclass.extend({
|
|
__init__: function(cfgsec, cfgparam, title, desc, rows = 10) {
|
|
this.cfgsec = cfgsec;
|
|
this.cfgparam = cfgparam;
|
|
this.title = title;
|
|
this.desc = desc;
|
|
this.rows = rows;
|
|
},
|
|
|
|
load: function() {
|
|
return uci.get('zapret', this.cfgsec, this.cfgparam);
|
|
},
|
|
|
|
render: function(content) {
|
|
ui.showModal(this.title, [
|
|
E('div', { 'class': 'cbi-section' }, [
|
|
E('div', { 'class': 'cbi-section-descr' }, this.desc),
|
|
E('div', { 'class': 'cbi-section' },
|
|
E('p', {},
|
|
E('textarea', {
|
|
'id': 'widget.modal_content',
|
|
'class': 'cbi-input-textarea',
|
|
'style': 'width:100% !important',
|
|
'rows': this.rows,
|
|
'wrap': 'on',
|
|
'spellcheck': 'false',
|
|
},
|
|
content)
|
|
)
|
|
),
|
|
]),
|
|
E('div', { 'class': 'right' }, [
|
|
E('button', {
|
|
'class': 'btn',
|
|
'click': ui.hideModal,
|
|
}, _('Dismiss')),
|
|
' ',
|
|
E('button', {
|
|
'id': 'btn_save',
|
|
'class': 'btn cbi-button-positive important',
|
|
'click': ui.createHandlerFn(this, this.handleSave),
|
|
}, _('Save')),
|
|
]),
|
|
]);
|
|
},
|
|
|
|
handleSave: function(ev) {
|
|
let txt = document.getElementById('widget.modal_content');
|
|
let value = txt.value.trim().replace(/\r\n/g, ' ').replace(/\r/g, ' ').replace(/\n/g, ' ').trim();
|
|
|
|
uci.set('zapret', this.cfgsec, this.cfgparam, value);
|
|
uci.save();
|
|
let elem = document.getElementById("cbi-zapret-" + this.cfgsec + "-_" + this.cfgparam);
|
|
if (elem) {
|
|
elem.querySelector('div').textContent = value;
|
|
}
|
|
ui.hideModal();
|
|
/*
|
|
return uci.save()
|
|
.then(L.bind(ui.changes.init, ui.changes))
|
|
.then(L.bind(ui.changes.displayChanges, ui.changes))
|
|
//.then(L.bind(ui.changes.apply, ui.changes))
|
|
.then(ui.addNotification(null, E('p', _('Contents have been saved.')), 'info'))
|
|
.catch(e => {
|
|
ui.addNotification(null, E('p', _('Unable to save the contents') + ': %s'.format(e.message)));
|
|
}).finally(() => {
|
|
ui.hideModal();
|
|
});
|
|
*/
|
|
},
|
|
|
|
error: function(e) {
|
|
let msg = (typeof(e) == 'object') ? e.message : ''+e;
|
|
ui.showModal(this.title, [
|
|
E('div', { 'class': 'cbi-section' },
|
|
E('p', {}, _('Unable to read the contents') + ': %s'.format(msg))
|
|
),
|
|
E('div', { 'class': 'right' },
|
|
E('button', {
|
|
'class': 'btn',
|
|
'click': ui.hideModal,
|
|
}, _('Dismiss'))
|
|
),
|
|
]);
|
|
},
|
|
|
|
show: function() {
|
|
//ui.showModal(null, E('p', { 'class': 'spinning' }, _('Loading')) );
|
|
let content = this.load();
|
|
//ui.hideModal();
|
|
if (content === null) {
|
|
return this.error('Cannot load parameter');
|
|
}
|
|
return this.render(content);
|
|
},
|
|
}),
|
|
|
|
});
|