PageRenderTime 49ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/static/admin.js

https://github.com/iRail/The-DataTank-GUI
JavaScript | 695 lines | 519 code | 116 blank | 60 comment | 33 complexity | fce2776c732a63e79b2a3783f4071bf7 MD5 | raw file
  1. window.App = (function ($, _, Backbone) {
  2. /*** Basic UI elements ***/
  3. // Extend View as to allow jquery object as elements instead of strings.
  4. window.jQueryView = Backbone.View.extend({
  5. initialize: function() {
  6. this.el = $(this.el);
  7. this.template = $(this.template);
  8. },
  9. });
  10. window.AdminView = jQueryView.extend({
  11. initialize: function() {
  12. // Super
  13. jQueryView.prototype.initialize.call(this);
  14. },
  15. render: function() {
  16. this.el.removeClass('hidden');
  17. },
  18. hide: function() {
  19. this.el.addClass('hidden');
  20. },
  21. });
  22. /*** Index ***/
  23. window.IndexAdminView = AdminView.extend({
  24. el: '#admin-admin',
  25. initialize: function() {
  26. // Super
  27. AdminView.prototype.initialize.call(this);
  28. },
  29. });
  30. /*** Package ***/
  31. window.Package = Backbone.Model.extend({
  32. getPackageUrl: function() {
  33. return window.TDT_URL + '/' + this.get('name') + '/'
  34. },
  35. });
  36. window.PackageCollection = Backbone.Collection.extend({
  37. model: Package,
  38. url: '/TDTInfo/Packages',
  39. parse: function(response) {
  40. return _.map(response.Packages, function(o) {
  41. // Multiply by 1000 because timestamp is in seconds instead of
  42. // microseconds.
  43. return {name: o.package_name, creation_date: new Date(o.timestamp*1000)};
  44. });
  45. },
  46. });
  47. window.Packages = new PackageCollection();
  48. window.PackageRemoveModal = jQueryView.extend({
  49. el: '#admin-package-remove-modal',
  50. initialize: function(params) {
  51. // Super
  52. jQueryView.prototype.initialize.call(this);
  53. var self = this;
  54. //this.package = params.package;
  55. this.resources = Resources.filter(function(resource) {
  56. return resource.get('package') === self.model.get('name');
  57. });
  58. this.el.find('.modal-header h3').html('Removing "' + this.model.get('name') + '"');
  59. this.el.find('.modal-body').html('Are you shure you want to remove this packages with all of its resources?<ul>');
  60. // TODO add list of all resources of package.
  61. //$.tmpl('#admin-package-remove-resources-modal', this.resources).appendTo(
  62. //this.el.find('.modal-body')
  63. //);
  64. // Show modal box
  65. this.el.modal({
  66. backdrop: true,
  67. keyboard: true,
  68. });
  69. },
  70. events: {
  71. 'click #admin-package-remove-remove': 'removePackage',
  72. 'click #admin-package-remove-cancel': 'cancel',
  73. },
  74. removePackage: function() {
  75. console.log('Remove');
  76. Packages.remove(this.model, {silent: true});
  77. },
  78. cancel: function() {
  79. console.log('Cancel remove');
  80. this.el.modal('toggle')
  81. },
  82. });
  83. window.PackageView = jQueryView.extend({
  84. tagName: 'tr',
  85. template: '#admin-package-template',
  86. initialize: function(model) {
  87. console.log('cr pam');
  88. // Super
  89. jQueryView.prototype.initialize.call(this);
  90. //this.removeModalTemplate = $('#admin-package-remove-modal-template');
  91. Packages.bind('add', this.addOne, this);
  92. },
  93. events: {
  94. 'click .admin-packages-remove': 'removePackage',
  95. 'click .admin-packages-name': 'detailPackage',
  96. },
  97. removePackage: function() {
  98. var modal = new PackageRemoveModal({model: this.model});
  99. },
  100. detailPackage: function() {
  101. alert('detail');
  102. },
  103. render: function() {
  104. this.el.html(this.template.tmpl({pkg: this.model}));
  105. return this;
  106. },
  107. });
  108. window.PackageAdminView = AdminView.extend({
  109. el: '#admin-package',
  110. initialize: function() {
  111. // Super
  112. AdminView.prototype.initialize.call(this);
  113. Packages.bind('add', this.addOne, this);
  114. Packages.bind('reset', this.addAll, this);
  115. Packages.bind('all', this.render, this);
  116. //this._packageView = new PackageView();
  117. Packages.fetch({
  118. success: function() {
  119. console.log('Successfully fetched pkgs. (pav)');
  120. },
  121. error: function() {
  122. console.log('Error while fetching pkgs. (pav)');
  123. },
  124. });
  125. },
  126. events: {
  127. "keypress #admin-package-name": "createPackageOnEnter",
  128. 'click #admin-package-save': 'createPackage',
  129. },
  130. validate: function(attr) {
  131. if ($('#admin-package-name').val() == '') {
  132. return 'Name can not be empty.';
  133. }
  134. },
  135. createPackageOnEnter: function(e) {
  136. var text = $('#admin-package-name').val();
  137. if (!text || e.keyCode != 13) return;
  138. this.createPackage();
  139. },
  140. createPackage: function() {
  141. var name = $('#admin-package-name').val();
  142. Packages.create({name: name});
  143. $('#admin-package-name').val('');
  144. },
  145. addOne: function(package) {
  146. var view = new PackageView({model: package});
  147. this.$("#admin-packages").append(view.render().el);
  148. },
  149. addAll: function() {
  150. Packages.each(this.addOne);
  151. },
  152. });
  153. window.PackageDetailsAdminView = AdminView.extend({
  154. el: 'admin-package-details',
  155. initialize: function() {
  156. // Super
  157. AdminView.prototype.initialize.call(this);
  158. },
  159. });
  160. /*** Resources ***/
  161. window.Resource = Backbone.Model.extend({
  162. getResourceUrl: function() {
  163. return window.TDT_URL + '/' + this.get('package') + '/' + this.get('name');
  164. },
  165. });
  166. window.ResourceList = Backbone.Collection.extend({
  167. model: Resource,
  168. url: '/TDTInfo/Resources',
  169. parse: function(response) {
  170. var resources = [];
  171. var packages = _.keys(response);
  172. // Multiply by 1000 because timestamp is in seconds instead of
  173. // microseconds.
  174. _.each(packages, function(package) {
  175. var partialResources = _.keys(response[package]);
  176. _.each(partialResources, function(name) {
  177. var resource = {
  178. name: name,
  179. type: 'CSV',
  180. package: package,
  181. last_modified: new Date(
  182. response[package][name].modification_timestamp * 1000
  183. ),
  184. creation_date: new Date(
  185. response[package][name].creation_timestamp * 1000
  186. ),
  187. }
  188. resources.push(resource);
  189. });
  190. });
  191. return resources;
  192. },
  193. });
  194. window.Resources = new ResourceList();
  195. window.ResourceView = jQueryView.extend({
  196. tagName: 'tr',
  197. template: '#admin-resource-template',
  198. initialize: function(model) {
  199. // super
  200. //this.model = model;
  201. jQueryView.prototype.initialize.call(this);
  202. //Resource.bind('add', this.addOne, this);
  203. },
  204. render: function() {
  205. this.el.html(this.template.tmpl({resource: this.model}));
  206. return this;
  207. },
  208. });
  209. window.ResourceAddLinkModal = jQueryView.extend({
  210. el: '#admin-resource-link',
  211. initialize: function(params) {
  212. // Super
  213. jQueryView.prototype.initialize.call(this);
  214. // Show modal box
  215. this.el.modal({
  216. backdrop: true,
  217. keyboard: true,
  218. });
  219. },
  220. events: {
  221. 'click #admin-resource-link-add': 'add',
  222. 'click #admin-resource-link-cancel': 'cancel',
  223. },
  224. add: function() {
  225. var url = $('#admin-resource-url').attr('value');
  226. console.log('Add link ', url);
  227. $('#admin-upload').addClass('hidden');
  228. $('#admin-resource-file').attr('placeholder', url);
  229. $('#admin-file').removeClass('hidden');
  230. this.el.modal('hide');
  231. },
  232. cancel: function() {
  233. console.log('Cancel remove');
  234. this.el.modal('hide');
  235. },
  236. });
  237. window.ResourceAdminView = AdminView.extend({
  238. el: '#admin-resource',
  239. initialize: function() {
  240. // Super
  241. AdminView.prototype.initialize.call(this);
  242. Resources.bind('add', this.addOne, this);
  243. Resources.bind('reset', this.addAll, this);
  244. Resources.bind('all', this.render, this);
  245. this.name = $('#admin-resource-name');
  246. this.path = $('#admin-resource-path');
  247. this.columns = $('#admin-resource-columns');
  248. this.primaryKey = $('#admin-resource-pk');
  249. this.pkg = $('#admin-resource-pkg');
  250. this.doc = $('#admin-resource-doc');
  251. this.computer = $('#admin-upload-computer');
  252. this.link = $('#admin-upload-link');
  253. this.file = $('#admin-upload-file');
  254. this.selectedFile = $('#admin-file');
  255. // Fill Resources
  256. Resources.fetch({
  257. success: function() {
  258. console.log('Successfully fetched recs. (rav)');
  259. },
  260. error: function() {
  261. console.log('Error while fetching recs. (rav)');
  262. },
  263. });
  264. // Fill Packages for the package select input.
  265. var self = this;
  266. this.pkg.empty();
  267. self.pkg.append('<option>-- Select a package --</option>');
  268. _.each(Packages.models, function(pkg) {
  269. self.pkg.append('<option>' + pkg.get('name') + '</option>');
  270. });
  271. },
  272. events: {
  273. 'click #admin-resource-save': 'createResource',
  274. 'click #admin-upload-computer': 'selectUploadFile',
  275. 'click #admin-upload-link': 'showUploadModal',
  276. 'click #admin-remove-upload': 'removeUpload',
  277. },
  278. validate: function(attr) {
  279. console.log('validate');
  280. },
  281. createResource: function() {
  282. console.log('create resource...');
  283. var self = this;
  284. var name = this.name.val();
  285. var path = this.path.val();
  286. var columns = this.columns.val();
  287. var primaryKey = this.primaryKey.val();
  288. var pkg = this.pkg.val();
  289. var doc = this.doc.val();
  290. $.ajax({
  291. url: window.TDT_URL + '/' + pkg +'/' + name,
  292. contentType: 'application/json',
  293. type: 'PUT',
  294. data: {
  295. resource_type: 'generic',
  296. printmethods: 'json;xml;jsonp',
  297. generic_type: 'CSV',
  298. documentation: doc,
  299. uri: path,
  300. columns: columns,
  301. PK: primaryKey,
  302. },
  303. success: function() {
  304. console.log('Success in creating resource');
  305. self.name.val('');
  306. self.path.val('');
  307. self.columns.val('');
  308. self.primaryKey.val('');
  309. self.pkg.val('');
  310. self.doc.val('');
  311. Resources.fetch({
  312. success: function() {
  313. console.log('Successfully fetched recs. (rav)');
  314. },
  315. error: function() {
  316. console.log('Error while fetching recs. (rav)');
  317. },
  318. });
  319. },
  320. error: function() {
  321. console.log('FAIL');
  322. }
  323. });
  324. },
  325. selectUploadFile: function() {
  326. this.file.select();
  327. },
  328. showUploadModal: function() {
  329. var modal = new ResourceAddLinkModal();
  330. },
  331. removeUpload: function() {
  332. $('#admin-file').addClass('hidden');
  333. $('#admin-resource-file').attr('placeholder', '');
  334. // TODO clear value of admin-upload-file.
  335. $('#admin-upload').removeClass('hidden');
  336. },
  337. addOne: function(resource) {
  338. var view = new ResourceView({model: resource});
  339. this.$("#admin-resources").append(view.render().el);
  340. },
  341. addAll: function() {
  342. Resources.each(this.addOne);
  343. },
  344. });
  345. /*** Profile ***/
  346. window.ProfileAdminView = AdminView.extend({
  347. el: '#admin-profile',
  348. initialize: function() {
  349. // Super
  350. AdminView.prototype.initialize.call(this);
  351. },
  352. });
  353. /*** Login & Logout ***/
  354. window.LoginAdminView = AdminView.extend({
  355. el: "#admin-login",
  356. initialize: function() {
  357. // Super
  358. AdminView.prototype.initialize.call(this);
  359. },
  360. });
  361. window.LogoutAdminView = AdminView.extend({
  362. el: '#admin-logout',
  363. initialize: function() {
  364. // Super
  365. AdminView.prototype.initialize.call(this);
  366. },
  367. });
  368. /*** Workspace ***/
  369. window.Workspace = Backbone.Router.extend({
  370. _index: null,
  371. _packages: null,
  372. _resources: null,
  373. _profile: null,
  374. _login: null,
  375. _logout: null,
  376. _handlePage: null,
  377. _createdPages: [],
  378. _menu: null,
  379. _menuItems: {
  380. 'admin-admin': '#admin-menu-index',
  381. 'admin-package': '#admin-menu-packages',
  382. 'admin-resource': '#admin-menu-resources',
  383. 'admin-profile': '#admin-menu-profile',
  384. 'admin-login': '#admin-menu-login',
  385. 'admin-logout': '#admin-menu-logout',
  386. },
  387. initialize: function() {
  388. this._menu = $('#admin-menu li');
  389. //_.extend(this._menu, $('.secondary-nav li'));
  390. },
  391. activatePage: function(page) {
  392. var self = this;
  393. _.each(this._createdPages, function(p) {
  394. p.hide();
  395. });
  396. page.render();
  397. self.activateMenuItem(page.el.attr('id'));
  398. },
  399. activateMenuItem: function(item) {
  400. console.log('item: ', item);
  401. this._menu.each(function(index) {
  402. $(this).removeClass('active');
  403. });
  404. console.log('Menu: ', item);
  405. $(this._menuItems[item]).addClass('active');
  406. },
  407. routes: {
  408. '': 'index',
  409. 'packages': 'packages',
  410. 'packages/:name': 'packageDetails',
  411. 'resources': 'resources',
  412. 'resources/:name': 'resourceDetails',
  413. 'profile': 'profile',
  414. 'login': 'login',
  415. 'logout': 'logout',
  416. },
  417. // A generic page handler that returns a function that creates a page
  418. // handler for `page` and creates a coresponding view with `view`.
  419. _handlePage: function(context, page, view) {
  420. console.log('page: ' + page);
  421. if (!context[page]) {
  422. context[page] = new view();
  423. this._createdPages.push(context[page]);
  424. }
  425. console.log('page: ' + context[page]);
  426. this.activatePage(context[page]);
  427. },
  428. index: function() {
  429. this._handlePage(this, '_index', IndexAdminView)
  430. },
  431. packages: function() {
  432. this._handlePage(this, '_packages', PackageAdminView)
  433. },
  434. packageDetails: function() {
  435. this._handlePage(this, '_packageDetails', PackageDetailsAdminView)
  436. },
  437. resources: function() {
  438. this._handlePage(this, '_resources', ResourceAdminView)
  439. },
  440. resourceDetails: function() {
  441. this._handlePage(this, '_resourceDetails', ResourcDetailseAdminView)
  442. },
  443. profile: function() {
  444. this._handlePage(this, '_profile', ProfileAdminView)
  445. },
  446. login: function() {
  447. this._handlePage(this, '_login', LoginAdminView)
  448. },
  449. logout: function() {
  450. this._handlePage(this, '_logout', ResourceAdminView)
  451. },
  452. });
  453. /*** Drag & Drop ***/
  454. window.DragAndDrop = jQueryView.extend({
  455. el: 'body',
  456. initialize: function(args) {
  457. // Super
  458. AdminView.prototype.initialize.call(this);
  459. this.workspace = args.workspace;
  460. },
  461. events: {
  462. 'drag': 'dragEnter',
  463. 'dragleave': 'dragLeave',
  464. 'drop': 'drop',
  465. },
  466. dragEnter: function() {
  467. $('#admin-resource-drag').removeClass('hidden');
  468. console.log('drag enter');
  469. },
  470. dragLeave: function() {
  471. $('#admin-resource-drag').addClass('hidden');
  472. console.log('drag leave');
  473. },
  474. drop: function() {
  475. console.log('drop');
  476. },
  477. });
  478. /*** Start ***/
  479. var self = {};
  480. self.start = function() {
  481. var workspace = new Workspace();
  482. var r = Backbone.history.start({
  483. //pushState: true,
  484. root: '/~abe/The-DataTank-GUI/app.php/admin'
  485. });
  486. var drag = new DragAndDrop({workspace: workspace});
  487. };
  488. return self;
  489. });
  490. $(function() {
  491. // Monkey path Date to add a function that returns the name of the month.
  492. Date.prototype.getMonthName = function() {
  493. var months = {
  494. 0: 'January',
  495. 1: 'Febuary',
  496. 2: 'March',
  497. 3: 'April',
  498. 4: 'May',
  499. 5: 'June',
  500. 6: 'Julu',
  501. 8: 'August',
  502. 9: 'September',
  503. 10: 'October',
  504. 11: 'December',
  505. };
  506. return months[this.getMonth()];
  507. };
  508. // Monkey path Backbone.sync to make it work with the sucky backend api.
  509. Backbone.sync = function(method, model, options) {
  510. // Helper function to get a URL from a Model or Collection as a property
  511. // or as a function.
  512. var getUrl = function(object) {
  513. if (!(object && object.url)) return null;
  514. return _.isFunction(object.url) ? object.url() : object.url;
  515. };
  516. // Throw an error when a URL is needed, and none is supplied.
  517. var urlError = function() {
  518. throw new Error('A "url" property or function must be specified');
  519. };
  520. var methodMap = {
  521. 'create': 'POST',
  522. 'update': 'PUT',
  523. 'delete': 'DELETE',
  524. 'read' : 'GET'
  525. };
  526. var type = methodMap[method];
  527. // Default JSON-request options.
  528. var params = _.extend({
  529. type: type,
  530. dataType: 'json',
  531. //beforeSend: function(xhr) {
  532. // xhr.setRequestHeader("Authorization", "Basic " + encodeBase64(':'));
  533. //},
  534. }, options);
  535. // Ensure that we have a URL.
  536. if (!params.url) {
  537. params.url = getUrl(model) || urlError();
  538. }
  539. // Ensure that we have the appropriate request data.
  540. if (!params.data && model && (method == 'create' || method == 'update')) {
  541. params.contentType = 'application/json';
  542. params.data = JSON.stringify(model.toJSON());
  543. }
  544. // Don't process data on a non-GET request.
  545. if (params.type !== 'GET' && !Backbone.emulateJSON) {
  546. params.processData = false;
  547. }
  548. // Use a different url and method for Packages.
  549. if (model instanceof Package) {
  550. if (method === 'create') {
  551. params.url = model.getPackageUrl();
  552. params.type = 'PUT';
  553. } else if (method === 'update') {
  554. params.url = model.getPackageUrl();
  555. params.type = 'POST';
  556. } else if (method === 'delete') {
  557. console.log('==========================================================>Sync: delete pkg');
  558. params.url = window.TDT_URL + '/' + params.model.get('name');
  559. params.type = 'DELETE';
  560. }
  561. }
  562. // Use a different url and method for Resources.
  563. if (model instanceof Resource) {
  564. if (method === 'create') {
  565. params.url = model.getResourceUrl();
  566. params.type = 'PUT';
  567. } else if (method === 'update') {
  568. params.url = model.getResourceUrl();
  569. params.type = 'POST';
  570. } else if (method === 'delete') {
  571. params.url = model.getResourceUrl();
  572. params.type = 'DELETE';
  573. }
  574. }
  575. // Make the request.
  576. return $.ajax(params);
  577. };
  578. new App(jQuery, _, Backbone).start();
  579. });