luci-app-simple-adblock: convert to js
[project/luci.git] / applications / luci-app-simple-adblock / htdocs / luci-static / resources / simple-adblock / status.js
1 // Copyright 2022 Stan Grishin <stangri@melmac.ca>
2 // This code wouldn't have been possible without help from [@vsviridov](https://github.com/vsviridov)
3
4 "require ui";
5 "require rpc";
6 "require form";
7 "require baseclass";
8
9 var pkg = {
10 get Name() { return 'simple-adblock'; },
11 get URL() { return 'https://docs.openwrt.melmac.net/' + pkg.Name + '/'; },
12 };
13
14 var getInitList = rpc.declare({
15 object: "luci." + pkg.Name,
16 method: "getInitList",
17 params: ["name"],
18 });
19
20 var getInitStatus = rpc.declare({
21 object: "luci." + pkg.Name,
22 method: "getInitStatus",
23 params: ["name"],
24 });
25
26 var getPlatformSupport = rpc.declare({
27 object: "luci." + pkg.Name,
28 method: "getPlatformSupport",
29 params: ["name"],
30 });
31
32 var _setInitAction = rpc.declare({
33 object: "luci." + pkg.Name,
34 method: "setInitAction",
35 params: ["name", "action"],
36 expect: { result: false },
37 });
38
39 var RPC = {
40 listeners: [],
41 on: function on(event, callback) {
42 var pair = { event: event, callback: callback }
43 this.listeners.push(pair);
44 return function unsubscribe() {
45 this.listeners = this.listeners.filter(function (listener) {
46 return listener !== pair;
47 });
48 }.bind(this);
49 },
50 emit: function emit(event, data) {
51 this.listeners.forEach(function (listener) {
52 if (listener.event === event) {
53 listener.callback(data);
54 }
55 });
56 },
57 getInitList: function getInitList(name) {
58 getInitList(name).then(function (result) {
59 this.emit('getInitList', result);
60 }.bind(this));
61 },
62 getInitStatus: function getInitStatus(name) {
63 getInitStatus(name).then(function (result) {
64 this.emit('getInitStatus', result);
65 }.bind(this));
66 },
67 getPlatformSupport: function getPlatformSupport(name) {
68 getPlatformSupport(name).then(function (result) {
69 this.emit('getPlatformSupport', result);
70 }.bind(this));
71 },
72 setInitAction: function setInitAction(name, action) {
73 _setInitAction(name, action).then(function (result) {
74 this.emit('setInitAction', result);
75 }.bind(this));
76 },
77 }
78
79 var status = baseclass.extend({
80 render: function () {
81 return Promise.all([
82 L.resolveDefault(getInitStatus(), {}),
83 ]).then(function (data) {
84 var replyStatus = data[0];
85 var text ="";
86 var status = replyStatus[pkg.Name];
87 var outputFile = status.outputFile;
88 var outputCache = status.outputCache;
89 var statusTable = {
90 statusNoInstall: _("%s is not installed or not found").format(pkg.Name),
91 statusStopped: _("Stopped"),
92 statusStarting: _("Starting"),
93 statusRestarting: _("Restarting"),
94 statusForceReloading: _("Force Reloading"),
95 statusDownloading: _("Downloading"),
96 statusError: _("Error"),
97 statusWarning: _("Warning"),
98 statusFail: _("Fail"),
99 statusSuccess: _("Active")
100 };
101
102 var header = E('h2', {}, _("Simple AdBlock - Status"))
103 var statusTitle = E('label', { class: 'cbi-value-title' }, _("Service Status"));
104 if (status.version) {
105 text += _("Version: %s").format(status.version) + " - ";
106 switch (status.status) {
107 case 'statusSuccess':
108 text += statusTable[status.status] + ".";
109 text += "<br />" + _("Blocking %s domains (with %s).").format(status.entries, status.dns);
110 if (status.outputGzipExists) {
111 text += "<br />" + _("Compressed cache file created.");
112 }
113 if (status.force_dns_active) {
114 text += "<br />" + _("Force DNS ports:");
115 status.force_dns_ports.forEach(element => {
116 text += " " + element;
117 });
118 text += ".";
119 }
120 break;
121 case 'statusStopped':
122 if (status.enabled) {
123 text += statusTable[status.status] + ".";
124 }
125 else {
126 text += statusTable[status.status] + _("disabled") + "."
127 }
128 if (status.outputCacheExists) {
129 text += "<br />" + _("Cache file found.");
130 }
131 else if (status.outputGzipExists) {
132 text += "<br />" + _("Compressed cache file found.");
133 }
134 break;
135 case 'statusRestarting':
136 case 'statusForceReloading':
137 case 'statusDownloading':
138 text += statusTable[status.status] + "...";
139 break;
140 default:
141 text += statusTable[status.status] + ".";
142 break;
143 }
144 }
145 else {
146 text = _("Not installed or not found");
147 }
148 var statusText = E('div', {}, text);
149 var statusField = E('div', { class: 'cbi-value-field' }, statusText);
150 var statusDiv = E('div', { class: 'cbi-value' }, [statusTitle, statusField]);
151
152 var warningsDiv = [];
153 if (status.warnings) {
154 var warningsTitle = E('label', { class: 'cbi-value-title' }, _("Service Warnings"));
155 var warningsText = E('div', {}, status.warnings);
156 var warningsField = E('div', { class: 'cbi-value-field' }, warningsText);
157 warningsDiv = E('div', { class: 'cbi-value' }, [warningsTitle, warningsField]);
158 }
159
160 var errorsDiv = [];
161 if ((status.errors).length) {
162 var errorTable = {
163 errorOutputFileCreate: _("failed to create '%s' file").format(outputFile),
164 errorFailDNSReload: _("failed to restart/reload DNS resolver"),
165 errorSharedMemory: _("failed to access shared memory"),
166 errorSorting: _("failed to sort data file"),
167 errorOptimization: _("failed to optimize data file"),
168 errorAllowListProcessing: _("failed to process allow-list"),
169 errorDataFileFormatting: _("failed to format data file"),
170 errorMovingDataFile: _("failed to move temporary data file to '%s'").format(outputFile),
171 errorCreatingCompressedCache: _("failed to create compressed cache"),
172 errorRemovingTempFiles: _("failed to remove temporary files"),
173 errorRestoreCompressedCache: _("failed to unpack compressed cache"),
174 errorRestoreCache: _("failed to move '%s' to '%s'").format(outputCache, outputFile),
175 errorOhSnap: _("failed to create block-list or restart DNS resolver"),
176 errorStopping: _("failed to stop %s").format(pkg.Name),
177 errorDNSReload: _("failed to reload/restart DNS resolver"),
178 errorDownloadingConfigUpdate: _("failed to download Config Update file"),
179 errorDownloadingList: _("failed to download"),
180 errorParsingConfigUpdate: _("failed to parse Config Update file"),
181 errorParsingList: _("failed to parse"),
182 errorNoSSLSupport: _("no HTTPS/SSL support on device"),
183 errorCreatingDirectory: _("failed to create output/cache/gzip file directory")
184 }
185 var errorsTitle = E('label', { class: 'cbi-value-title' }, _("Service Errors"));
186 var text = "";
187 (status.errors).forEach(element => {
188 text += errorTable[element] + ".<br />";
189 });
190 var errorsText = E('div', {}, text);
191 var errorsField = E('div', { class: 'cbi-value-field' }, errorsText);
192 errorsDiv = E('div', { class: 'cbi-value' }, [errorsTitle, errorsField]);
193 }
194
195 var btn_gap = E('span', {}, '&#160;&#160;');
196 var btn_gap_long = E('span', {}, '&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;');
197
198 var btn_start = E('button', {
199 'class': 'btn cbi-button cbi-button-apply',
200 disabled: true,
201 click: function (ev) {
202 ui.showModal(null, [
203 E('p', { 'class': 'spinning' }, _('Starting %s service').format(pkg.Name))
204 ]);
205 return RPC.setInitAction(pkg.Name, 'start');
206 }
207 }, _('Start'));
208
209 var btn_action = E('button', {
210 'class': 'btn cbi-button cbi-button-apply',
211 disabled: true,
212 click: function (ev) {
213 ui.showModal(null, [
214 E('p', { 'class': 'spinning' }, _('Force re-downloading %s block lists').format(pkg.Name))
215 ]);
216 return RPC.setInitAction(pkg.Name, 'dl');
217 }
218 }, _('Force Re-Download'));
219
220 var btn_stop = E('button', {
221 'class': 'btn cbi-button cbi-button-reset',
222 disabled: true,
223 click: function (ev) {
224 ui.showModal(null, [
225 E('p', { 'class': 'spinning' }, _('Stopping %s service').format(pkg.Name))
226 ]);
227 return RPC.setInitAction(pkg.Name, 'stop');
228 }
229 }, _('Stop'));
230
231 var btn_enable = E('button', {
232 'class': 'btn cbi-button cbi-button-apply',
233 disabled: true,
234 click: function (ev) {
235 ui.showModal(null, [
236 E('p', { 'class': 'spinning' }, _('Enabling %s service').format(pkg.Name))
237 ]);
238 return RPC.setInitAction(pkg.Name, 'enable');
239 }
240 }, _('Enable'));
241
242 var btn_disable = E('button', {
243 'class': 'btn cbi-button cbi-button-reset',
244 disabled: true,
245 click: function (ev) {
246 ui.showModal(null, [
247 E('p', { 'class': 'spinning' }, _('Disabling %s service').format(pkg.Name))
248 ]);
249 return RPC.setInitAction(pkg.Name, 'disable');
250 }
251 }, _('Disable'));
252
253 if (status.enabled) {
254 btn_enable.disabled = true;
255 btn_disable.disabled = false;
256 switch (status.status) {
257 case 'statusSuccess':
258 btn_start.disabled = true;
259 btn_action.disabled = false;
260 btn_stop.disabled = false;
261 break;
262 case 'statusStopped':
263 btn_start.disabled = false;
264 btn_action.disabled = true;
265 btn_stop.disabled = true;
266 break;
267 default:
268 btn_start.disabled = true;
269 btn_action.disabled = true;
270 btn_stop.disabled = true;
271 btn_enable.disabled = true;
272 btn_disable.disabled = true;
273 break;
274 }
275 }
276 else {
277 btn_start.disabled = true;
278 btn_action.disabled = true;
279 btn_stop.disabled = true;
280 btn_enable.disabled = false;
281 btn_disable.disabled = true;
282 }
283
284 var buttonsDiv = [];
285 var buttonsTitle = E('label', { class: 'cbi-value-title' }, _("Service Control"))
286 var buttonsText = E('div', {}, [btn_start, btn_gap, btn_action, btn_gap, btn_stop, btn_gap_long, btn_enable, btn_gap, btn_disable]);
287 var buttonsField = E('div', { class: 'cbi-value-field' }, buttonsText);
288 if (status.version) {
289 buttonsDiv = E('div', { class: 'cbi-value' }, [buttonsTitle, buttonsField]);
290 }
291
292 return E('div', {}, [header, statusDiv, warningsDiv, errorsDiv, buttonsDiv]);
293 });
294 },
295 });
296
297 RPC.on('setInitAction', function (reply) {
298 ui.hideModal();
299 location.reload();
300 });
301
302 return L.Class.extend({
303 status: status,
304 getPlatformSupport: getPlatformSupport
305 });