import {module} from '../module'; import Component from '../lib/component'; import getModifiedData from '../lib/modified'; import copyObject from '../lib/copy'; import isEqual from '../lib/equals'; /** * Component that checks for changes on a specific model property and * asks the user to save or discard it when the state changes. * Also it can save the data to the server when the @url and @idField * properties are provided. */ export default class Watcher extends Component { constructor($element, $scope, $state, $transitions, $http, vnAppLogger, $translate) { super($element); this.$scope = $scope; this.$state = $state; this.$http = $http; this.$translate = $translate; this.vnAppLogger = vnAppLogger; this.state = null; this.deregisterCallback = $transitions.onStart({}, (transition) => this.callback(transition)); this.copyData(); } $onInit() { if(this.get) { this.fetchData(); } } $onChanges(changes) { if(this.data) { this.copyData(); } } $onDestroy() { this.deregisterCallback(); } fetchData() { let id = this.data[this.idField]; return new Promise((resolve, reject) => { this.$http.get(`${this.url}/${id}`).then( json => this.writeData(json, resolve), json => reject(json) ); }); } submit() { if(this.form && !this.form.$valid) { return new Promise ( (resolve, reject) => this.invalidForm(reject) ); } if (!this.dataChanged()) { return new Promise ( (resolve, reject) => this.noChanges(reject) ); } let changedData = getModifiedData(this.data, this.orgData); if(this.save) { this.save.model = changedData; return new Promise((resolve, reject) => { this.save.accept().then( json => this.writeData({data: json}, resolve), json => reject(json) ); }); } // XXX: Alternative when mgCrud is not used let id = this.orgData[this.idField]; if(id) { return new Promise((resolve, reject) => { this.$http.put(`${this.url}/${id}`, changedData).then( json => this.writeData(json, resolve), json => reject(json) ); }); } else { return new Promise((resolve, reject) => { this.$http.post(this.url, this.data).then( json => this.writeData(json, resolve), json => reject(json) ); }); } } writeData(json, resolve) { copyObject(json.data, this.data); this.copyData(); resolve(json); } noChanges(resolve) { this.vnAppLogger.showMessage( this.$translate.instant('No changes to save') ); resolve(); } invalidForm(resolve) { this.vnAppLogger.showMessage( this.$translate.instant('Some fields are invalid') ); resolve(); } copyData() { this.orgData = copyObject(this.data); } callback(transition) { if (!this.state && this.dataChanged()) { this.state = transition.to().name; this.$scope.confirm.show(); return false; } return true; } dataChanged() { return !isEqual(this.data, this.orgData); } onConfirmResponse(response) { if(response == 'ACCEPT') { copyObject(this.orgData, this.data); this.$state.go(this.state); } else { this.state = null; } } } Watcher.$inject = ['$element', '$scope', '$state', '$transitions', '$http', 'vnAppLogger', '$translate']; module.component('vnWatcher', { template: require('./index.html'), bindings: { url: '@?', idField: '@?', data: '<', form: '<', save: '<', get: '=?' }, controller: Watcher });