Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- const DEBUG_MODE = false;
- const DEFAULT_SCHEMA = {
- /**
- * Flags for disable main save/delete buttons
- */
- $editable: true,
- $deletable: true,
- /**
- * Default callback for save/edit your ngResource instance
- *
- * Required fields on resource:
- * - $isNew
- * - $$post()
- * - $$patch()
- *
- * It will search all formly fields with 'templateOptions.data.file',
- * upload all images, patch images fields on copy with uploaded images ids
- * and run default $$post/$$patch action on resource copy
- */
- saveCallback: function (copy, schema) {
- const methodName = copy.$isNew ? '$$post' : '$$patch';
- const fileFields = _.filter(schema.fields, 'templateOptions.data.file');
- const uploaders = _.map(fileFields, 'templateOptions.data');
- const uploads = _.map(uploaders, u => u.upload());
- const promise = this.$q.all(uploads);
- return promise
- .then(patches => {
- _.map(patches, patch => _.assign(copy, patch));
- return copy[methodName]();
- })
- .catch(err => {
- console.error(err);
- throw new Error('Uploading failed');
- });
- },
- /**
- * Default callback for delete your ngResource instance
- *
- * Required fields on resource:
- * - $$delete()
- */
- deleteCallback: function (copy) {
- return copy.$$delete();
- }
- };
- const DEFAULT_CONFIG = {
- onCreated: angular.noop,
- onPatched: angular.noop,
- onDeleted: angular.noop
- };
- export default class FormCtrl {
- // @ngInject
- constructor ($scope, $q, debug) {
- this.$q = $q;
- this.$scope = $scope;
- this.log = debug('ct:form');
- }
- $onInit () {
- /**
- * Enabled from component bindings:
- * - this.model
- * - this.config
- */
- _.defaults(this.config, DEFAULT_CONFIG);
- /**
- * Copy of main component model
- * Will be changed on model changes
- */
- this.edited = null;
- /**
- * Current schema for model
- * - fields
- * - $editable
- * - $deletable
- * - saveCallback(nv, ov)
- * - deleteCallback(nv, ov)
- * Will be changed on model changes
- */
- this.schema = null;
- /**
- * Main model watcher
- */
- this.$scope.$watch(
- () => this.model,
- this._onChange.bind(this)
- );
- /**
- * Only handling when selected post will drop self `$place`
- * TODO: refactor with storage for handle this fucking update
- */
- this.$scope.$watch(
- () => _.get(this, 'model.$place'),
- (nv, ov) => {
- if (_.isUndefined(nv) && _.isString(ov)) {
- this._onChange(this.model, this.edited);
- }
- }
- );
- }
- hasDiff () {
- let hasDiff = false;
- const marker = 'templateOptions.data.$nonField';
- const fields = _.filter(this.schema.fields, f => !_.get(f, marker));
- DEBUG_MODE && this.log('DIFF START:');
- _.forEach(fields, f => {
- const real = _.get(this.model, f.key);
- const copy = _.invoke(f, 'value');
- if (_.isUndefined(copy)) return;
- if (copy === real) return;
- hasDiff = true;
- DEBUG_MODE && this.log(f.key, real, copy);
- });
- DEBUG_MODE && this.log('DIFF END:');
- return hasDiff;
- }
- isSchemaValid () {
- const model = this.edited;
- const simpleControls = _.map(this._getSimpleFields(), 'formControl');
- const simpleAreValid = _.every(simpleControls, c => _.get(c, '$valid'));
- const colorsControls = _.map(this._getColorsFields(), 'formControl[0]');
- const colorsAreValid = _.every(colorsControls, c => _.get(c, '$valid'));
- const imagesFields = this._getImagesFields();
- const imagesAreValid = _.every(imagesFields, f => {
- const to = f.templateOptions;
- const required = to.required;
- const file = to.data.file;
- const val = model[f.key];
- if (!required) return true;
- return val || file;
- });
- DEBUG_MODE && this.log('Props, images, colors:', [simpleAreValid, imagesAreValid, colorsAreValid]);
- return _.every([
- simpleAreValid,
- imagesAreValid,
- colorsAreValid
- ]);
- }
- resetEdited () {
- this.edited = angular.copy(this.model);
- }
- saveEdited () {
- const copy = this.edited;
- const schema = this.schema;
- const callbackName = copy.$isNew ? 'onCreated' : 'onPatched';
- schema
- .saveCallback.apply(this, [copy, schema])
- .then(() => {
- this.config[callbackName](copy);
- });
- }
- deleteEdited () {
- const copy = this.edited;
- const model = this.model;
- const schema = this.schema;
- schema
- .deleteCallback.apply(this, [copy, schema])
- .then(() => this.config.onDeleted(model));
- }
- _onChange (newModel, oldModel) {
- if (!_.isObject(newModel)) {
- this.edited = null;
- this.schema = null;
- } else {
- this.edited = angular.copy(newModel);
- this.schema = this.config.onChange(newModel, oldModel);
- _.defaults(this.schema, DEFAULT_SCHEMA);
- }
- }
- _getSimpleFields () {
- const simpleTypes = [
- 'ct-boolean',
- 'ct-date',
- 'ct-string',
- 'ct-switch',
- 'ct-text',
- 'ct-number',
- 'ct-select-number',
- 'ct-select-string'
- ];
- const filtered = _.filter(this.schema.fields, (field) => {
- const {type} = field;
- const isSimple = simpleTypes.indexOf(type) !== -1;
- // const isPresent = _.isFunction(field.value);
- const isPresent = !field.hide;
- return _.every([isSimple, isPresent]);
- });
- DEBUG_MODE && this.log('Executed fields:', _.map(filtered, 'key'), filtered);
- return filtered;
- }
- _getImagesFields () {
- const imageTypes = ['ct-image'];
- return _.filter(this.schema.fields, ({type}) => {
- return imageTypes.indexOf(type) !== -1;
- });
- }
- _getColorsFields () {
- const imageTypes = ['ct-color'];
- return _.filter(this.schema.fields, ({type}) => {
- return imageTypes.indexOf(type) !== -1;
- });
- }
- }
- /**
- * TODO: implement via `$onChanges` component life-cycle hooks
- *
- * $onChanges ({model}) {
- *
- * // API:
- * const {currentValue: nv, previousValue: ov} = model;
- * model.isFirstChange();
- *
- * // FIRE:
- * this._onChange(nv, ov);
- *
- * }
- */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement