create-collections.ko.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. // Licensed to Cloudera, Inc. under one
  2. // or more contributor license agreements. See the NOTICE file
  3. // distributed with this work for additional information
  4. // regarding copyright ownership. Cloudera, Inc. licenses this file
  5. // to you under the Apache License, Version 2.0 (the
  6. // "License"); you may not use this file except in compliance
  7. // with the License. You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing, software
  12. // distributed under the License is distributed on an "AS IS" BASIS,
  13. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. // See the License for the specific language governing permissions and
  15. // limitations under the License.
  16. // Start Models
  17. var Collection = function(viewModel) {
  18. var self = this;
  19. self.name = ko.observable().extend({'errors': null});
  20. self.fields = ko.observableArray();
  21. self.removeField = function(field) {
  22. self.fields.remove(field);
  23. };
  24. self.addField = function(name, type) {
  25. self.fields.push(new Field(self, name, type));
  26. };
  27. self.newField = function() {
  28. self.addField('', '');
  29. };
  30. self.setData = function(data_json) {
  31. self.data(data_json);
  32. };
  33. };
  34. var Field = function(collection, name, type) {
  35. var self = this;
  36. self.name = ko.observable(name).extend({'errors': null});
  37. self.type = ko.observable(type).extend({'errors': null});
  38. self.remove = function() {
  39. collection.removeField(self);
  40. };
  41. };
  42. // End Models
  43. // Start Wizard
  44. var Page = function(name, url, validate_fn) {
  45. var self = this;
  46. self.name = ko.observable(name);
  47. self.url = ko.observable(url);
  48. self.validate = validate_fn || function() {return true;};
  49. };
  50. var Wizard = function(pages) {
  51. var self = this;
  52. self.pages = ko.observableArray();
  53. $.each(pages, function(index, page) {
  54. self.pages.push(new Page(page.name, page.url, page.validate));
  55. });
  56. self.index = ko.observable(0);
  57. self.hasPrevious = ko.computed(function() {
  58. return self.index() > 0;
  59. });
  60. self.hasNext = ko.computed(function() {
  61. return self.index() + 1 < self.pages().length;
  62. });
  63. self.current = ko.computed(function() {
  64. return self.pages()[self.index()];
  65. });
  66. self.next = function() {
  67. if (self.hasNext() && self.pages()[self.index()].validate()) {
  68. return self.pages()[self.index() + 1];
  69. } else {
  70. return self.pages()[self.index()];
  71. }
  72. };
  73. self.previous = function() {
  74. if (self.hasPrevious()) {
  75. return self.pages()[self.index() - 1];
  76. }
  77. };
  78. self.setIndexByUrl = function(url) {
  79. $.each(self.pages(), function(index, step) {
  80. if (step.url() == url) {
  81. self.index(index);
  82. }
  83. });
  84. };
  85. };
  86. // End Wizard
  87. var CreateCollectionViewModel = function(steps) {
  88. var self = this;
  89. var fieldTypes = [
  90. 'string',
  91. 'integer',
  92. 'float',
  93. 'boolean'
  94. ];
  95. var fieldSeparators = [
  96. ',',
  97. '\t'
  98. ];
  99. // Models
  100. self.fieldTypes = ko.mapping.fromJS(fieldTypes);
  101. self.fieldSeparators = ko.mapping.fromJS(fieldSeparators);
  102. self.collection = new Collection(self);
  103. self.fieldSeparator = ko.observable();
  104. // UI
  105. self.wizard = new Wizard(steps);
  106. self.inferFields = function(data) {
  107. var fields = [];
  108. var field_names = data[0];
  109. var first_row = data[1];
  110. $.each(first_row, function(index, value) {
  111. var type = null;
  112. if ($.isNumeric(value)) {
  113. if (value.toString().indexOf(".") == -1) {
  114. type = 'integer';
  115. } else {
  116. type = 'float';
  117. }
  118. } else {
  119. if (value.toLowerCase().indexOf("true") > -1 || value.toLowerCase().indexOf("false") > -1) {
  120. type = 'boolean';
  121. }
  122. else {
  123. type = 'string';
  124. }
  125. }
  126. fields.push(new Field(self.collection, field_names[index], type));
  127. });
  128. self.collection.fields(fields);
  129. };
  130. self.save = function() {
  131. if (self.wizard.current().validate()) {
  132. return $.post("/search/admin/collections/create", {
  133. collection: ko.toJSON(self.collection),
  134. })
  135. .success(function(data) {
  136. if (data.status == 0) {
  137. $(document).trigger("info", data.message);
  138. } else {
  139. $(document).trigger("error", data.message);
  140. }
  141. })
  142. .fail(function (xhr, textStatus, errorThrown) {
  143. $(document).trigger("error", xhr.responseText);
  144. });
  145. }
  146. };
  147. };
  148. // Start utils
  149. ko.bindingHandlers.routie = {
  150. init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
  151. $(element).click(function() {
  152. var obj = ko.utils.unwrapObservable(valueAccessor());
  153. var url = null;
  154. var bubble = false;
  155. if ($.isPlainObject(obj)) {
  156. url = obj.url;
  157. bubble = !!obj.bubble;
  158. } else {
  159. url = obj;
  160. }
  161. routie(url);
  162. return bubble;
  163. });
  164. }
  165. };
  166. ko.extenders.errors = function(target, options) {
  167. target.errors = ko.observableArray();
  168. return target;
  169. };
  170. qq.CollectionFileUploader = function(o){
  171. // call parent constructor
  172. qq.FileUploader.apply(this, arguments);
  173. this._handler._upload = function(id, params){
  174. var file = this._files[id],
  175. name = this.getName(id),
  176. size = this.getSize(id);
  177. this._loaded[id] = 0;
  178. var xhr = this._xhrs[id] = new XMLHttpRequest();
  179. var self = this;
  180. xhr.upload.onprogress = function(e){
  181. if (e.lengthComputable){
  182. self._loaded[id] = e.loaded;
  183. self._options.onProgress(id, name, e.loaded, e.total);
  184. }
  185. };
  186. xhr.onreadystatechange = function(){
  187. if (xhr.readyState == 4){
  188. self._onComplete(id, xhr);
  189. }
  190. };
  191. var formData = new FormData();
  192. formData.append(params.fileFieldLabel, file);
  193. formData.append('field-separator', params.fieldSeparator);
  194. var action = this._options.action;
  195. xhr.open("POST", action, true);
  196. xhr.send(formData);
  197. };
  198. };
  199. qq.extend(qq.CollectionFileUploader.prototype, qq.FileUploader.prototype);
  200. qq.extend(qq.CollectionFileUploader.prototype, {
  201. _finish: [],
  202. _onInputChange: function(input){
  203. if (this._handler instanceof qq.UploadHandlerXhr) {
  204. this._finish.push(this._uploadFileList.bind(this, input.files));
  205. } else {
  206. if (this._validateFile(input)) {
  207. this._finish.push(this._uploadFile.bind(this, input));
  208. }
  209. }
  210. this._button.reset();
  211. },
  212. finishUpload: function() {
  213. $.each(this._finish, function(index, upload) {
  214. upload();
  215. });
  216. }
  217. });
  218. // End utils