2151 - Added thermograph edit section
gitea/salix/pipeline/head This commit has test failures Details

This commit is contained in:
Joan Sanchez 2020-02-28 14:18:55 +01:00
parent a2001636d2
commit 28b7f5d3a2
14 changed files with 219 additions and 90 deletions

View File

@ -10,8 +10,7 @@ module.exports = Self => {
type: 'Number',
description: 'The document id',
http: {source: 'path'}
},
{
}, {
arg: 'warehouseId',
type: 'Number',
description: 'The warehouse id'
@ -44,9 +43,9 @@ module.exports = Self => {
}
});
Self.updateFile = async(ctx, id, warehouseId, companyId,
dmsTypeId, reference, description, hasFileAttached, options) => {
Self.updateFile = async(ctx, id, options) => {
const models = Self.app.models;
const args = ctx.args;
let tx;
let myOptions = {};
@ -60,20 +59,20 @@ module.exports = Self => {
}
try {
const hasWriteRole = await models.DmsType.hasWriteRole(ctx, dmsTypeId);
const hasWriteRole = await models.DmsType.hasWriteRole(ctx, args.dmsTypeId);
if (!hasWriteRole)
throw new UserError(`You don't have enough privileges`);
const dms = await Self.findById(id, null, myOptions);
await dms.updateAttributes({
dmsTypeFk: dmsTypeId,
companyFk: companyId,
warehouseFk: warehouseId,
reference: reference,
description: description
dmsTypeFk: args.dmsTypeId,
companyFk: args.companyId,
warehouseFk: args.warehouseId,
reference: args.reference,
description: args.description
}, myOptions);
if (hasFileAttached)
if (args.hasFileAttached)
await uploadNewFile(ctx, dms, myOptions);
if (tx) await tx.commit();

View File

@ -192,7 +192,7 @@ export default {
},
dms: {
deleteFileButton: 'vn-client-dms-index vn-tr:nth-child(1) vn-icon-button[icon="delete"]',
firstDocWorker: 'vn-client-dms-index vn-td:nth-child(8) > span',
firstDocWorker: 'vn-client-dms-index vn-td:nth-child(7) > span',
firstDocWorkerDescriptor: '.vn-popover.shown vn-worker-descriptor',
acceptDeleteButton: '.vn-confirm.shown button[response="accept"]'
},
@ -786,7 +786,7 @@ export default {
travelThermograph: {
add: 'vn-travel-thermograph-index vn-float-button[icon="add"]',
thermographID: 'vn-travel-thermograph-create vn-autocomplete[ng-model="$ctrl.dms.thermographId"]',
uploadIcon: 'vn-travel-thermograph-create vn-icon[icon="cloud_upload"]',
uploadIcon: 'vn-travel-thermograph-create vn-icon[icon="attach_file"]',
createdThermograph: 'vn-travel-thermograph-index vn-tbody > vn-tr',
upload: 'vn-travel-thermograph-create button[type=submit]'
},

View File

@ -56,7 +56,16 @@
label="File"
ng-model="$ctrl.dms.files"
on-change="$ctrl.onFileChange($files)"
accept=".pdf, .png, .jpg, .jpeg, application/zip, application/rar, application/x-7z-compressed">
accept="{{$ctrl.allowedContentTypes}}"
required="true"
multiple="true">
<append>
<vn-icon vn-none
color-marginal
title="{{$ctrl.contentTypesInfo}}"
icon="info">
</vn-icon>
</append>
</vn-input-file>
</vn-horizontal>
<vn-vertical>

View File

@ -53,11 +53,6 @@
{{::document.dms.description}}
</span>
</vn-td>
<vn-td shrink>
<vn-check disabled="true"
ng-model="document.dms.hasFile">
</vn-check>
</vn-td>
<vn-td shrink>
<a target="_blank"
title="{{'Download file' | translate}}"

View File

@ -51,11 +51,6 @@
{{::document.dms.description}}
</span>
</vn-td>
<vn-td shrink>
<vn-check disabled="true"
field="document.dms.hasFile">
</vn-check>
</vn-td>
<vn-td shrink>
<a target="_blank"
title="{{'Download file' | translate}}"

View File

@ -58,7 +58,6 @@ module.exports = Self => {
try {
const options = {transaction: tx};
const travelThermograph = await models.TravelThermograph.findOne({
where: {
thermographFk: thermographId,

View File

@ -0,0 +1,83 @@
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.remoteMethodCtx('updateThermograph', {
description: 'updates a file properties or file',
accessType: 'WRITE',
accepts: [{
arg: 'id',
type: 'Number',
description: 'The travel id',
http: {source: 'path'}
}, {
arg: 'thermographId',
type: 'String',
description: 'The thermograph id',
required: true
}, {
arg: 'state',
type: 'String',
required: true
}, {
arg: 'warehouseId',
type: 'Number',
description: 'The warehouse id'
}, {
arg: 'companyId',
type: 'Number',
description: 'The company id'
}, {
arg: 'dmsTypeId',
type: 'Number',
description: 'The dms type id'
}, {
arg: 'reference',
type: 'String'
}, {
arg: 'description',
type: 'String'
}, {
arg: 'hasFileAttached',
type: 'Boolean',
description: 'True if has an attached file'
}],
returns: {
type: 'Object',
root: true
},
http: {
path: `/:id/updateThermograph`,
verb: 'POST'
}
});
Self.updateThermograph = async(ctx, id, thermographId, state) => {
const models = Self.app.models;
const tx = await Self.beginTransaction({});
try {
const options = {transaction: tx};
const travelThermograph = await models.TravelThermograph.findOne({
where: {
thermographFk: thermographId,
travelFk: id
}
}, options);
if (!travelThermograph)
throw new UserError('No valid travel thermograph found');
const dmsFk = travelThermograph.dmsFk;
await models.Dms.updateFile(ctx, dmsFk, options);
await travelThermograph.updateAttributes({
result: state
}, options);
await tx.commit();
return travelThermograph;
} catch (e) {
await tx.rollback();
throw e;
}
};
};

View File

@ -4,4 +4,5 @@ module.exports = Self => {
require('../methods/travel/filter')(Self);
require('../methods/travel/createThermograph')(Self);
require('../methods/travel/deleteThermograph')(Self);
require('../methods/travel/updateThermograph')(Self);
};

View File

@ -82,7 +82,7 @@
},
"acl": ["buyer"]
}, {
"url" : "/:dmsId/edit",
"url" : "/:thermographId/edit",
"state": "travel.card.thermograph.edit",
"component": "vn-travel-thermograph-edit",
"description": "Edit thermograph",

View File

@ -12,27 +12,27 @@
<vn-horizontal>
<vn-autocomplete vn-one
label="Thermograph"
ng-model="$ctrl.dms.thermographId"
ng-model="$ctrl.thermograph.thermographId"
url="TravelThermographs"
where="{travelFk: null}"
show-field="thermographFk"
value-field="thermographFk">
value-field="thermographFk"
disabled="true">
</vn-autocomplete>
<vn-textfield vn-one
label="State"
ng-model="$ctrl.dms.state"
ng-model="$ctrl.thermograph.state"
rule>
</vn-textfield>
</vn-horizontal>
<vn-horizontal>
<vn-textfield vn-one
label="Reference"
ng-model="$ctrl.dms.reference"
ng-model="$ctrl.thermograph.reference"
rule>
</vn-textfield>
<vn-autocomplete vn-one
label="Type"
ng-model="$ctrl.dms.dmsTypeId"
ng-model="$ctrl.thermograph.dmsTypeId"
url="DmsTypes"
show-field="name"
value-field="id">
@ -41,14 +41,14 @@
<vn-horizontal>
<vn-autocomplete vn-one
label="Company"
ng-model="$ctrl.dms.companyId"
ng-model="$ctrl.thermograph.companyId"
url="Companies"
show-field="code"
value-field="id">
</vn-autocomplete>
<vn-autocomplete vn-one
label="Warehouse"
ng-model="$ctrl.dms.warehouseId"
ng-model="$ctrl.thermograph.warehouseId"
url="Warehouses"
show-field="name"
value-field="id">
@ -57,7 +57,7 @@
<vn-horizontal>
<vn-textarea vn-one vn-focus
label="Description"
ng-model="$ctrl.dms.description"
ng-model="$ctrl.thermograph.description"
rule>
</vn-textarea>
</vn-horizontal>
@ -65,7 +65,8 @@
<vn-input-file
vn-one
label="File"
ng-model="$ctrl.dms.files"
ng-model="$ctrl.thermograph.files"
on-change="$ctrl.onFileChange($files)"
accept="{{$ctrl.allowedContentTypes}}"
multiple="true">
<append>

View File

@ -30,16 +30,20 @@ class Controller extends Component {
}
setDefaultParams() {
const path = `Dms/${this.$params.dmsId}`;
const filterObj = {include: {relation: 'dms'}};
const filter = encodeURIComponent(JSON.stringify(filterObj));
const path = `TravelThermographs/${this.$params.thermographId}?filter=${filter}`;
this.$http.get(path).then(res => {
const dms = res.data && res.data;
this.dms = {
reference: dms.reference,
warehouseId: dms.warehouseFk,
companyId: dms.companyFk,
dmsTypeId: dms.dmsTypeFk,
description: dms.description,
hasFile: dms.hasFile,
const thermograph = res.data && res.data;
this.thermograph = {
thermographId: thermograph.thermographFk,
state: thermograph.result,
reference: thermograph.dms.reference,
warehouseId: thermograph.dms.warehouseFk,
companyId: thermograph.dms.companyFk,
dmsTypeId: thermograph.dms.dmsTypeFk,
description: thermograph.dms.description,
hasFile: thermograph.dms.hasFile,
hasFileAttached: false,
files: []
};
@ -47,11 +51,11 @@ class Controller extends Component {
}
onSubmit() {
const query = `dms/${this.$params.dmsId}/updateFile`;
const query = `travels/${this.$params.id}/updateThermograph`;
const options = {
method: 'POST',
url: query,
params: this.dms,
params: this.thermograph,
headers: {
'Content-Type': undefined
},
@ -63,16 +67,26 @@ class Controller extends Component {
return formData;
},
data: this.dms.files
data: this.thermograph.files
};
this.$http(options).then(res => {
if (res) {
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
this.$.watcher.updateOriginalData();
this.$state.go('worker.card.dms.index');
this.$state.go('travel.card.thermograph.index');
}
});
}
onFileChange(files) {
let hasFileAttached = false;
if (files.length > 0)
hasFileAttached = true;
this.$.$applyAsync(() => {
this.thermograph.hasFileAttached = hasFileAttached;
});
}
}
ngModule.component('vnTravelThermographEdit', {

View File

@ -1,78 +1,87 @@
import './index';
import watcher from 'core/mocks/watcher.js';
describe('Worker', () => {
describe('Component vnClientDmsEdit', () => {
describe('Component vnTravelThermographEdit', () => {
let controller;
let $scope;
let $element;
let $httpBackend;
let $httpParamSerializer;
beforeEach(ngModule('worker'));
beforeEach(ngModule('travel'));
beforeEach(angular.mock.inject(($componentController, $rootScope, _$httpBackend_) => {
beforeEach(angular.mock.inject(($componentController, $rootScope, _$httpBackend_, _$httpParamSerializer_) => {
$scope = $rootScope.$new();
$httpBackend = _$httpBackend_;
$element = angular.element(`<vn-worker-dms-edit></vn-worker-dms-edit`);
controller = $componentController('vnWorkerDmsEdit', {$element, $scope});
controller._worker = {id: 106};
controller.$params = {dmsId: 4};
$httpParamSerializer = _$httpParamSerializer_;
$element = angular.element(`<vn-travel-thermograph-edit></vn-travel-thermograph-edit`);
controller = $componentController('vnTravelThermographEdit', {$element, $scope});
controller._travel = {id: 3};
controller.$params = {id: 3, thermographId: 6};
controller.$.watcher = watcher;
}));
describe('worker() setter', () => {
it('should set the worker data and then call setDefaultParams() and getAllowedContentTypes()', () => {
describe('travel() setter', () => {
it('should set the travel data and then call setDefaultParams() and getAllowedContentTypes()', () => {
jest.spyOn(controller, 'setDefaultParams');
jest.spyOn(controller, 'getAllowedContentTypes');
controller._worker = undefined;
controller.worker = {
id: 106
controller._travel = undefined;
controller.travel = {
id: 3
};
expect(controller.setDefaultParams).toHaveBeenCalledWith();
expect(controller.worker).toBeDefined();
expect(controller.travel).toBeDefined();
expect(controller.getAllowedContentTypes).toHaveBeenCalledWith();
});
});
describe('setDefaultParams()', () => {
it('should perform a GET query and define the dms property on controller', () => {
const dmsId = 4;
const thermographId = 6;
const expectedResponse = {
reference: 101,
warehouseFk: 1,
companyFk: 442,
dmsTypeFk: 3,
description: 'Test',
hasFile: false,
hasFileAttached: false
thermographFk: 6,
result: 'Ok',
dms: {
reference: '123456-01',
warehouseFk: 1,
companyFk: 442,
dmsTypeFk: 3,
description: 'Test'
}
};
$httpBackend.when('GET', `Dms/${dmsId}`).respond(expectedResponse);
$httpBackend.expect('GET', `Dms/${dmsId}`).respond(expectedResponse);
const filterObj = {include: {relation: 'dms'}};
const filter = encodeURIComponent(JSON.stringify(filterObj));
const query = `TravelThermographs/${thermographId}?filter=${filter}`;
$httpBackend.expect('GET', query).respond(expectedResponse);
controller.setDefaultParams();
$httpBackend.flush();
expect(controller.dms).toBeDefined();
expect(controller.dms.reference).toEqual(101);
expect(controller.dms.dmsTypeId).toEqual(3);
expect(controller.thermograph).toBeDefined();
expect(controller.thermograph.reference).toEqual('123456-01');
expect(controller.thermograph.dmsTypeId).toEqual(3);
expect(controller.thermograph.state).toEqual('Ok');
});
});
describe('onFileChange()', () => {
it('should set dms hasFileAttached property to true if has any files', () => {
const files = [{id: 1, name: 'MyFile'}];
controller.dms = {hasFileAttached: false};
controller.thermograph = {hasFileAttached: false};
controller.onFileChange(files);
$scope.$apply();
expect(controller.dms.hasFileAttached).toBeTruthy();
expect(controller.thermograph.hasFileAttached).toBeTruthy();
});
});
describe('getAllowedContentTypes()', () => {
it('should make an HTTP GET request to get the allowed content types', () => {
const expectedResponse = ['image/png', 'image/jpg'];
$httpBackend.when('GET', `WorkerDms/allowedContentTypes`).respond(expectedResponse);
$httpBackend.expect('GET', `WorkerDms/allowedContentTypes`);
$httpBackend.when('GET', `TravelThermographs/allowedContentTypes`).respond(expectedResponse);
$httpBackend.expect('GET', `TravelThermographs/allowedContentTypes`);
controller.getAllowedContentTypes();
$httpBackend.flush();
@ -80,5 +89,34 @@ describe('Worker', () => {
expect(controller.allowedContentTypes).toEqual('image/png, image/jpg');
});
});
describe('contentTypesInfo()', () => {
it('should return a description with a list of allowed content types', () => {
controller.allowedContentTypes = ['image/png', 'image/jpg'];
const expectedTypes = controller.allowedContentTypes.join(', ');
const expectedResult = `Allowed content types: ${expectedTypes}`;
jest.spyOn(controller.$translate, 'instant').mockReturnValue(expectedResult);
const result = controller.contentTypesInfo;
expect(result).toEqual(expectedResult);
});
});
describe('onSubmit()', () => {
it('should make an HTTP POST request to save the form data', () => {
jest.spyOn(controller.$.watcher, 'updateOriginalData');
const files = [{id: 1, name: 'MyFile'}];
controller.thermograph = {files};
const serializedParams = $httpParamSerializer(controller.thermograph);
const query = `travels/${controller.$params.id}/updateThermograph?${serializedParams}`;
$httpBackend.expect('POST', query).respond({});
controller.onSubmit();
$httpBackend.flush();
});
});
});
});

View File

@ -23,11 +23,11 @@
</vn-thead>
<vn-tbody>
<vn-tr ng-repeat="thermograph in $ctrl.travelThermographs">
<vn-td>{{thermograph.thermographFk}} </vn-td>
<vn-td>{{thermograph.temperature}} </vn-td>
<vn-td expand>{{thermograph.result}}</vn-td>
<vn-td>{{thermograph.warehouse.name}}</vn-td>
<vn-td>{{thermograph.created | date: 'dd/MM/yyyy'}}</vn-td>
<vn-td>{{::thermograph.thermographFk}} </vn-td>
<vn-td>{{::thermograph.temperature}} </vn-td>
<vn-td expand>{{::thermograph.result}}</vn-td>
<vn-td>{{::thermograph.warehouse.name}}</vn-td>
<vn-td>{{::thermograph.created | date: 'dd/MM/yyyy'}}</vn-td>
<vn-td shrink>
<a target="_blank"
href="api/dms/{{::thermograph.dmsFk}}/downloadFile?access_token={{::$ctrl.accessToken}}">
@ -38,7 +38,7 @@
</a>
</vn-td>
<vn-td shrink>
<vn-icon-button ui-sref="travel.card.thermograph.edit({dmsId: {{::thermograph.dmsFk}}})"
<vn-icon-button ui-sref="travel.card.thermograph.edit({thermographId: {{::thermograph.id}}})"
icon="edit"
title="{{'Edit file' | translate}}">
</vn-icon-button>

View File

@ -39,11 +39,6 @@
{{::document.dms.description}}
</span>
</vn-td>
<vn-td shrink>
<vn-check disabled="true"
ng-model="document.dms.hasFile">
</vn-check>
</vn-td>
<vn-td shrink>
<a target="_blank"
title="{{'Download file' | translate}}"