Advertisement
Guest User

Untitled

a guest
Oct 22nd, 2016
51
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.58 KB | None | 0 0
  1. const DEBUG_MODE = false;
  2.  
  3. const DEFAULT_SCHEMA = {
  4. /**
  5. * Flags for disable main save/delete buttons
  6. */
  7. $editable: true,
  8. $deletable: true,
  9. /**
  10. * Default callback for save/edit your ngResource instance
  11. *
  12. * Required fields on resource:
  13. * - $isNew
  14. * - $$post()
  15. * - $$patch()
  16. *
  17. * It will search all formly fields with 'templateOptions.data.file',
  18. * upload all images, patch images fields on copy with uploaded images ids
  19. * and run default $$post/$$patch action on resource copy
  20. */
  21. saveCallback: function (copy, schema) {
  22. const methodName = copy.$isNew ? '$$post' : '$$patch';
  23. const fileFields = _.filter(schema.fields, 'templateOptions.data.file');
  24. const uploaders = _.map(fileFields, 'templateOptions.data');
  25. const uploads = _.map(uploaders, u => u.upload());
  26. const promise = this.$q.all(uploads);
  27. return promise
  28. .then(patches => {
  29. _.map(patches, patch => _.assign(copy, patch));
  30. return copy[methodName]();
  31. })
  32. .catch(err => {
  33. console.error(err);
  34. throw new Error('Uploading failed');
  35. });
  36. },
  37. /**
  38. * Default callback for delete your ngResource instance
  39. *
  40. * Required fields on resource:
  41. * - $$delete()
  42. */
  43. deleteCallback: function (copy) {
  44. return copy.$$delete();
  45. }
  46. };
  47.  
  48. const DEFAULT_CONFIG = {
  49. onCreated: angular.noop,
  50. onPatched: angular.noop,
  51. onDeleted: angular.noop
  52. };
  53.  
  54. export default class FormCtrl {
  55.  
  56. // @ngInject
  57. constructor ($scope, $q, debug) {
  58. this.$q = $q;
  59. this.$scope = $scope;
  60. this.log = debug('ct:form');
  61. }
  62.  
  63. $onInit () {
  64.  
  65. /**
  66. * Enabled from component bindings:
  67. * - this.model
  68. * - this.config
  69. */
  70. _.defaults(this.config, DEFAULT_CONFIG);
  71.  
  72. /**
  73. * Copy of main component model
  74. * Will be changed on model changes
  75. */
  76. this.edited = null;
  77.  
  78. /**
  79. * Current schema for model
  80. * - fields
  81. * - $editable
  82. * - $deletable
  83. * - saveCallback(nv, ov)
  84. * - deleteCallback(nv, ov)
  85. * Will be changed on model changes
  86. */
  87. this.schema = null;
  88.  
  89.  
  90. /**
  91. * Main model watcher
  92. */
  93. this.$scope.$watch(
  94. () => this.model,
  95. this._onChange.bind(this)
  96. );
  97.  
  98. /**
  99. * Only handling when selected post will drop self `$place`
  100. * TODO: refactor with storage for handle this fucking update
  101. */
  102. this.$scope.$watch(
  103. () => _.get(this, 'model.$place'),
  104. (nv, ov) => {
  105. if (_.isUndefined(nv) && _.isString(ov)) {
  106. this._onChange(this.model, this.edited);
  107. }
  108. }
  109. );
  110.  
  111. }
  112.  
  113. hasDiff () {
  114. let hasDiff = false;
  115. const marker = 'templateOptions.data.$nonField';
  116. const fields = _.filter(this.schema.fields, f => !_.get(f, marker));
  117. DEBUG_MODE && this.log('DIFF START:');
  118. _.forEach(fields, f => {
  119. const real = _.get(this.model, f.key);
  120. const copy = _.invoke(f, 'value');
  121. if (_.isUndefined(copy)) return;
  122. if (copy === real) return;
  123. hasDiff = true;
  124. DEBUG_MODE && this.log(f.key, real, copy);
  125. });
  126. DEBUG_MODE && this.log('DIFF END:');
  127. return hasDiff;
  128. }
  129.  
  130. isSchemaValid () {
  131. const model = this.edited;
  132. const simpleControls = _.map(this._getSimpleFields(), 'formControl');
  133. const simpleAreValid = _.every(simpleControls, c => _.get(c, '$valid'));
  134. const colorsControls = _.map(this._getColorsFields(), 'formControl[0]');
  135. const colorsAreValid = _.every(colorsControls, c => _.get(c, '$valid'));
  136. const imagesFields = this._getImagesFields();
  137. const imagesAreValid = _.every(imagesFields, f => {
  138. const to = f.templateOptions;
  139. const required = to.required;
  140. const file = to.data.file;
  141. const val = model[f.key];
  142. if (!required) return true;
  143. return val || file;
  144. });
  145. DEBUG_MODE && this.log('Props, images, colors:', [simpleAreValid, imagesAreValid, colorsAreValid]);
  146. return _.every([
  147. simpleAreValid,
  148. imagesAreValid,
  149. colorsAreValid
  150. ]);
  151. }
  152.  
  153. resetEdited () {
  154. this.edited = angular.copy(this.model);
  155. }
  156.  
  157. saveEdited () {
  158. const copy = this.edited;
  159. const schema = this.schema;
  160. const callbackName = copy.$isNew ? 'onCreated' : 'onPatched';
  161. schema
  162. .saveCallback.apply(this, [copy, schema])
  163. .then(() => {
  164. this.config[callbackName](copy);
  165. });
  166. }
  167.  
  168. deleteEdited () {
  169. const copy = this.edited;
  170. const model = this.model;
  171. const schema = this.schema;
  172. schema
  173. .deleteCallback.apply(this, [copy, schema])
  174. .then(() => this.config.onDeleted(model));
  175. }
  176.  
  177. _onChange (newModel, oldModel) {
  178. if (!_.isObject(newModel)) {
  179. this.edited = null;
  180. this.schema = null;
  181. } else {
  182. this.edited = angular.copy(newModel);
  183. this.schema = this.config.onChange(newModel, oldModel);
  184. _.defaults(this.schema, DEFAULT_SCHEMA);
  185. }
  186. }
  187.  
  188. _getSimpleFields () {
  189. const simpleTypes = [
  190. 'ct-boolean',
  191. 'ct-date',
  192. 'ct-string',
  193. 'ct-switch',
  194. 'ct-text',
  195. 'ct-number',
  196. 'ct-select-number',
  197. 'ct-select-string'
  198. ];
  199. const filtered = _.filter(this.schema.fields, (field) => {
  200. const {type} = field;
  201. const isSimple = simpleTypes.indexOf(type) !== -1;
  202. // const isPresent = _.isFunction(field.value);
  203. const isPresent = !field.hide;
  204. return _.every([isSimple, isPresent]);
  205. });
  206. DEBUG_MODE && this.log('Executed fields:', _.map(filtered, 'key'), filtered);
  207. return filtered;
  208. }
  209.  
  210. _getImagesFields () {
  211. const imageTypes = ['ct-image'];
  212. return _.filter(this.schema.fields, ({type}) => {
  213. return imageTypes.indexOf(type) !== -1;
  214. });
  215. }
  216.  
  217. _getColorsFields () {
  218. const imageTypes = ['ct-color'];
  219. return _.filter(this.schema.fields, ({type}) => {
  220. return imageTypes.indexOf(type) !== -1;
  221. });
  222. }
  223.  
  224. }
  225.  
  226. /**
  227. * TODO: implement via `$onChanges` component life-cycle hooks
  228. *
  229. * $onChanges ({model}) {
  230. *
  231. * // API:
  232. * const {currentValue: nv, previousValue: ov} = model;
  233. * model.isFirstChange();
  234. *
  235. * // FIRE:
  236. * this._onChange(nv, ov);
  237. *
  238. * }
  239. */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement