#179 listar notas de ticket
This commit is contained in:
parent
a218e50658
commit
ece2fd384d
|
@ -46,6 +46,18 @@
|
||||||
"icon": "settings"
|
"icon": "settings"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"url": "/observations",
|
||||||
|
"state": "ticket.card.observations",
|
||||||
|
"component": "vn-ticket-observations",
|
||||||
|
"params": {
|
||||||
|
"ticket": "$ctrl.ticket"
|
||||||
|
},
|
||||||
|
"menu": {
|
||||||
|
"description": "Notes",
|
||||||
|
"icon": "insert_drive_file"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"url" : "/package",
|
"url" : "/package",
|
||||||
"abstract": true,
|
"abstract": true,
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
<vn-watcher
|
||||||
|
vn-id="watcher"
|
||||||
|
url="/client/api/Addresses"
|
||||||
|
id-field="id"
|
||||||
|
data="$ctrl.address"
|
||||||
|
form="form">
|
||||||
|
</vn-watcher>
|
||||||
|
<form name="form" ng-submit="$ctrl.submit()">
|
||||||
|
<vn-card pad-large>
|
||||||
|
<vn-one margin-medium-top>
|
||||||
|
<vn-title>Notes</vn-title>
|
||||||
|
<mg-ajax path="/ticket/api/ObservationTypes" options="mgIndex as observationTypes"></mg-ajax>
|
||||||
|
<vn-horizontal ng-repeat="ticketObservation in $ctrl.ticketObservations track by $index">
|
||||||
|
<vn-autocomplete
|
||||||
|
ng-if="!ticketObservation.id"
|
||||||
|
vn-one
|
||||||
|
initial-data="ticketObservation.observationType"
|
||||||
|
field="ticketObservation.observationTypeFk"
|
||||||
|
data="observationTypes.model"
|
||||||
|
show-field="description"
|
||||||
|
label="Observation type">
|
||||||
|
</vn-autocomplete>
|
||||||
|
<vn-textfield
|
||||||
|
ng-if="ticketObservation.id"
|
||||||
|
vn-one
|
||||||
|
label="Observation type"
|
||||||
|
model="ticketObservation.observationType.description"
|
||||||
|
disabled="true">
|
||||||
|
</vn-textfield>
|
||||||
|
<vn-textfield
|
||||||
|
vn-two
|
||||||
|
margin-large-right
|
||||||
|
label="Description"
|
||||||
|
model="ticketObservation.description">
|
||||||
|
</vn-textfield>
|
||||||
|
<vn-auto pad-medium-top>
|
||||||
|
<vn-icon
|
||||||
|
pointer
|
||||||
|
medium-grey
|
||||||
|
vn-tooltip="Remove note"
|
||||||
|
tooltip-position="left"
|
||||||
|
icon="remove_circle_outline"
|
||||||
|
ng-click="$ctrl.removeObservation($index)">
|
||||||
|
</vn-icon>
|
||||||
|
</vn-auto>
|
||||||
|
</vn-horizontal>
|
||||||
|
</vn-one>
|
||||||
|
<vn-one>
|
||||||
|
<vn-icon
|
||||||
|
pointer margin-medium-left vn-tooltip="Add note"
|
||||||
|
tooltip-position="right" orange icon="add_circle"
|
||||||
|
ng-if="observationTypes.model.length > $ctrl.ticketObservations.length"
|
||||||
|
ng-click="$ctrl.addObservation()">
|
||||||
|
</vn-icon>
|
||||||
|
</vn-one>
|
||||||
|
</vn-card>
|
||||||
|
<vn-button-bar>
|
||||||
|
<vn-submit label="Save"></vn-submit>
|
||||||
|
</vn-button-bar>
|
||||||
|
</form>
|
|
@ -0,0 +1,140 @@
|
||||||
|
import ngModule from '../module';
|
||||||
|
|
||||||
|
class TicketObservations {
|
||||||
|
constructor($stateParams, $scope, $http, $translate, vnApp) {
|
||||||
|
this.params = $stateParams;
|
||||||
|
this.$scope = $scope;
|
||||||
|
this.$http = $http;
|
||||||
|
this.$translate = $translate;
|
||||||
|
this.vnApp = vnApp;
|
||||||
|
|
||||||
|
this.ticketObservations = [];
|
||||||
|
this.oldObservations = {};
|
||||||
|
this.removedObservations = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
_setIconAdd() {
|
||||||
|
if (this.ticketObservations.length) {
|
||||||
|
this.ticketObservations.map(element => {
|
||||||
|
element.showAddIcon = false;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
this.ticketObservations[this.ticketObservations.length - 1].showAddIcon = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_setDirtyForm() {
|
||||||
|
if (this.$scope.form) {
|
||||||
|
this.$scope.form.$setDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_unsetDirtyForm() {
|
||||||
|
if (this.$scope.form) {
|
||||||
|
this.$scope.form.$setPristine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addObservation() {
|
||||||
|
this.ticketObservations.push({description: null, ticketFk: this.params.id, showAddIcon: true});
|
||||||
|
this._setIconAdd();
|
||||||
|
}
|
||||||
|
|
||||||
|
removeObservation(index) {
|
||||||
|
let item = this.ticketObservations[index];
|
||||||
|
if (item) {
|
||||||
|
this.ticketObservations.splice(index, 1);
|
||||||
|
this._setIconAdd();
|
||||||
|
if (item.id) {
|
||||||
|
this.removedObservations.push(item.id);
|
||||||
|
this._setDirtyForm();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_equalObservations(oldObservation, newObservation) {
|
||||||
|
return oldObservation.id === newObservation.id && oldObservation.observationTypeFk === newObservation.observationTypeFk && oldObservation.description === newObservation.description;
|
||||||
|
}
|
||||||
|
|
||||||
|
setOldObservations(response) {
|
||||||
|
this._setIconAdd();
|
||||||
|
response.data.forEach(observation => {
|
||||||
|
this.oldObservations[observation.id] = Object.assign({}, observation);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getObservations() {
|
||||||
|
let filter = {
|
||||||
|
where: {ticketFk: this.params.id},
|
||||||
|
include: ['observationType']
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$http.get(`/ticket/api/TicketObservations?filter=${JSON.stringify(filter)}`).then(response => {
|
||||||
|
this.ticketObservations = response.data;
|
||||||
|
this.setOldObservations(response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
submit() {
|
||||||
|
let typesDefined = [];
|
||||||
|
let repeatedType = false;
|
||||||
|
let canSubmit;
|
||||||
|
let observationsObj = {
|
||||||
|
delete: this.removedObservations,
|
||||||
|
create: [],
|
||||||
|
update: []
|
||||||
|
};
|
||||||
|
|
||||||
|
this.ticketObservations.forEach(observation => {
|
||||||
|
let isNewObservation = !observation.id;
|
||||||
|
|
||||||
|
delete observation.showAddIcon;
|
||||||
|
|
||||||
|
if (typesDefined.indexOf(observation.observationTypeFk) !== -1) {
|
||||||
|
repeatedType = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
typesDefined.push(observation.observationTypeFk);
|
||||||
|
|
||||||
|
if (isNewObservation && observation.description && observation.observationTypeFk) {
|
||||||
|
observationsObj.create.push(observation);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isNewObservation && !this._equalObservations(this.oldObservations[observation.id], observation)) {
|
||||||
|
observationsObj.update.push(observation);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this.$scope.form.$invalid) {
|
||||||
|
return this.vnApp.showMessage(this.$translate.instant('Some fields are invalid'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (repeatedType) {
|
||||||
|
return this.vnApp.showMessage(this.$translate.instant('The observation type must be unique'));
|
||||||
|
}
|
||||||
|
|
||||||
|
canSubmit = observationsObj.update.length > 0 || observationsObj.create.length > 0 || observationsObj.delete.length > 0;
|
||||||
|
|
||||||
|
if (canSubmit) {
|
||||||
|
return this.$http.post(`/ticket/api/TicketObservations/crudTicketObservations`, observationsObj).then(() => {
|
||||||
|
this.getObservations();
|
||||||
|
this._unsetDirtyForm();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.vnApp.showMessage(this.$translate.instant('No changes to save'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$onInit() {
|
||||||
|
this.getObservations();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TicketObservations.$inject = ['$stateParams', '$scope', '$http', '$translate', 'vnApp'];
|
||||||
|
|
||||||
|
ngModule.component('vnTicketObservations', {
|
||||||
|
template: require('./ticket-observations.html'),
|
||||||
|
controller: TicketObservations,
|
||||||
|
bindings: {
|
||||||
|
ticket: '<'
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,143 @@
|
||||||
|
import './ticket-observations.js';
|
||||||
|
|
||||||
|
describe('ticket', () => {
|
||||||
|
describe('Component vnTicketObservations', () => {
|
||||||
|
let $componentController;
|
||||||
|
let $state;
|
||||||
|
let controller;
|
||||||
|
let $httpBackend;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
angular.mock.module('ticket');
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_) => {
|
||||||
|
$componentController = _$componentController_;
|
||||||
|
$state = _$state_;
|
||||||
|
$httpBackend = _$httpBackend_;
|
||||||
|
controller = $componentController('vnTicketObservations', {$state: $state});
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('add / remove observation', () => {
|
||||||
|
it('should add one empty observation into controller observations collection and call _setIconAdd()', () => {
|
||||||
|
controller.ticketObservations = [];
|
||||||
|
spyOn(controller, '_setIconAdd').and.callThrough();
|
||||||
|
controller.addObservation();
|
||||||
|
|
||||||
|
expect(controller._setIconAdd).toHaveBeenCalledWith();
|
||||||
|
expect(controller.ticketObservations.length).toEqual(1);
|
||||||
|
expect(controller.ticketObservations[0].id).toBe(undefined);
|
||||||
|
expect(controller.ticketObservations[0].showAddIcon).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should remove an observation that occupies the position in the index given and call _setIconAdd()', () => {
|
||||||
|
let index = 2;
|
||||||
|
controller.ticketObservations = [
|
||||||
|
{id: 1, observationTypeFk: 1, description: 'one', showAddIcon: false},
|
||||||
|
{id: 2, observationTypeFk: 2, description: 'two', showAddIcon: false},
|
||||||
|
{id: 3, observationTypeFk: 3, description: 'three', showAddIcon: true}
|
||||||
|
];
|
||||||
|
|
||||||
|
spyOn(controller, '_setIconAdd').and.callThrough();
|
||||||
|
|
||||||
|
controller.removeObservation(index);
|
||||||
|
|
||||||
|
expect(controller._setIconAdd).toHaveBeenCalledWith();
|
||||||
|
expect(controller.ticketObservations.length).toEqual(2);
|
||||||
|
expect(controller.ticketObservations[0].showAddIcon).toBeFalsy();
|
||||||
|
expect(controller.ticketObservations[1].showAddIcon).toBeTruthy();
|
||||||
|
expect(controller.ticketObservations[index]).toBe(undefined);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('_equalObservations()', () => {
|
||||||
|
it('should return true if two observations are equals independent of control attributes', () => {
|
||||||
|
let observationOne = {id: 1, observationTypeFk: 1, description: 'one', showAddIcon: true};
|
||||||
|
let observationTwo = {id: 1, observationTypeFk: 1, description: 'one', showAddIcon: false};
|
||||||
|
let equals = controller._equalObservations(observationOne, observationTwo);
|
||||||
|
|
||||||
|
expect(equals).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false if two observations aint equals independent of control attributes', () => {
|
||||||
|
let observationOne = {id: 1, observationTypeFk: 1, description: 'one', showAddIcon: true};
|
||||||
|
let observationTwo = {id: 1, observationTypeFk: 1, description: 'two', showAddIcon: true};
|
||||||
|
let equals = controller._equalObservations(observationOne, observationTwo);
|
||||||
|
|
||||||
|
expect(equals).toBeFalsy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('get Observations()', () => {
|
||||||
|
it('should perform a GET query to receive the ticket observations', () => {
|
||||||
|
let res = [{id: 1, observationTypeFk: 1, description: 'one'}];
|
||||||
|
|
||||||
|
$httpBackend.whenGET(`/ticket/api/TicketObservations?filter={"where":{},"include":["observationType"]}`).respond(res);
|
||||||
|
$httpBackend.expectGET(`/ticket/api/TicketObservations?filter={"where":{},"include":["observationType"]}`);
|
||||||
|
controller.getObservations();
|
||||||
|
$httpBackend.flush();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('submit()', () => {
|
||||||
|
it("should return an error message 'The observation type must be unique'", () => {
|
||||||
|
controller.$scope.form = {};
|
||||||
|
spyOn(controller.vnApp, 'showMessage').and.callThrough();
|
||||||
|
controller.ticketObservations = [
|
||||||
|
{id: 1, observationTypeFk: 1, description: 'one', itemFk: 1},
|
||||||
|
{observationTypeFk: 1, description: 'one', itemFk: 1}
|
||||||
|
];
|
||||||
|
controller.oldObservations = {1: {id: 1, observationTypeFk: 1, description: 'one', itemFk: 1}};
|
||||||
|
controller.submit();
|
||||||
|
|
||||||
|
expect(controller.vnApp.showMessage).toHaveBeenCalledWith('The observation type must be unique');
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should perfom a query to delete observations", () => {
|
||||||
|
controller.$scope.form = {$setPristine: () => {}};
|
||||||
|
controller.oldObservations = {1: {id: 1, observationTypeFk: 1, description: 'one'}};
|
||||||
|
controller.ticketObservations = [];
|
||||||
|
controller.removedObservations = [1];
|
||||||
|
|
||||||
|
$httpBackend.whenGET(`/ticket/api/TicketObservations?filter={"where":{},"include":["observationType"]}`).respond([]);
|
||||||
|
$httpBackend.expectPOST(`/ticket/api/TicketObservations/crudTicketObservations`).respond('ok!');
|
||||||
|
controller.submit();
|
||||||
|
$httpBackend.flush();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should perfom a query to update observations", () => {
|
||||||
|
controller.$scope.form = {$setPristine: () => {}};
|
||||||
|
controller.ticketObservations = [{id: 1, observationTypeFk: 1, description: 'number one!'}];
|
||||||
|
controller.oldObservations = {1: {id: 1, observationTypeFk: 1, description: 'one'}};
|
||||||
|
|
||||||
|
$httpBackend.whenGET(`/ticket/api/TicketObservations?filter={"where":{},"include":["observationType"]}`).respond([]);
|
||||||
|
$httpBackend.expectPOST(`/ticket/api/TicketObservations/crudTicketObservations`).respond('ok!');
|
||||||
|
controller.submit();
|
||||||
|
$httpBackend.flush();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should perfom a query to create new observation", () => {
|
||||||
|
controller.$scope.form = {$setPristine: () => {}};
|
||||||
|
controller.ticketObservations = [{observationTypeFk: 2, description: 'two'}];
|
||||||
|
|
||||||
|
$httpBackend.whenGET(`/ticket/api/TicketObservations?filter={"where":{},"include":["observationType"]}`).respond([]);
|
||||||
|
$httpBackend.expectPOST(`/ticket/api/TicketObservations/crudTicketObservations`).respond('ok!');
|
||||||
|
controller.submit();
|
||||||
|
$httpBackend.flush();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return a message 'No changes to save' when there are no changes to apply", () => {
|
||||||
|
controller.$scope.form = {$setPristine: () => {}};
|
||||||
|
spyOn(controller.vnApp, 'showMessage').and.callThrough();
|
||||||
|
controller.oldObservations = [
|
||||||
|
{id: 1, observationTypeFk: 1, description: 'one', showAddIcon: false},
|
||||||
|
{id: 2, observationTypeFk: 2, description: 'two', showAddIcon: true}
|
||||||
|
];
|
||||||
|
controller.ticketObservations = [];
|
||||||
|
controller.submit();
|
||||||
|
|
||||||
|
expect(controller.vnApp.showMessage).toHaveBeenCalledWith('No changes to save');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -5,5 +5,6 @@ import './create/ticket-create';
|
||||||
import './card/ticket-card';
|
import './card/ticket-card';
|
||||||
import './summary/ticket-summary';
|
import './summary/ticket-summary';
|
||||||
import './data/ticket-data';
|
import './data/ticket-data';
|
||||||
|
import './notes/ticket-observations';
|
||||||
import './package/list/package-list';
|
import './package/list/package-list';
|
||||||
import './review/review';
|
import './review/review';
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.installCrudModel('crudTicketObservations');
|
||||||
|
};
|
|
@ -0,0 +1,3 @@
|
||||||
|
module.exports = function(Self) {
|
||||||
|
require('../methods/ticket/crudTicketObservations.js')(Self);
|
||||||
|
};
|
|
@ -2,33 +2,33 @@
|
||||||
"name": "TicketObservation",
|
"name": "TicketObservation",
|
||||||
"base": "VnModel",
|
"base": "VnModel",
|
||||||
"options": {
|
"options": {
|
||||||
"mysql": {
|
"mysql": {
|
||||||
"table": "ticketObservation"
|
"table": "ticketObservation"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
"id": {
|
"id": {
|
||||||
"id": true,
|
"id": true,
|
||||||
"type": "Number",
|
"type": "Number",
|
||||||
"description": "Identifier"
|
"description": "Identifier"
|
||||||
},
|
},
|
||||||
"description": {
|
"description": {
|
||||||
"type": "String",
|
"type": "String",
|
||||||
"required": true
|
"required": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"relations": {
|
"relations": {
|
||||||
"ticket": {
|
"ticket": {
|
||||||
"type": "belongsTo",
|
"type": "belongsTo",
|
||||||
"model": "Ticket",
|
"model": "Ticket",
|
||||||
"foreignKey": "ticketFk",
|
"foreignKey": "ticketFk",
|
||||||
"required": true
|
"required": true
|
||||||
},
|
},
|
||||||
"observationType": {
|
"observationType": {
|
||||||
"type": "belongsTo",
|
"type": "belongsTo",
|
||||||
"model": "ObservationType",
|
"model": "ObservationType",
|
||||||
"foreignKey": "observationTypeFk",
|
"foreignKey": "observationTypeFk",
|
||||||
"required": true
|
"required": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue