vines-services 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,404 @@
1
+ var ServicesPage;
2
+ var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
3
+ ServicesPage = (function() {
4
+ var ATTRS, MEMBERS, SERVICES, SYSTEMS, USERS;
5
+ SERVICES = 'http://getvines.com/protocol/services';
6
+ MEMBERS = 'http://getvines.com/protocol/services/members';
7
+ SYSTEMS = 'http://getvines.com/protocol/systems';
8
+ ATTRS = 'http://getvines.com/protocol/systems/attributes';
9
+ USERS = 'http://getvines.com/protocol/users';
10
+ function ServicesPage(session) {
11
+ this.session = session;
12
+ this.api = new Api(this.session);
13
+ this.selectedService = null;
14
+ this.validateTimeout = null;
15
+ this.layout = null;
16
+ this.users = [];
17
+ }
18
+ ServicesPage.prototype.deleteService = function(event) {
19
+ var selected;
20
+ this.drawBlankSlate();
21
+ this.toggleForm('#remove-contact-form');
22
+ selected = $("#services li[data-id='" + this.selectedService.id + "']");
23
+ this.api.remove(SERVICES, this.selectedService.id, __bind(function(result) {
24
+ return selected.fadeOut(200, function() {
25
+ selected.remove();
26
+ return this.selectedService = null;
27
+ });
28
+ }, this));
29
+ return false;
30
+ };
31
+ ServicesPage.prototype.icon = function(member) {
32
+ var icon, icons;
33
+ icons = {
34
+ darwin: 'mac.png',
35
+ linux: 'linux.png',
36
+ windows: 'windows.png'
37
+ };
38
+ icon = icons[member.os] || 'run.png';
39
+ return "images/" + icon;
40
+ };
41
+ ServicesPage.prototype.drawMember = function(member) {
42
+ var node;
43
+ if (!this.editorVisible()) {
44
+ return;
45
+ }
46
+ node = $("<li>\n <span class=\"icon\"><img src=\"" + (this.icon(member)) + "\"/></span>\n <span class=\"text\"></span>\n</li>").appendTo('#members');
47
+ return $('.text', node).text(member.name);
48
+ };
49
+ ServicesPage.prototype.operators = function() {
50
+ var node, operator, _i, _len, _ref, _results;
51
+ _ref = ['like', 'not like', 'starts with', 'ends with', 'is', 'is not', '>', '>=', '<', '<=', 'and', 'or'];
52
+ _results = [];
53
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
54
+ operator = _ref[_i];
55
+ node = $("<li data-selector=\"" + operator + "\">\n " + operator + "\n</li>").appendTo('#operators');
56
+ _results.push(node.click(__bind(function(event) {
57
+ var name;
58
+ $('#syntax').focus();
59
+ name = $(event.currentTarget).attr('data-selector');
60
+ $('#syntax').val($('#syntax').val() + (" " + name + " "));
61
+ return this.validateIn();
62
+ }, this)));
63
+ }
64
+ return _results;
65
+ };
66
+ ServicesPage.prototype.selectService = function(node) {
67
+ var id, name;
68
+ id = $(node).attr('data-id');
69
+ name = $(node).attr('data-name');
70
+ $('#services li').removeClass('selected');
71
+ $(node).addClass('selected');
72
+ $('#remove-service-msg').html("Are you sure you want to remove the " + ("<strong>" + name + "</strong> service?"));
73
+ $('#remove-service-form .buttons').fadeIn(200);
74
+ return this.api.get(SERVICES, {
75
+ id: id
76
+ }, __bind(function(result) {
77
+ this.selectedService = result;
78
+ return this.drawEditor(result);
79
+ }, this));
80
+ };
81
+ ServicesPage.prototype.serviceNode = function(service) {
82
+ var label, node;
83
+ label = service.size === 1 ? 'system' : 'systems';
84
+ node = $("<li data-id=\"" + service.id + "\" data-name=\"\" data-size=\"" + service.size + "\">\n <span class=\"text\">" + service.name + "</span>\n <span class=\"count\">" + service.size + " " + label + "</span>\n</li>").appendTo('#services');
85
+ node.attr('data-name', service.name);
86
+ $('.text', node).text(service.name);
87
+ node.click(__bind(function(event) {
88
+ return this.selectService(event.currentTarget);
89
+ }, this));
90
+ return node;
91
+ };
92
+ ServicesPage.prototype.findServices = function() {
93
+ return this.api.get(SERVICES, {}, __bind(function(result) {
94
+ var row, _i, _len, _ref, _results;
95
+ _ref = result.rows;
96
+ _results = [];
97
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
98
+ row = _ref[_i];
99
+ _results.push(this.serviceNode(row));
100
+ }
101
+ return _results;
102
+ }, this));
103
+ };
104
+ ServicesPage.prototype.findMembers = function(id) {
105
+ return this.api.get(MEMBERS, {
106
+ id: id
107
+ }, __bind(function(result) {
108
+ var row, _i, _len, _ref, _results;
109
+ _ref = result.rows;
110
+ _results = [];
111
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
112
+ row = _ref[_i];
113
+ _results.push(this.drawMember(row));
114
+ }
115
+ return _results;
116
+ }, this));
117
+ };
118
+ ServicesPage.prototype.findUsers = function(syntax) {
119
+ return this.api.get(USERS, {}, __bind(function(result) {
120
+ var row;
121
+ this.users = (function() {
122
+ var _i, _len, _ref, _results;
123
+ _ref = result.rows;
124
+ _results = [];
125
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
126
+ row = _ref[_i];
127
+ if (!row.system) {
128
+ _results.push(row);
129
+ }
130
+ }
131
+ return _results;
132
+ })();
133
+ return this.drawUsers();
134
+ }, this));
135
+ };
136
+ ServicesPage.prototype.attributeNode = function(attribute) {
137
+ var node;
138
+ node = $('<li data-name=""></li>').appendTo('#attributes');
139
+ node.text(attribute);
140
+ node.attr('data-name', attribute);
141
+ return node.click(__bind(function(event) {
142
+ var name;
143
+ $('#syntax').focus();
144
+ name = $(event.currentTarget).attr('data-name');
145
+ $('#syntax').val($('#syntax').val() + (" " + name + " "));
146
+ return this.validateIn();
147
+ }, this));
148
+ };
149
+ ServicesPage.prototype.findAttributes = function(syntax) {
150
+ return this.api.get(ATTRS, {}, __bind(function(result) {
151
+ var row, _i, _len, _ref, _results;
152
+ _ref = result.rows;
153
+ _results = [];
154
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
155
+ row = _ref[_i];
156
+ _results.push(this.attributeNode(row));
157
+ }
158
+ return _results;
159
+ }, this));
160
+ };
161
+ ServicesPage.prototype.validateIn = function(millis) {
162
+ clearTimeout(this.validateTimeout);
163
+ return this.validateTimeout = setTimeout((__bind(function() {
164
+ return this.validate();
165
+ }, this)), millis || 500);
166
+ };
167
+ ServicesPage.prototype.validate = function() {
168
+ var code, prev;
169
+ $('#syntax-status').text('');
170
+ prev = $('#syntax').data('prev');
171
+ code = $.trim($('#syntax').val());
172
+ $('#syntax').data('prev', code);
173
+ if (!(code && code !== prev)) {
174
+ return;
175
+ }
176
+ $('#syntax-status').text('Searching . . .');
177
+ $('#members').empty();
178
+ return this.api.get2(MEMBERS, code, __bind(function(result) {
179
+ var row, _i, _len, _ref, _results;
180
+ if (result.ok) {
181
+ $('#syntax-status').text('');
182
+ _ref = result.rows;
183
+ _results = [];
184
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
185
+ row = _ref[_i];
186
+ _results.push(this.drawMember(row));
187
+ }
188
+ return _results;
189
+ } else {
190
+ return $('#syntax-status').text(result.error);
191
+ }
192
+ }, this));
193
+ };
194
+ ServicesPage.prototype.validateForm = function() {
195
+ var name, valid;
196
+ $('#name-error').empty();
197
+ valid = true;
198
+ name = $.trim($('#name').val());
199
+ if (name === '') {
200
+ $('#name-error').text('Name is required.');
201
+ valid = false;
202
+ }
203
+ return valid;
204
+ };
205
+ ServicesPage.prototype.save = function() {
206
+ var accounts, service, u, users;
207
+ if (!this.validateForm()) {
208
+ return;
209
+ }
210
+ users = $('#users :checked').map(function() {
211
+ return $(this).val();
212
+ }).get();
213
+ accounts = $('#unix-users').val().split(',');
214
+ accounts = (function() {
215
+ var _i, _len, _results;
216
+ _results = [];
217
+ for (_i = 0, _len = accounts.length; _i < _len; _i++) {
218
+ u = accounts[_i];
219
+ if ($.trim(u).length > 0) {
220
+ _results.push($.trim(u));
221
+ }
222
+ }
223
+ return _results;
224
+ })();
225
+ service = {
226
+ name: $('#name').val(),
227
+ code: $('#syntax').val(),
228
+ accounts: accounts,
229
+ users: users
230
+ };
231
+ if ($('#id').val().length > 0) {
232
+ service['id'] = $('#id').val();
233
+ }
234
+ this.api.save(SERVICES, service, __bind(function(result) {
235
+ var node;
236
+ new Notification('Service saved successfully');
237
+ result.size = $('#members').length;
238
+ $('#id').val(result.id);
239
+ node = $("#services li[data-id='" + result.id + "']");
240
+ if (node.length === 0) {
241
+ node = this.serviceNode(result);
242
+ return this.selectService(node);
243
+ } else {
244
+ return $('.text', node).text(result.name);
245
+ }
246
+ }, this));
247
+ return false;
248
+ };
249
+ ServicesPage.prototype.drawBlankSlate = function() {
250
+ $('#beta').empty();
251
+ $("<form id=\"blank-slate\">\n <p>\n Services are dynamically updated groups of systems based on\n criteria you define. Send a command to the service and it runs\n on every system in the group.\n </p>\n <input type=\"submit\" id=\"blank-slate-add\" value=\"Add Service\"/>\n</form>").appendTo('#beta');
252
+ if (!this.api.user.permissions.services) {
253
+ $('#blank-slate-add').remove();
254
+ }
255
+ return $('#blank-slate').submit(__bind(function() {
256
+ this.drawEditor();
257
+ return false;
258
+ }, this));
259
+ };
260
+ ServicesPage.prototype.draw = function() {
261
+ var fn;
262
+ if (!this.session.connected()) {
263
+ window.location.hash = '';
264
+ return;
265
+ }
266
+ $('body').attr('id', 'services-page');
267
+ $('#container').hide().empty();
268
+ $("<div id=\"alpha\" class=\"sidebar column y-fill\">\n <h2>Services <div id=\"search-services-icon\"></div></h2>\n <div id=\"search-services-form\"></div>\n <ul id=\"services\" class=\"selectable scroll y-fill\"></ul>\n <div id=\"alpha-controls\" class=\"controls\">\n <div id=\"add-service\"></div>\n <div id=\"remove-service\"></div>\n </div>\n <form id=\"remove-service-form\" class=\"overlay\" style=\"display:none;\">\n <h2>Remove Service</h2>\n <p id=\"remove-service-msg\">Select a service in the list above to remove.</p>\n <fieldset class=\"buttons\" style=\"display:none;\">\n <input id=\"remove-service-cancel\" type=\"button\" value=\"Cancel\"/>\n <input id=\"remove-service-ok\" type=\"submit\" value=\"Remove\"/>\n </fieldset>\n </form>\n</div>\n<div id=\"beta\" class=\"primary column x-fill y-fill\"></div>\n<div id=\"charlie\" class=\"sidebar column y-fill\">\n <h2>Operators</h2>\n <ul id=\"operators\"></ul>\n <h2>Attributes <div id=\"search-attributes-icon\"></div></h2>\n <div id=\"search-attributes-form\"></div>\n <ul id=\"attributes\" class=\"y-fill scroll\"></ul>\n</div>").appendTo('#container');
269
+ new Button('#add-service', ICONS.plus);
270
+ new Button('#remove-service', ICONS.minus);
271
+ if (!this.api.user.permissions.services) {
272
+ $('#alpha-controls div').remove();
273
+ }
274
+ this.drawBlankSlate();
275
+ $('#add-service').click(__bind(function() {
276
+ return this.drawEditor();
277
+ }, this));
278
+ $('#remove-service').click(__bind(function() {
279
+ return this.toggleForm('#remove-service-form');
280
+ }, this));
281
+ $('#remove-service-cancel').click(__bind(function() {
282
+ return this.toggleForm('#remove-service-form');
283
+ }, this));
284
+ $('#remove-service-form').submit(__bind(function() {
285
+ return this.deleteService();
286
+ }, this));
287
+ this.operators();
288
+ this.findServices();
289
+ this.findAttributes();
290
+ this.findUsers();
291
+ $('#container').show();
292
+ this.layout = this.resize();
293
+ fn = __bind(function() {
294
+ this.layout.resize();
295
+ return this.layout.resize();
296
+ }, this);
297
+ new Filter({
298
+ list: '#services',
299
+ icon: '#search-services-icon',
300
+ form: '#search-services-form',
301
+ attrs: ['data-name'],
302
+ open: fn,
303
+ close: fn
304
+ });
305
+ return new Filter({
306
+ list: '#attributes',
307
+ icon: '#search-attributes-icon',
308
+ form: '#search-attributes-form',
309
+ attrs: ['data-name'],
310
+ open: fn,
311
+ close: fn
312
+ });
313
+ };
314
+ ServicesPage.prototype.drawEditor = function(service) {
315
+ if (!this.pageVisible()) {
316
+ return;
317
+ }
318
+ if (!service) {
319
+ this.selectedService = null;
320
+ $('#services li').removeClass('selected');
321
+ }
322
+ $('#beta').empty();
323
+ $("<form id=\"editor-form\" class=\"sections y-fill scroll\">\n <input id=\"id\" type=\"hidden\"/>\n <div>\n <section>\n <h2>Service</h2>\n <fieldset>\n <label for=\"name\">Name</label>\n <input id=\"name\" type=\"text\"/>\n <p id=\"name-error\" class=\"error\"></p>\n <label for=\"syntax\">Criteria</label>\n <textarea id=\"syntax\" placeholder=\"fqdn starts with 'www.' and platform is 'mac_os_x'\"></textarea>\n <p id=\"syntax-status\"></p>\n </fieldset>\n </section>\n <section>\n <h2>Members</h2>\n <fieldset id=\"service-preview\">\n <ul id=\"members\" class=\"scroll\"></ul>\n </fieldset>\n </section>\n <section>\n <h2>Permissions</h2>\n <fieldset>\n <label>Users</label>\n <ul id=\"users\" class=\"scroll\"></ul>\n <label for=\"unix-users\">Unix Accounts</label>\n <input id=\"unix-users\" type=\"text\"/>\n </fieldset>\n </section>\n </div>\n</form>\n<form id=\"editor-buttons\">\n <input id=\"save\" type=\"submit\" value=\"Save\"/>\n</form>").appendTo('#beta');
324
+ if (service) {
325
+ this.findMembers(service.id);
326
+ $('#id').val(service.id);
327
+ $('#name').val(service.name);
328
+ $('#syntax').val(service.code);
329
+ $('#unix-users').val(service.accounts.join(', '));
330
+ }
331
+ if (this.users.length > 0) {
332
+ this.drawUsers();
333
+ }
334
+ this.layout.resize();
335
+ $('#name').focus();
336
+ $('#syntax').change(__bind(function() {
337
+ return this.validateIn();
338
+ }, this));
339
+ $('#syntax').keyup(__bind(function() {
340
+ return this.validateIn();
341
+ }, this));
342
+ $('#editor-form').submit(__bind(function() {
343
+ return this.save();
344
+ }, this));
345
+ return $('#editor-buttons').submit(__bind(function() {
346
+ return this.save();
347
+ }, this));
348
+ };
349
+ ServicesPage.prototype.drawUsers = function() {
350
+ var node, user, _i, _len, _ref;
351
+ if (!this.editorVisible()) {
352
+ return;
353
+ }
354
+ $('#users').empty();
355
+ _ref = this.users;
356
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
357
+ user = _ref[_i];
358
+ node = $("<li>\n <input id='user-" + user.jid + "' type='checkbox' value='" + user.jid + "'/>\n <label for='user-" + user.jid + "'>" + user.jid + "</label>\n</li>").appendTo('#users');
359
+ if (user.jid === this.session.bareJid()) {
360
+ $('input', node).prop('checked', true);
361
+ }
362
+ }
363
+ if (this.selectedService) {
364
+ return $('#users input[type="checkbox"]').val(this.selectedService.users);
365
+ }
366
+ };
367
+ ServicesPage.prototype.toggleForm = function(form, fn) {
368
+ form = $(form);
369
+ $('form.overlay').each(function() {
370
+ if (this.id !== form.attr('id')) {
371
+ return $(this).hide();
372
+ }
373
+ });
374
+ if (form.is(':hidden')) {
375
+ if (fn) {
376
+ fn();
377
+ }
378
+ return form.fadeIn(100);
379
+ } else {
380
+ return form.fadeOut(100, function() {
381
+ form[0].reset();
382
+ if (fn) {
383
+ return fn();
384
+ }
385
+ });
386
+ }
387
+ };
388
+ ServicesPage.prototype.pageVisible = function() {
389
+ return $('#services-page').length > 0;
390
+ };
391
+ ServicesPage.prototype.editorVisible = function() {
392
+ return $('#services-page #editor-form').length > 0;
393
+ };
394
+ ServicesPage.prototype.resize = function() {
395
+ var a, b, c;
396
+ a = $('#alpha');
397
+ b = $('#beta');
398
+ c = $('#charlie');
399
+ return new Layout(function() {
400
+ return c.css('left', a.width() + b.width());
401
+ });
402
+ };
403
+ return ServicesPage;
404
+ })();