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