luci2: rewrite LuCI2.ui.loading(), LuCI2.ui.dialog(), LuCI2.ui.login() and LuCI2...
[project/luci2/ui.git] / luci2 / htdocs / luci2 / view / system.software.js
1 L.ui.view.extend({
2         updateDiskSpace: function()
3         {
4                 return L.system.getDiskInfo().then(function(info) {
5                         $('#package_space').empty().append(
6                                 new L.ui.progress({
7                                         value:  info.root.used / 1024,
8                                         max:    info.root.total / 1024,
9                                         format: '%d ' + L.tr('kB') + ' / %d ' + L.tr('kB') + ' ' + L.trc('Used disk space', 'used') + ' (%d%%)'
10                                 }).render());
11                 });
12         },
13
14         installRemovePackage: function(name)
15         {
16                 if (typeof(name) != 'string')
17                         name = undefined;
18
19                 var pkgname   = (name || this.getAttribute('name')).replace(/^.*\//, '');
20                 var installed = name ? false : !!this.getAttribute('installed');
21                 var action    = installed ? L.opkg.removePackage : L.opkg.installPackage;
22                 var title     = (installed ? L.tr('Removing package "%s" …') : L.tr('Installing package "%s" …')).format(pkgname);
23                 var confirm   = (installed ? L.tr('Really remove package "%h" ?') : L.tr('Really install package "%h" ?')).format(pkgname);
24
25                 var self = this;
26
27                 L.ui.dialog(title, confirm, {
28                         style:   'confirm',
29                         confirm: function() {
30                                 L.ui.dialog(title, L.tr('Waiting for package manager …'), { style: 'wait' });
31
32                                 action(name || pkgname).then(function(res) {
33                                         self.fetchInstalledList().then(function() { return self.fetchPackageList(); }).then(function() {
34                                                 var output = [ ];
35
36                                                 if (res.stdout)
37                                                         output.push($('<pre />').text(res.stdout));
38
39                                                 if (res.stderr)
40                                                         output.push($('<pre />').addClass('alert-message').text(res.stderr));
41
42                                                 output.push(res.code ? L.tr('Package manager failed with status %d.').format(res.code) : L.tr('Package manager finished successfully.'));
43
44                                                 L.ui.dialog(title, output, { style: 'close' });
45
46                                                 if (name)
47                                                         $('#package_url').val('');
48                                         });
49                                 });
50                         }
51                 });
52         },
53
54         fetchInstalledList: function()
55         {
56                 var self = this;
57                 return L.opkg.installedPackages(0, 0, '*').then(function(list) {
58                         self.installedList = { };
59                         for (var i = 0; i < list.length; i++)
60                                 self.installedList[list[i][0]] = true;
61                 });
62         },
63
64         fetchPackageList: function(offset, interactive)
65         {
66                 if (interactive)
67                         L.ui.loading(true);
68
69                 if (typeof(offset) == 'undefined')
70                         offset = parseInt($('#package_filter').attr('offset')) || 0;
71
72                 var pattern = $('#package_filter').val() || '';
73                 var action;
74
75                 if (pattern.length)
76                 {
77                         action = $('#package_which').prop('checked') ? L.opkg.installedPackages : L.opkg.findPackages;
78                         pattern = '*' + pattern + '*';
79
80                         $('#package_filter').next().attr('src', L.globals.resource + '/icons/cbi/remove.gif');
81                 }
82                 else
83                 {
84                         action = $('#package_which').prop('checked') ? L.opkg.installedPackages : L.opkg.listPackages;
85                         pattern = '*';
86
87                         $('#package_filter').next().attr('src', L.globals.resource + '/icons/cbi/find.gif');
88                 }
89
90                 $('#package_filter').attr('offset', offset);
91
92                 var install_disabled = $('#package_install').attr('disabled');
93                 var self = this;
94
95                 return action(offset, 100, pattern).then(function(list) {
96                         var packageTable = new L.ui.table({
97                                 placeholder: L.tr('No matching packages found.'),
98                                 columns: [ {
99                                         caption: L.trc('Package table header', 'Package'),
100                                         key:     0
101                                 }, {
102                                         caption: L.trc('Package table header', 'Version'),
103                                         key:     1,
104                                         format:  function(v) {
105                                                 return (v.length > 15 ? v.substring(0, 14) + '…' : v);
106                                         }
107                                 }, {
108                                         caption: L.trc('Package table header', 'Description'),
109                                         key:     2
110                                 }, {
111                                         caption: L.trc('Package table header', 'Installation Status'),
112                                         key:     0,
113                                         width:   '120px',
114                                         format: function(v, n) {
115                                                 var inst = self.installedList[list[n][0]];
116                                                 return $('<button />')
117                                                         .css('width', '100%')
118                                                         .attr('disabled', install_disabled)
119                                                         .attr('name', list[n][0])
120                                                         .attr('installed', inst)
121                                                         .addClass('cbi-button')
122                                                         .addClass(inst ? 'cbi-button-apply' : 'cbi-button-reset')
123                                                         .text(inst ? L.trc('Package state', 'Installed') : L.trc('Package state', 'Not installed'))
124                                                         .click(self.installRemovePackage);
125                                         }
126                                 } ]
127                         });
128
129                         packageTable.rows(list);
130                         packageTable.insertInto('#package_table');
131
132                         if (offset > 0)
133                                 $('#package_prev')
134                                         .attr('offset', offset - 100)
135                                         .attr('disabled', false)
136                                         .val('« %d - %d'.format(offset - 100 + 1, offset));
137                         else
138                                 $('#package_prev')
139                                         .attr('disabled', true)
140                                         .val('« %d - %d'.format(1, Math.min(100, list.total)));
141
142                         if ((offset + 100) < list.total)
143                                 $('#package_next')
144                                         .attr('offset', offset + 100)
145                                         .attr('disabled', false)
146                                         .val('%d - %d »'.format(offset + 100 + 1, Math.min(offset + 200, list.total)));
147                         else
148                                 $('#package_next')
149                                         .attr('disabled', true)
150                                         .val('%d - %d »'.format(list.total - (list.total % 100) + 1, list.total));
151
152                         if (interactive)
153                                 L.ui.loading(false);
154                 }).then(self.updateDiskSpace);
155         },
156
157         execute: function()
158         {
159                 var self = this;
160
161                 $('textarea, input.cbi-button-save').attr('disabled', !this.options.acls.software);
162                 $('#package_update, #package_url, #package_install').attr('disabled', !this.options.acls.software);
163
164                 return $.when(
165                         L.opkg.getConfig().then(function(config) {
166                                 $('textarea')
167                                         .attr('rows', (config.match(/\n/g) || [ ]).length + 1)
168                                         .val(config);
169
170                                 $('input.cbi-button-save')
171                                         .click(function() {
172                                                 var data = ($('textarea').val() || '').replace(/\r/g, '').replace(/\n?$/, '\n');
173                                                 L.ui.loading(true);
174                                                 L.opkg.setConfig(data).then(function() {
175                                                         $('textarea')
176                                                                 .attr('rows', (data.match(/\n/g) || [ ]).length + 1)
177                                                                 .val(data);
178
179                                                         L.ui.loading(false);
180                                                 });
181                                         });
182                         }),
183                         self.fetchInstalledList(),
184                         self.updateDiskSpace()
185                 ).then(function() {
186                         $('#tabs').show().tabs();
187
188                         $('#package_prev, #package_next').click(function(ev) {
189                                 if (!this.getAttribute('disabled'))
190                                 {
191                                         self.fetchPackageList(parseInt(this.getAttribute('offset')), true);
192                                         this.blur();
193                                 }
194                         });
195
196                         $('#package_filter').next().click(function(ev) {
197                                 if (this.getAttribute('src').indexOf('remove.gif') > -1)
198                                         $('#package_filter').val('');
199
200                                 self.fetchPackageList(0, true);
201                         });
202
203                         $('#package_filter').keyup(function(ev) {
204                                 if (ev.which != 13)
205                                         return true;
206
207                                 ev.preventDefault();
208                                 self.fetchPackageList(0, true);
209                                 return false;
210                         });
211
212                         $('#package_which').click(function(ev) {
213                                 this.blur();
214                                 self.fetchPackageList(0, true);
215                         });
216
217                         $('#package_url').keyup(function(ev) {
218                                 if (ev.which != 13)
219                                         return true;
220
221                                 ev.preventDefault();
222
223                                 if (this.value)
224                                         self.installRemovePackage(this.value);
225                         });
226
227                         $('#package_install').click(function(ev) {
228                                 var name = $('#package_url').val();
229                                 if (name)
230                                         self.installRemovePackage(name);
231                         });
232
233                         $('#package_update').click(function(ev) {
234                                 L.ui.dialog(L.tr('Updating package lists'), L.tr('Waiting for package manager …'), { style: 'wait' });
235                                 L.opkg.updateLists().then(function(res) {
236                                         var output = [ ];
237
238                                         if (res.stdout)
239                                                 output.push($('<pre />').text(res.stdout));
240
241                                         if (res.stderr)
242                                                 output.push($('<pre />').addClass('alert-message').text(res.stderr));
243
244                                         output.push(res.code ? L.tr('Package manager failed with status %d.').format(res.code) : L.tr('Package manager finished successfully.'));
245
246                                         L.ui.dialog(L.tr('Updating package lists'), output, { style: 'close' });
247                                 });
248                         });
249
250                         return self.fetchPackageList(0);
251                 });
252         }
253 });