Merge branch 'dev' of http://git.verdnatura.es/salix into dev

This commit is contained in:
Carlos Jimenez 2018-02-06 09:08:02 +01:00
commit 8f6f7fb2a3
11 changed files with 169 additions and 121 deletions

View File

@ -19,3 +19,4 @@ rules:
no-eq-null: 0 no-eq-null: 0
no-console: 0 no-console: 0
no-warning-comments: 0 no-warning-comments: 0
no-empty: 0

View File

@ -1,4 +1,4 @@
<mg-ajax path="/client/api/Addresses/{{edit.params.addressId}}" actions="$ctrl.address=edit.model" options="mgEdit"></mg-ajax> <mg-ajax path="/client/api/Addresses/{{edit.params.addressId}}" actions="$ctrl.address=edit.model;$ctrl._setIconAdd();" options="mgEdit"></mg-ajax>
<vn-watcher <vn-watcher
vn-id="watcher" vn-id="watcher"
url="/client/api/Addresses" url="/client/api/Addresses"
@ -6,7 +6,7 @@
data="$ctrl.address" data="$ctrl.address"
form="form"> form="form">
</vn-watcher> </vn-watcher>
<form name="form" ng-submit="watcher.submitBack()" pad-medium> <form name="form" ng-submit="$ctrl.submit()" pad-medium>
<vn-card> <vn-card>
<vn-vertical pad-large> <vn-vertical pad-large>
<vn-title>Address</vn-title> <vn-title>Address</vn-title>
@ -50,11 +50,11 @@
<vn-one margin-medium-top> <vn-one margin-medium-top>
<vn-title>Notes</vn-title> <vn-title>Notes</vn-title>
<mg-ajax path="/client/api/ObservationTypes" options="mgIndex as observationsTypes"></mg-ajax> <mg-ajax path="/client/api/ObservationTypes" options="mgIndex as observationsTypes"></mg-ajax>
<vn-horizontal ng-repeat="note in $ctrl.notes track by note.id"> <vn-horizontal ng-repeat="observation in $ctrl.observations track by $index">
<vn-autocomplete <vn-autocomplete
vn-one vn-one
initial-data = "note.observationType" initial-data = "observation.observationType"
field = "note.observationTypeFk" field = "observation.observationTypeFk"
data = "observationsTypes.model" data = "observationsTypes.model"
show-field = "description" show-field = "description"
label = "Observation type" label = "Observation type"
@ -63,14 +63,13 @@
> >
<tpl-item>{{$parent.$parent.item.description}}</tpl-item> <tpl-item>{{$parent.$parent.item.description}}</tpl-item>
</vn-autocomplete> </vn-autocomplete>
<vn-textfield vn-three label="Description" model="note.description"></vn-textfield> <vn-textfield vn-three label="Description" model="observation.description"></vn-textfield>
<vn-one pad-medium-top> <vn-one pad-medium-top>
<vn-icon <vn-icon
pointer pointer
medium-grey medium-grey
icon="remove_circle_outline" icon="remove_circle_outline"
ng-if = "note.showRemoveIcon" ng-click="$ctrl.removeObservation($index)"
ng-click="$ctrl.removeNote(note.id)"
> >
</vn-icon> </vn-icon>
<vn-icon <vn-icon
@ -78,8 +77,8 @@
margin-medium-left margin-medium-left
orange orange
icon="add_circle" icon="add_circle"
ng-if = "note.showAddIcon" ng-if = "observation.showAddIcon"
ng-click="$ctrl.addNote()" ng-click="$ctrl.addObservation()"
></vn-icon> ></vn-icon>
</vn-one> </vn-one>
</vn-horizontal> </vn-horizontal>

View File

@ -1,76 +1,137 @@
import ngModule from '../module'; import ngModule from '../module';
export default class Controller { export default class Controller {
constructor($state, $http) { constructor($state, $scope, $http, $q, $translate, vnApp) {
this.$state = $state;
this.$scope = $scope;
this.$http = $http;
this.$q = $q;
this.$translate = $translate;
this.vnApp = vnApp;
this.address = { this.address = {
id: parseInt($state.params.addressId) id: parseInt($state.params.addressId)
}; };
this.$http = $http; this.observations = [];
this.notes = []; this.observationsDictionary = {};
this.observationsRemoved = [];
} }
_setIconAdd() { _setIconAdd() {
if (this.notes.length) { if (this.observations.length) {
this.notes.forEach(element => { this.observations.map(element => {
element.showAddIcon = false; element.showAddIcon = false;
return true;
}); });
this.notes[this.notes.length - 1].showAddIcon = true; this.observations[this.observations.length - 1].showAddIcon = true;
}
}
_setRemoveAdd() {
if (this.notes.length) {
this.notes.forEach(element => {
element.showRemoveIcon = true;
});
} else { } else {
this.notes = [this._createEmptyNote()]; this.addObservation();
}
}
_createEmptyNote() {
return {id: this._createFakeId(), observationTypeFk: null, description: null, showRemoveIcon: true, showAddIcon: true};
}
_createFakeId() {
let now = Date.now();
let random = Math.ceil((Math.random() * 100000) + 1);
return `fakeId${now}${random}`;
}
addNote() {
this.notes.push(this._createEmptyNote());
this._setIconAdd();
this._setRemoveAdd();
}
removeNote(id) {
let found = false;
for (let i = 0; i < this.notes.length; i++) {
if (this.notes[i].id === id) {
this.notes.splice(i, 1);
found = true;
break;
} }
} }
if (found) { _setDirtyForm() {
if (this.$scope.form) {
this.$scope.form.$setDirty();
}
}
_unsetDirtyForm() {
if (this.$scope.form) {
this.$scope.form.$setPristine();
}
}
addObservation() {
this.observations.push({observationTypeFk: null, description: null, showAddIcon: true});
this._setIconAdd(); this._setIconAdd();
this._setRemoveAdd(); }
removeObservation(index) {
let item = this.observations[index];
if (item) {
this.observations.splice(index, 1);
this._setIconAdd();
if (item.id) {
this.observationsRemoved.push(item.id);
this._setDirtyForm();
} }
} }
}
_submitObservations(objectObservations) {
return this.$http.post('/client/api/crudAddressObservations', objectObservations);
}
submit() {
this._unsetDirtyForm();
let submitWatcher = this.$scope.watcher.dataChanged();
let submitObservations;
let repeatedTypes = false;
let observationsObj = {
remove: this.observationsRemoved,
news: [],
modified: []
};
for (let i = 0; i < this.observations.length; i++) {
let observation = this.observations[i];
// only one observation is allowed for each of its types
if (this.observationsDictionary[observation.observationTypeFk] !== undefined && // IF the dictionary contains the type
(
// AND (is a new Observation OR is old but with distinct Id) --> repeated
!observation.id || (observation.id && this.observationsDictionary[observation.observationTypeFk].id !== observation.id)
)
) {
repeatedTypes = true;
break;
}
this.observationsDictionary[observation.observationTypeFk] = observation;
if (!observation.id && observation.observationTypeFk && observation.description) {
observationsObj.news.push(observation);
} else if (observation.id && this.observationsDictionary[observation.observationTypeFk].description !== observation.description) {
observationsObj.modified.push(observation);
}
}
submitObservations = observationsObj.modified.length > 0 || observationsObj.news.length > 0 || observationsObj.remove.length > 0;
if (repeatedTypes) {
this.vnApp.showMessage(
this.$translate.instant('you can not repeat the types of observations')
);
} else if (submitWatcher && !submitObservations) {
this.$scope.watcher.submit().then(() => {
this.$state.go('clientCard.addresses.list', {id: this.$state.params.id});
});
} else if (!submitWatcher && submitObservations) {
this._submitObservations(observationsObj).then(() => {
this.$state.go('clientCard.addresses.list', {id: this.$state.params.id});
});
} else if (submitWatcher && submitObservations) {
this.$q.all([this.$scope.watcher.submit(), this._submitObservations(observationsObj)]).then(() => {
this.$state.go('clientCard.addresses.list', {id: this.$state.params.id});
});
} else {
this.vnApp.showMessage(
this.$translate.instant('No changes to save')
);
}
}
$onInit() { $onInit() {
let filter = { let filter = {
where: { where: {addressFk: this.address.id},
addressFk: this.address.id include: {relation: 'observationType'}
},
include: [
{relation: 'observationType'}
]
}; };
this.$http.get(`/client/api/AddressObservations?filter=${JSON.stringify(filter)}`).then(res => { this.$http.get(`/client/api/AddressObservations?filter=${JSON.stringify(filter)}`).then(res => {
this.notes = (res.data && res.data.length) ? res.data : [this._createEmptyNote()]; this.observations = res.data;
this._setIconAdd(); this.observations.forEach(item => {
this._setRemoveAdd(); this.observationsDictionary[item.observationTypeFk] = {id: item.id, description: item.description};
});
}); });
} }
} }
Controller.$inject = ['$state', '$http']; Controller.$inject = ['$state', '$scope', '$http', '$q', '$translate', 'vnApp'];
ngModule.component('vnAddressEdit', { ngModule.component('vnAddressEdit', {
template: require('./address-edit.html'), template: require('./address-edit.html'),

View File

@ -3,6 +3,9 @@ import isEqual from './equals';
export default function getModifiedData(object, objectOld) { export default function getModifiedData(object, objectOld) {
var newObject = {}; var newObject = {};
if (objectOld === null) {
return object;
}
for (var k in object) { for (var k in object) {
var val = object[k]; var val = object[k];
var valOld = objectOld[k] === undefined ? null : objectOld[k]; var valOld = objectOld[k] === undefined ? null : objectOld[k];

View File

@ -96,7 +96,7 @@ export default class Watcher extends Component {
} }
let changedData = (this.$attrs.save && this.$attrs.save.toLowerCase() === 'post') ? this.copyInNewObject(this.data) : getModifiedData(this.data, this.orgData); let changedData = (this.$attrs.save && this.$attrs.save.toLowerCase() === 'post') ? this.copyInNewObject(this.data) : getModifiedData(this.data, this.orgData);
if (this.save) { if (this.save && this.save.accept) {
this.save.model = changedData; // this.copyInNewObject(changedData); this.save.model = changedData; // this.copyInNewObject(changedData);
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.save.accept().then( this.save.accept().then(
@ -108,7 +108,7 @@ export default class Watcher extends Component {
// XXX: Alternative when mgCrud is not used // XXX: Alternative when mgCrud is not used
let id = this.orgData[this.idField]; let id = this.idField ? this.orgData[this.idField] : null;
if (id) { if (id) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -120,7 +120,7 @@ export default class Watcher extends Component {
} }
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.$http.post(this.url, this.data).then( this.$http.post(this.url, changedData).then(
json => this.writeData(json, resolve), json => this.writeData(json, resolve),
json => reject(json) json => reject(json)
); );
@ -181,7 +181,7 @@ export default class Watcher extends Component {
} }
dataChanged() { dataChanged() {
if (this.form && !this.form.$dirty) return false; if (this.form && this.form.$dirty) return true;
let newData = this.copyInNewObject(this.data); let newData = this.copyInNewObject(this.data);
return !isEqual(newData, this.orgData); return !isEqual(newData, this.orgData);
} }

View File

@ -145,7 +145,7 @@ describe('Component vnWatcher', () => {
describe('when controller.save()', () => { describe('when controller.save()', () => {
it(`should set controller.save.model property`, () => { it(`should set controller.save.model property`, () => {
controller.save = {}; controller.save = {accept: () => {}};
controller.data = {originalInfo: 'original data', info: 'new data'}; controller.data = {originalInfo: 'original data', info: 'new data'};
controller.orgData = {originalInfo: 'original data'}; controller.orgData = {originalInfo: 'original data'};
controller.submit(); controller.submit();

View File

@ -101,6 +101,9 @@ gulp.task('install', () => {
})); }));
}); });
// Gulp install alias
gulp.task('i', ['install']);
// Deployment // Deployment
gulp.task('build', ['clean'], () => { gulp.task('build', ['clean'], () => {
@ -141,13 +144,48 @@ gulp.task('docker-compose', async () => {
// Nginx & services // Nginx & services
gulp.task('nginx', ['nginx-conf'], callback => { let nginxConf = 'temp/nginx.conf';
let command = isWindows ? 'start.cmd' : 'start.sh'; let nginxTemp = `${nginxDir}/temp`;
command = path.join(`${nginxDir}/${command}`);
exec(command, (err, stdout, stderr) => { async function nginxGetBin() {
// if (stderr) console.log(stderr); if (isWindows)
callback(err); return 'nginx';
try {
let nginxBin = '/usr/sbin/nginx';
await fs.stat(nginxBin);
return nginxBin;
} catch (e) {
return 'nginx';
}
}
gulp.task('nginx', ['nginx-stop'], async () => {
let nginxBin = await nginxGetBin();
if (isWindows)
nginxBin = `start /B ${nginxBin}`;
return new Promise((resolve, reject) => {
exec(`${nginxBin} -c "${nginxConf}" -p "${nginxDir}"`, err => {
if (err) return reject(err);
resolve();
}); });
});
});
gulp.task('nginx-stop', ['nginx-conf'], async () => {
try {
let nginxBin = await nginxGetBin();
await fs.stat(`${nginxTemp}/nginx.pid`);
let command = `${nginxBin} -c "${nginxConf}" -p "${nginxDir}" -s stop`;
return new Promise((resolve, reject) => {
exec(command, err => {
if (err) return reject(err);
resolve();
});
});
} catch (e) {}
}); });
gulp.task('nginx-conf', async () => { gulp.task('nginx-conf', async () => {

4
package-lock.json generated
View File

@ -10103,7 +10103,7 @@
"karma-chrome-launcher": { "karma-chrome-launcher": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz", "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz",
"integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==", "integrity": "sha1-zxudBxNswY/iOTJ9JGVMPbw2is8=",
"dev": true, "dev": true,
"requires": { "requires": {
"fs-access": "1.0.1", "fs-access": "1.0.1",
@ -10134,7 +10134,7 @@
"karma-webpack": { "karma-webpack": {
"version": "2.0.9", "version": "2.0.9",
"resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-2.0.9.tgz", "resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-2.0.9.tgz",
"integrity": "sha512-F1j3IG/XhiMzcunAXbWXH95uizjzr3WdTzmVWlta8xqxcCtAu9FByCb4sccIMxaVFAefpgnUW9KlCo0oLvIX6A==", "integrity": "sha1-YciAkffdkQY1E0wDKyZqRlr/tX8=",
"dev": true, "dev": true,
"requires": { "requires": {
"async": "0.9.2", "async": "0.9.2",

View File

@ -38,7 +38,8 @@ module.exports = function(Client) {
}, },
skip: (params.page - 1) * params.size, skip: (params.page - 1) * params.size,
limit: params.size, limit: params.size,
order: ['isDefaultAddress DESC', 'isActive DESC'] order: ['isDefaultAddress DESC', 'isActive DESC'],
include: {observations: 'observationType'}
}; };
let total = null; let total = null;

View File

@ -1,27 +0,0 @@
@echo off
set nginxDir=%~dp0
set nginxTemp=%nginxDir%\temp
set nginxConf=temp\nginx.conf
if "%1"=="" goto caseStart
if "%1"=="start" goto caseStart
if "%1"=="stop" goto caseStop
goto caseUsage
:caseStart
call "%0" stop
echo Starting nginx.
if not exist "%nginxTemp%" (mkdir "%nginxTemp%")
start /I nginx -c "%nginxConf%" -p "%nginxDir%"
goto caseEnd
:caseStop
echo Stoping nginx.
if exist "%nginxTemp%\nginx.pid" (nginx -c "%nginxConf%" -p "%nginxDir%" -s stop)
goto caseEnd
:caseUsage
echo "Usage: %0 [start|stop]"
:caseEnd

View File

@ -1,28 +0,0 @@
#!/bin/bash
nginxDir="$(dirname $0)"
nginxTemp="$nginxDir/temp"
nginxConf="temp/nginx.conf"
nginxBin="/usr/sbin/nginx"
if [ ! -f $nginxBin ]; then
nginxBin="nginx"
fi
case "$1" in
start|"")
$0 stop
echo "Starting nginx."
mkdir -p "$nginxTemp"
"$nginxBin" -c "$nginxConf" -p "$nginxDir"
;;
stop)
echo "Stoping nginx."
if [ -f "$nginxTemp/nginx.pid" ]; then
"$nginxBin" -c "$nginxConf" -p "$nginxDir" -s stop
fi
;;
*)
echo "Usage: `basename "$0"` [start|stop]"
exit 1
esac