1762-worker_dms #31
|
@ -63,7 +63,7 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const hasWriteRole = await models.DmsType.hasWriteRole(ctx, args.dmsTypeId);
|
const hasWriteRole = await models.DmsType.hasWriteRole(ctx, args.dmsTypeId, myOptions);
|
||||||
if (!hasWriteRole)
|
if (!hasWriteRole)
|
||||||
throw new UserError(`You don't have enough privileges`);
|
throw new UserError(`You don't have enough privileges`);
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ module.exports = Self => {
|
||||||
const originPath = `${tempContainer.client.root}/${tempContainer.name}/${file.name}`;
|
const originPath = `${tempContainer.client.root}/${tempContainer.name}/${file.name}`;
|
||||||
const destinationPath = `${container.client.root}/${pathHash}/${newDms.file}`;
|
const destinationPath = `${container.client.root}/${pathHash}/${newDms.file}`;
|
||||||
|
|
||||||
fs.rename(originPath, destinationPath);
|
await fs.rename(originPath, destinationPath);
|
||||||
|
|
||||||
addedDms.push(newDms);
|
addedDms.push(newDms);
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,8 +60,8 @@ module.exports = Self => {
|
||||||
* @param {String} name The role name
|
* @param {String} name The role name
|
||||||
* @return {Boolean} %true if user has the role, %false otherwise
|
* @return {Boolean} %true if user has the role, %false otherwise
|
||||||
*/
|
*/
|
||||||
Self.hasRole = async function(userId, name) {
|
Self.hasRole = async function(userId, name, options) {
|
||||||
let roles = await Self.getRoles(userId);
|
let roles = await Self.getRoles(userId, options);
|
||||||
return roles.some(role => role == name);
|
return roles.some(role => role == name);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -71,13 +71,13 @@ module.exports = Self => {
|
||||||
* @param {Integer} userId The user id
|
* @param {Integer} userId The user id
|
||||||
* @return {Object} User role list
|
* @return {Object} User role list
|
||||||
*/
|
*/
|
||||||
Self.getRoles = async userId => {
|
Self.getRoles = async(userId, options) => {
|
||||||
let result = await Self.rawSql(
|
let result = await Self.rawSql(
|
||||||
`SELECT r.name
|
`SELECT r.name
|
||||||
FROM account.user u
|
FROM account.user u
|
||||||
JOIN account.roleRole rr ON rr.role = u.role
|
JOIN account.roleRole rr ON rr.role = u.role
|
||||||
JOIN account.role r ON r.id = rr.inheritsFrom
|
JOIN account.role r ON r.id = rr.inheritsFrom
|
||||||
WHERE u.id = ?`, [userId]);
|
WHERE u.id = ?`, [userId], options);
|
||||||
|
|
||||||
let roles = [];
|
let roles = [];
|
||||||
for (role of result)
|
for (role of result)
|
||||||
|
|
|
@ -5,17 +5,18 @@ module.exports = Self => {
|
||||||
*
|
*
|
||||||
* @param {Object} ctx - Request context
|
* @param {Object} ctx - Request context
|
||||||
* @param {Interger} id - DmsType id
|
* @param {Interger} id - DmsType id
|
||||||
|
* @param {Object} options - Query options
|
||||||
* @return {Boolean} True for user with read privileges
|
* @return {Boolean} True for user with read privileges
|
||||||
*/
|
*/
|
||||||
Self.hasReadRole = async(ctx, id) => {
|
Self.hasReadRole = async(ctx, id, options) => {
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const dmsType = await models.DmsType.findById(id, {
|
const dmsType = await models.DmsType.findById(id, {
|
||||||
include: {
|
include: {
|
||||||
relation: 'readRole'
|
relation: 'readRole'
|
||||||
}
|
}
|
||||||
});
|
}, options);
|
||||||
|
|
||||||
return await hasRole(ctx, dmsType);
|
return await hasRole(ctx, dmsType, options);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,17 +25,18 @@ module.exports = Self => {
|
||||||
*
|
*
|
||||||
* @param {Object} ctx - Request context
|
* @param {Object} ctx - Request context
|
||||||
* @param {Interger} id - DmsType id
|
* @param {Interger} id - DmsType id
|
||||||
|
* @param {Object} options - Query options
|
||||||
* @return {Boolean} True for user with write privileges
|
* @return {Boolean} True for user with write privileges
|
||||||
*/
|
*/
|
||||||
Self.hasWriteRole = async(ctx, id) => {
|
Self.hasWriteRole = async(ctx, id, options) => {
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const dmsType = await models.DmsType.findById(id, {
|
const dmsType = await models.DmsType.findById(id, {
|
||||||
include: {
|
include: {
|
||||||
relation: 'writeRole'
|
relation: 'writeRole'
|
||||||
}
|
}
|
||||||
});
|
}, options);
|
||||||
|
|
||||||
return await hasRole(ctx, dmsType);
|
return await hasRole(ctx, dmsType, options);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -42,8 +44,9 @@ module.exports = Self => {
|
||||||
* read or write privileges
|
* read or write privileges
|
||||||
* @param {Object} ctx - Context
|
* @param {Object} ctx - Context
|
||||||
* @param {Object} dmsType - Dms type [read/write]
|
* @param {Object} dmsType - Dms type [read/write]
|
||||||
|
* @param {Object} options - Query options
|
||||||
*/
|
*/
|
||||||
async function hasRole(ctx, dmsType) {
|
async function hasRole(ctx, dmsType, options) {
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const myUserId = ctx.req.accessToken.userId;
|
const myUserId = ctx.req.accessToken.userId;
|
||||||
|
|
||||||
|
@ -51,8 +54,8 @@ module.exports = Self => {
|
||||||
const writeRole = dmsType.writeRole() && dmsType.writeRole().name;
|
const writeRole = dmsType.writeRole() && dmsType.writeRole().name;
|
||||||
const requiredRole = readRole || writeRole;
|
const requiredRole = readRole || writeRole;
|
||||||
|
|
||||||
const hasRequiredRole = await models.Account.hasRole(myUserId, requiredRole);
|
const hasRequiredRole = await models.Account.hasRole(myUserId, requiredRole, options);
|
||||||
const isRoot = await models.Account.hasRole(myUserId, 'root');
|
const isRoot = await models.Account.hasRole(myUserId, 'root', options);
|
||||||
|
|
||||||
if (isRoot || hasRequiredRole)
|
if (isRoot || hasRequiredRole)
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1869,7 +1869,8 @@ INSERT INTO `vn`.`dms`(`id`, `dmsTypeFk`, `file`, `contentType`, `workerFk`, `wa
|
||||||
VALUES
|
VALUES
|
||||||
(1, 14, '1.txt', 'text/plain', 5, 1, 442, NULL, FALSE, 'Ticket:11', 'Ticket:11 dms for the ticket', CURDATE()),
|
(1, 14, '1.txt', 'text/plain', 5, 1, 442, NULL, FALSE, 'Ticket:11', 'Ticket:11 dms for the ticket', CURDATE()),
|
||||||
(2, 5, '2.txt', 'text/plain', 5, 1, 442, 1, TRUE, 'Client:104', 'Client:104 dms for the client', CURDATE()),
|
(2, 5, '2.txt', 'text/plain', 5, 1, 442, 1, TRUE, 'Client:104', 'Client:104 dms for the client', CURDATE()),
|
||||||
(3, 5, '3.txt', 'text/plain', 5, 1, 442, NULL, TRUE, 'Client: 104', 'Client:104 readme', CURDATE());
|
(3, 5, '3.txt', 'text/plain', 5, 1, 442, NULL, TRUE, 'Client: 104', 'Client:104 readme', CURDATE()),
|
||||||
|
(4, 3, '3.txt', 'text/plain', 5, 1, 442, NULL, TRUE, 'Worker: 106', 'Worker:106 readme', CURDATE());
|
||||||
|
|
||||||
INSERT INTO `vn`.`ticketDms`(`ticketFk`, `dmsFk`)
|
INSERT INTO `vn`.`ticketDms`(`ticketFk`, `dmsFk`)
|
||||||
VALUES
|
VALUES
|
||||||
|
@ -1880,6 +1881,10 @@ INSERT INTO `vn`.`clientDms`(`clientFk`, `dmsFk`)
|
||||||
(104, 2),
|
(104, 2),
|
||||||
(104, 3);
|
(104, 3);
|
||||||
|
|
||||||
|
INSERT INTO `vn`.`workerDocument`(`id`, `worker`, `document`)
|
||||||
|
VALUES
|
||||||
|
(1, 106, 4);
|
||||||
|
|
||||||
INSERT INTO `vn`.`device` (`sn`, `model`, `userFk`)
|
INSERT INTO `vn`.`device` (`sn`, `model`, `userFk`)
|
||||||
VALUES
|
VALUES
|
||||||
('aaa', 'android', '9');
|
('aaa', 'android', '9');
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('removeFile', {
|
Self.remoteMethodCtx('removeFile', {
|
||||||
description: 'Removes a ticket document',
|
description: 'Removes a claim document',
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
accepts: {
|
accepts: {
|
||||||
arg: 'id',
|
arg: 'id',
|
||||||
|
|
|
@ -20,7 +20,7 @@ module.exports = Self => {
|
||||||
|
|
||||||
Self.removeFile = async(ctx, id) => {
|
Self.removeFile = async(ctx, id) => {
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const clientDms = await models.ClientDms.findById(id);
|
const clientDms = await Self.findById(id);
|
||||||
|
|
||||||
await models.Dms.removeFile(ctx, clientDms.dmsFk);
|
await models.Dms.removeFile(ctx, clientDms.dmsFk);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('allowedContentTypes', {
|
||||||
|
description: 'Returns a list of allowed contentTypes',
|
||||||
|
accessType: 'READ',
|
||||||
|
returns: {
|
||||||
|
type: ['Object'],
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/allowedContentTypes`,
|
||||||
|
verb: 'GET'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.allowedContentTypes = async() => {
|
||||||
|
const storageConnector = Self.app.dataSources.storage.connector;
|
||||||
|
const allowedContentTypes = storageConnector.allowedContentTypes;
|
||||||
|
const modelAllowedContentTypes = Self.definition.settings.allowedContentTypes;
|
||||||
|
|
||||||
|
return modelAllowedContentTypes || allowedContentTypes;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('removeFile', {
|
||||||
|
description: 'Removes a worker document',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
accepts: {
|
||||||
|
arg: 'id',
|
||||||
|
type: 'Number',
|
||||||
|
description: 'The document id',
|
||||||
|
http: {source: 'path'}
|
||||||
|
},
|
||||||
|
returns: {
|
||||||
|
type: 'Object',
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/:id/removeFile`,
|
||||||
|
verb: 'POST'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.removeFile = async(ctx, id) => {
|
||||||
|
const models = Self.app.models;
|
||||||
|
const workerDms = await Self.findById(id);
|
||||||
|
|
||||||
|
await models.Dms.removeFile(ctx, workerDms.dmsFk);
|
||||||
|
|
||||||
|
return workerDms.destroy();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
const app = require('vn-loopback/server/server');
|
||||||
|
|
||||||
|
describe('WorkerDms removeFile()', () => {
|
||||||
|
const workerDmsFk = 1;
|
||||||
|
it(`should return an error for a user without enough privileges`, async() => {
|
||||||
|
let clientId = 101;
|
||||||
|
let ctx = {req: {accessToken: {userId: clientId}}};
|
||||||
|
|
||||||
|
let error;
|
||||||
|
await app.models.WorkerDms.removeFile(ctx, workerDmsFk).catch(e => {
|
||||||
|
error = e;
|
||||||
|
}).finally(() => {
|
||||||
|
expect(error.message).toEqual(`You don't have enough privileges`);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(error).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,19 @@
|
||||||
|
const app = require('vn-loopback/server/server');
|
||||||
|
|
||||||
|
describe('Worker uploadFile()', () => {
|
||||||
|
it(`should return an error for a user without enough privileges`, async() => {
|
||||||
|
let workerId = 106;
|
||||||
|
let currentUserId = 102;
|
||||||
|
let hhrrDataId = 3;
|
||||||
|
let ctx = {req: {accessToken: {userId: currentUserId}}, args: {dmsTypeId: hhrrDataId}};
|
||||||
|
|
||||||
|
let error;
|
||||||
|
await app.models.Worker.uploadFile(ctx, workerId).catch(e => {
|
||||||
|
error = e;
|
||||||
|
}).finally(() => {
|
||||||
|
expect(error.message).toEqual(`You don't have enough privileges`);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(error).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,76 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('uploadFile', {
|
||||||
|
description: 'Upload and attach a file to a client',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
accepts: [{
|
||||||
|
arg: 'id',
|
||||||
|
type: 'Number',
|
||||||
|
description: 'The worker id',
|
||||||
|
http: {source: 'path'}
|
||||||
|
}, {
|
||||||
|
arg: 'warehouseId',
|
||||||
|
type: 'Number',
|
||||||
|
description: 'The warehouse id',
|
||||||
|
required: true
|
||||||
|
}, {
|
||||||
|
arg: 'companyId',
|
||||||
|
type: 'Number',
|
||||||
|
description: 'The company id',
|
||||||
|
required: true
|
||||||
|
}, {
|
||||||
|
arg: 'dmsTypeId',
|
||||||
|
type: 'Number',
|
||||||
|
description: 'The dms type id',
|
||||||
|
required: true
|
||||||
|
}, {
|
||||||
|
arg: 'reference',
|
||||||
|
type: 'String',
|
||||||
|
required: true
|
||||||
|
}, {
|
||||||
|
arg: 'description',
|
||||||
|
type: 'String',
|
||||||
|
required: true
|
||||||
|
}, {
|
||||||
|
arg: 'hasFile',
|
||||||
|
type: 'Boolean',
|
||||||
|
description: 'True if has an attached file',
|
||||||
|
required: true
|
||||||
|
}],
|
||||||
|
returns: {
|
||||||
|
type: 'Object',
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/:id/uploadFile`,
|
||||||
|
verb: 'POST'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.uploadFile = async(ctx, id) => {
|
||||||
|
const models = Self.app.models;
|
||||||
|
const promises = [];
|
||||||
|
const tx = await Self.beginTransaction({});
|
||||||
|
|
||||||
|
try {
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
const uploadedFiles = await models.Dms.uploadFile(ctx, options);
|
||||||
|
uploadedFiles.forEach(dms => {
|
||||||
|
const newWorkerDms = models.WorkerDms.create({
|
||||||
|
workerFk: id,
|
||||||
|
dmsFk: dms.id
|
||||||
|
}, options);
|
||||||
|
|
||||||
|
promises.push(newWorkerDms);
|
||||||
|
});
|
||||||
|
const resolvedPromises = await Promise.all(promises);
|
||||||
|
|
||||||
|
await tx.commit();
|
||||||
|
|
||||||
|
return resolvedPromises;
|
||||||
|
} catch (err) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
|
@ -20,6 +20,9 @@
|
||||||
"WorkCenterHoliday": {
|
"WorkCenterHoliday": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
"WorkerDms": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
"Worker": {
|
"Worker": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
require('../methods/worker-dms/removeFile')(Self);
|
||||||
|
require('../methods/worker-dms/allowedContentTypes')(Self);
|
||||||
|
};
|
|
@ -0,0 +1,47 @@
|
||||||
|
{
|
||||||
|
"name": "WorkerDms",
|
||||||
|
"base": "Loggable",
|
||||||
|
"log": {
|
||||||
|
"model":"ClientLog",
|
||||||
|
"relation": "worker",
|
||||||
|
"showField": "dmsFk"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "workerDocument"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "Number",
|
||||||
|
"id": true
|
||||||
|
},
|
||||||
|
"dmsFk": {
|
||||||
|
"type": "Number",
|
||||||
|
"required": true,
|
||||||
|
"mysql": {
|
||||||
|
"columnName": "document"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"workerFk": {
|
||||||
|
"type": "Number",
|
||||||
|
"required": true,
|
||||||
|
"mysql": {
|
||||||
|
"columnName": "worker"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"relations": {
|
||||||
|
"worker": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Worker",
|
||||||
|
"foreignKey": "workerFk"
|
||||||
|
},
|
||||||
|
"dms": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Dms",
|
||||||
|
"foreignKey": "dmsFk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3,4 +3,5 @@ module.exports = Self => {
|
||||||
require('../methods/worker/mySubordinates')(Self);
|
require('../methods/worker/mySubordinates')(Self);
|
||||||
require('../methods/worker/isSubordinate')(Self);
|
require('../methods/worker/isSubordinate')(Self);
|
||||||
require('../methods/worker/getWorkedHours')(Self);
|
require('../methods/worker/getWorkedHours')(Self);
|
||||||
|
require('../methods/worker/uploadFile')(Self);
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
<mg-ajax path="dms/upload" options="vnPost"></mg-ajax>
|
||||||
|
<vn-watcher
|
||||||
|
vn-id="watcher"
|
||||||
|
data="$ctrl.dms">
|
||||||
|
</vn-watcher>
|
||||||
|
<form
|
||||||
|
name="form"
|
||||||
|
ng-submit="$ctrl.onSubmit()"
|
||||||
|
class="vn-ma-md"
|
||||||
|
enctype="multipart/form-data">
|
||||||
|
<div class="vn-w-md">
|
||||||
|
<vn-card class="vn-pa-lg">
|
||||||
|
<vn-horizontal>
|
||||||
|
<vn-textfield
|
||||||
|
vn-one
|
||||||
|
vn-focus
|
||||||
|
label="Reference"
|
||||||
|
ng-model="$ctrl.dms.reference"
|
||||||
|
rule>
|
||||||
|
</vn-textfield>
|
||||||
|
<vn-autocomplete vn-one
|
||||||
|
label="Company"
|
||||||
|
ng-model="$ctrl.dms.companyId"
|
||||||
|
url="Companies"
|
||||||
|
show-field="code"
|
||||||
|
value-field="id">
|
||||||
|
</vn-autocomplete>
|
||||||
|
</vn-horizontal>
|
||||||
|
<vn-horizontal>
|
||||||
|
<vn-autocomplete vn-one
|
||||||
|
label="Warehouse"
|
||||||
|
ng-model="$ctrl.dms.warehouseId"
|
||||||
|
url="Warehouses"
|
||||||
|
show-field="name"
|
||||||
|
value-field="id">
|
||||||
|
</vn-autocomplete>
|
||||||
|
<vn-autocomplete vn-one
|
||||||
|
label="Type"
|
||||||
|
ng-model="$ctrl.dms.dmsTypeId"
|
||||||
|
url="DmsTypes"
|
||||||
|
show-field="name"
|
||||||
|
value-field="id">
|
||||||
|
</vn-autocomplete>
|
||||||
|
</vn-horizontal>
|
||||||
|
<vn-horizontal>
|
||||||
|
<vn-textarea
|
||||||
|
vn-one
|
||||||
|
label="Description"
|
||||||
|
ng-model="$ctrl.dms.description"
|
||||||
|
rule>
|
||||||
|
</vn-textarea>
|
||||||
|
</vn-horizontal>
|
||||||
|
<vn-horizontal>
|
||||||
|
<vn-input-file
|
||||||
|
vn-one
|
||||||
|
label="File"
|
||||||
|
ng-model="$ctrl.dms.files"
|
||||||
|
on-change="$ctrl.onFileChange($files)"
|
||||||
|
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>
|
||||||
|
<vn-check
|
||||||
|
label="Generate identifier for original file"
|
||||||
|
ng-model="$ctrl.dms.hasFile">
|
||||||
|
</vn-check>
|
||||||
|
</vn-vertical>
|
||||||
|
</vn-card>
|
||||||
|
<vn-button-bar>
|
||||||
|
<vn-submit label="Upload"></vn-submit>
|
||||||
|
<vn-button ui-sref="worker.card.dms.index" label="Cancel"></vn-button>
|
||||||
|
</vn-button-bar>
|
||||||
|
</div>
|
||||||
|
</form>
|
|
@ -0,0 +1,114 @@
|
||||||
|
import ngModule from '../../module';
|
||||||
|
import Component from 'core/lib/component';
|
||||||
|
import './style.scss';
|
||||||
|
|
||||||
|
class Controller extends Component {
|
||||||
|
constructor($element, $, vnConfig) {
|
||||||
|
super($element, $);
|
||||||
|
this.vnConfig = vnConfig;
|
||||||
|
this.dms = {
|
||||||
|
files: [],
|
||||||
|
hasFile: false,
|
||||||
|
hasFileAttached: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
get worker() {
|
||||||
|
return this._worker;
|
||||||
|
}
|
||||||
|
|
||||||
|
set worker(value) {
|
||||||
|
this._worker = value;
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
this.setDefaultParams();
|
||||||
|
this.getAllowedContentTypes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getAllowedContentTypes() {
|
||||||
|
this.$http.get('workerDms/allowedContentTypes').then(res => {
|
||||||
|
const contentTypes = res.data.join(', ');
|
||||||
|
this.allowedContentTypes = contentTypes;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
get contentTypesInfo() {
|
||||||
|
return this.$translate.instant('ContentTypesInfo', {
|
||||||
|
allowedContentTypes: this.allowedContentTypes
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setDefaultParams() {
|
||||||
|
const params = {filter: {
|
||||||
|
where: {code: 'hhrrData'}
|
||||||
|
}};
|
||||||
|
this.$http.get('DmsTypes/findOne', {params}).then(res => {
|
||||||
|
const dmsType = res.data && res.data;
|
||||||
|
const companyId = this.vnConfig.companyFk;
|
||||||
|
const warehouseId = this.vnConfig.warehouseFk;
|
||||||
|
const defaultParams = {
|
||||||
|
reference: this.worker.id,
|
||||||
|
warehouseId: warehouseId,
|
||||||
|
companyId: companyId,
|
||||||
|
dmsTypeId: dmsType.id,
|
||||||
|
description: this.$translate.instant('WorkerFileDescription', {
|
||||||
|
dmsTypeName: dmsType.name,
|
||||||
|
workerId: this.worker.id,
|
||||||
|
workerName: this.worker.name
|
||||||
|
}).toUpperCase()
|
||||||
|
};
|
||||||
|
|
||||||
|
this.dms = Object.assign(this.dms, defaultParams);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubmit() {
|
||||||
|
const query = `Workers/${this.worker.id}/uploadFile`;
|
||||||
|
const options = {
|
||||||
|
method: 'POST',
|
||||||
|
url: query,
|
||||||
|
params: this.dms,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': undefined
|
||||||
|
},
|
||||||
|
transformRequest: files => {
|
||||||
|
const formData = new FormData();
|
||||||
|
|
||||||
|
for (let i = 0; i < files.length; i++)
|
||||||
|
formData.append(files[i].name, files[i]);
|
||||||
|
|
||||||
|
return formData;
|
||||||
|
},
|
||||||
|
data: this.dms.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');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onFileChange(files) {
|
||||||
|
let hasFileAttached = false;
|
||||||
|
|
||||||
|
if (files.length > 0)
|
||||||
|
hasFileAttached = true;
|
||||||
|
|
||||||
|
this.$.$applyAsync(() => {
|
||||||
|
this.dms.hasFileAttached = hasFileAttached;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Controller.$inject = ['$element', '$scope', 'vnConfig'];
|
||||||
|
|
||||||
|
ngModule.component('vnWorkerDmsCreate', {
|
||||||
|
template: require('./index.html'),
|
||||||
|
controller: Controller,
|
||||||
|
bindings: {
|
||||||
|
worker: '<'
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,77 @@
|
||||||
|
import './index';
|
||||||
|
|
||||||
|
describe('Client', () => {
|
||||||
|
describe('Component vnWorkerDmsCreate', () => {
|
||||||
|
let $element;
|
||||||
|
let controller;
|
||||||
|
let $scope;
|
||||||
|
let $httpBackend;
|
||||||
|
let $httpParamSerializer;
|
||||||
|
|
||||||
|
beforeEach(ngModule('worker'));
|
||||||
|
|
||||||
|
beforeEach(angular.mock.inject(($compile, $rootScope, _$httpBackend_, _$httpParamSerializer_) => {
|
||||||
|
$scope = $rootScope.$new();
|
||||||
|
$httpBackend = _$httpBackend_;
|
||||||
|
$httpParamSerializer = _$httpParamSerializer_;
|
||||||
|
$element = $compile(`<vn-worker-dms-create></vn-worker-dms-create>`)($rootScope);
|
||||||
|
controller = $element.controller('vnWorkerDmsCreate');
|
||||||
|
controller._worker = {id: 101, name: 'Bruce wayne'};
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('worker() setter', () => {
|
||||||
|
it('should set the worker data and then call setDefaultParams() and getAllowedContentTypes()', () => {
|
||||||
|
spyOn(controller, 'setDefaultParams');
|
||||||
|
spyOn(controller, 'getAllowedContentTypes');
|
||||||
|
controller.worker = {
|
||||||
|
id: 15,
|
||||||
|
name: 'Bruce wayne'
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(controller.worker).toBeDefined();
|
||||||
|
expect(controller.setDefaultParams).toHaveBeenCalledWith();
|
||||||
|
expect(controller.getAllowedContentTypes).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('setDefaultParams()', () => {
|
||||||
|
it('should perform a GET query and define the dms property on controller', () => {
|
||||||
|
$httpBackend.whenRoute('GET', `DmsTypes`).respond({id: 12, code: 'hhrrData'});
|
||||||
|
const params = {filter: {
|
||||||
|
where: {code: 'hhrrData'}
|
||||||
|
}};
|
||||||
|
let serializedParams = $httpParamSerializer(params);
|
||||||
|
$httpBackend.when('GET', `DmsTypes/findOne?${serializedParams}`).respond({id: 12, code: 'hhrrData'});
|
||||||
|
controller.setDefaultParams();
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.dms).toBeDefined();
|
||||||
|
expect(controller.dms.reference).toEqual(101);
|
||||||
|
expect(controller.dms.dmsTypeId).toEqual(12);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('onFileChange()', () => {
|
||||||
|
it('should set dms hasFileAttached property to true if has any files', () => {
|
||||||
|
const files = [{id: 1, name: 'MyFile'}];
|
||||||
|
controller.onFileChange(files);
|
||||||
|
$scope.$apply();
|
||||||
|
|
||||||
|
expect(controller.dms.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`);
|
||||||
|
controller.getAllowedContentTypes();
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.allowedContentTypes).toBeDefined();
|
||||||
|
expect(controller.allowedContentTypes).toEqual('image/png, image/jpg');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,7 @@
|
||||||
|
vn-ticket-request {
|
||||||
|
.vn-textfield {
|
||||||
|
margin: 0!important;
|
||||||
|
max-width: 100px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
<vn-watcher
|
||||||
|
vn-id="watcher"
|
||||||
|
data="$ctrl.dms">
|
||||||
|
</vn-watcher>
|
||||||
|
<form
|
||||||
|
name="form"
|
||||||
|
ng-submit="$ctrl.onSubmit()"
|
||||||
|
class="vn-ma-md"
|
||||||
|
enctype="multipart/form-data">
|
||||||
|
<div class="vn-w-md">
|
||||||
|
<vn-card class="vn-pa-lg">
|
||||||
|
<vn-horizontal>
|
||||||
|
<vn-textfield
|
||||||
|
vn-one
|
||||||
|
vn-focus
|
||||||
|
label="Reference"
|
||||||
|
ng-model="$ctrl.dms.reference"
|
||||||
|
rule>
|
||||||
|
</vn-textfield>
|
||||||
|
<vn-autocomplete vn-one required="true"
|
||||||
|
label="Company"
|
||||||
|
ng-model="$ctrl.dms.companyId"
|
||||||
|
url="Companies"
|
||||||
|
show-field="code"
|
||||||
|
value-field="id">
|
||||||
|
</vn-autocomplete>
|
||||||
|
</vn-horizontal>
|
||||||
|
<vn-horizontal>
|
||||||
|
<vn-autocomplete vn-one required="true"
|
||||||
|
label="Warehouse"
|
||||||
|
ng-model="$ctrl.dms.warehouseId"
|
||||||
|
url="Warehouses"
|
||||||
|
show-field="name"
|
||||||
|
value-field="id">
|
||||||
|
</vn-autocomplete>
|
||||||
|
<vn-autocomplete vn-one required="true"
|
||||||
|
label="Type"
|
||||||
|
ng-model="$ctrl.dms.dmsTypeId"
|
||||||
|
url="DmsTypes"
|
||||||
|
show-field="name"
|
||||||
|
value-field="id">
|
||||||
|
</vn-autocomplete>
|
||||||
|
</vn-horizontal>
|
||||||
|
<vn-horizontal>
|
||||||
|
<vn-textarea
|
||||||
|
vn-one
|
||||||
|
required="true"
|
||||||
|
label="Description"
|
||||||
|
ng-model="$ctrl.dms.description"
|
||||||
|
rule>
|
||||||
|
</vn-textarea>
|
||||||
|
</vn-horizontal>
|
||||||
|
<vn-horizontal>
|
||||||
|
<vn-input-file
|
||||||
|
vn-one
|
||||||
|
label="File"
|
||||||
|
ng-model="$ctrl.dms.files"
|
||||||
|
on-change="$ctrl.onFileChange($files)"
|
||||||
|
accept="{{$ctrl.allowedContentTypes}}"
|
||||||
|
multiple="true">
|
||||||
|
<append>
|
||||||
|
<vn-icon vn-none
|
||||||
|
color-marginal
|
||||||
|
title="{{$ctrl.contentTypesInfo}}"
|
||||||
|
icon="info">
|
||||||
|
</vn-icon>
|
||||||
|
</append>
|
||||||
|
</vn-input-file>
|
||||||
|
</vn-horizontal>
|
||||||
|
<vn-vertical>
|
||||||
|
<vn-check disabled="true"
|
||||||
|
label="Generate identifier for original file"
|
||||||
|
ng-model="$ctrl.dms.hasFile">
|
||||||
|
</vn-check>
|
||||||
|
</vn-vertical>
|
||||||
|
</vn-card>
|
||||||
|
<vn-button-bar>
|
||||||
|
<vn-submit label="Save"></vn-submit>
|
||||||
|
<vn-button ui-sref="worker.card.dms.index" label="Cancel"></vn-button>
|
||||||
|
</vn-button-bar>
|
||||||
|
</div>
|
||||||
|
</form>
|
|
@ -0,0 +1,94 @@
|
||||||
|
import ngModule from '../../module';
|
||||||
|
import Component from 'core/lib/component';
|
||||||
|
import './style.scss';
|
||||||
|
|
||||||
|
class Controller extends Component {
|
||||||
|
get worker() {
|
||||||
|
return this._worker;
|
||||||
|
}
|
||||||
|
|
||||||
|
set worker(value) {
|
||||||
|
this._worker = value;
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
this.setDefaultParams();
|
||||||
|
this.getAllowedContentTypes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getAllowedContentTypes() {
|
||||||
|
this.$http.get('WorkerDms/allowedContentTypes').then(res => {
|
||||||
|
const contentTypes = res.data.join(', ');
|
||||||
|
this.allowedContentTypes = contentTypes;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
get contentTypesInfo() {
|
||||||
|
return this.$translate.instant('ContentTypesInfo', {
|
||||||
|
allowedContentTypes: this.allowedContentTypes
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setDefaultParams() {
|
||||||
|
const path = `Dms/${this.$params.dmsId}`;
|
||||||
|
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,
|
||||||
|
hasFileAttached: false,
|
||||||
|
files: []
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubmit() {
|
||||||
|
const query = `dms/${this.$params.dmsId}/updateFile`;
|
||||||
|
const options = {
|
||||||
|
method: 'POST',
|
||||||
|
url: query,
|
||||||
|
params: this.dms,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': undefined
|
||||||
|
},
|
||||||
|
transformRequest: files => {
|
||||||
|
const formData = new FormData();
|
||||||
|
|
||||||
|
for (let i = 0; i < files.length; i++)
|
||||||
|
formData.append(files[i].name, files[i]);
|
||||||
|
|
||||||
|
return formData;
|
||||||
|
},
|
||||||
|
data: this.dms.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');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onFileChange(files) {
|
||||||
|
let hasFileAttached = false;
|
||||||
|
if (files.length > 0)
|
||||||
|
hasFileAttached = true;
|
||||||
|
|
||||||
|
this.$.$applyAsync(() => {
|
||||||
|
this.dms.hasFileAttached = hasFileAttached;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngModule.component('vnWorkerDmsEdit', {
|
||||||
|
template: require('./index.html'),
|
||||||
|
controller: Controller,
|
||||||
|
bindings: {
|
||||||
|
worker: '<'
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,84 @@
|
||||||
|
import './index';
|
||||||
|
|
||||||
|
describe('Worker', () => {
|
||||||
|
describe('Component vnClientDmsEdit', () => {
|
||||||
|
let controller;
|
||||||
|
let $scope;
|
||||||
|
let $element;
|
||||||
|
let $httpBackend;
|
||||||
|
|
||||||
|
beforeEach(ngModule('worker'));
|
||||||
|
|
||||||
|
beforeEach(angular.mock.inject(($componentController, $rootScope, _$httpBackend_) => {
|
||||||
|
$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};
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('worker() setter', () => {
|
||||||
|
it('should set the worker data and then call setDefaultParams() and getAllowedContentTypes()', () => {
|
||||||
|
spyOn(controller, 'setDefaultParams');
|
||||||
|
spyOn(controller, 'getAllowedContentTypes');
|
||||||
|
controller._worker = undefined;
|
||||||
|
controller.worker = {
|
||||||
|
id: 106
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(controller.setDefaultParams).toHaveBeenCalledWith();
|
||||||
|
expect(controller.worker).toBeDefined();
|
||||||
|
expect(controller.getAllowedContentTypes).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('setDefaultParams()', () => {
|
||||||
|
it('should perform a GET query and define the dms property on controller', () => {
|
||||||
|
const dmsId = 4;
|
||||||
|
const expectedResponse = {
|
||||||
|
reference: 101,
|
||||||
|
warehouseFk: 1,
|
||||||
|
companyFk: 442,
|
||||||
|
dmsTypeFk: 3,
|
||||||
|
description: 'Test',
|
||||||
|
hasFile: false,
|
||||||
|
hasFileAttached: false
|
||||||
|
};
|
||||||
|
|
||||||
|
$httpBackend.when('GET', `Dms/${dmsId}`).respond(expectedResponse);
|
||||||
|
$httpBackend.expect('GET', `Dms/${dmsId}`).respond(expectedResponse);
|
||||||
|
controller.setDefaultParams();
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.dms).toBeDefined();
|
||||||
|
expect(controller.dms.reference).toEqual(101);
|
||||||
|
expect(controller.dms.dmsTypeId).toEqual(3);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
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.onFileChange(files);
|
||||||
|
$scope.$apply();
|
||||||
|
|
||||||
|
expect(controller.dms.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`);
|
||||||
|
controller.getAllowedContentTypes();
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.allowedContentTypes).toBeDefined();
|
||||||
|
expect(controller.allowedContentTypes).toEqual('image/png, image/jpg');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,7 @@
|
||||||
|
vn-ticket-request {
|
||||||
|
.vn-textfield {
|
||||||
|
margin: 0!important;
|
||||||
|
max-width: 100px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,117 @@
|
||||||
|
<vn-crud-model
|
||||||
|
vn-id="model"
|
||||||
|
url="WorkerDms"
|
||||||
|
link="{workerFk: $ctrl.$params.id}"
|
||||||
|
filter="::$ctrl.filter"
|
||||||
|
limit="20"
|
||||||
|
data="$ctrl.workerDms"
|
||||||
|
order="dmsFk DESC"
|
||||||
|
auto-load="true">
|
||||||
|
</vn-crud-model>
|
||||||
|
<vn-data-viewer
|
||||||
|
model="model"
|
||||||
|
class="vn-w-lg">
|
||||||
|
<vn-card>
|
||||||
|
<vn-table model="model">
|
||||||
|
<vn-thead>
|
||||||
|
<vn-tr>
|
||||||
|
<vn-th field="dmsFk" shrink>Id</vn-th>
|
||||||
|
<vn-th field="dmsTypeFk" shrink>Type</vn-th>
|
||||||
|
<vn-th field="hardCopyNumber" shrink number>Order</vn-th>
|
||||||
|
<vn-th field="reference" shrink>Reference</vn-th>
|
||||||
|
<vn-th expand>Description</vn-th>
|
||||||
|
<vn-th field="hasFile" shrink>Original</vn-th>
|
||||||
|
<vn-th shrink>File</vn-th>
|
||||||
|
<vn-th shrink>Employee</vn-th>
|
||||||
|
<vn-th field="created">Created</vn-th>
|
||||||
|
<vn-th shrink></vn-th>
|
||||||
|
<vn-th shrink></vn-th>
|
||||||
|
<vn-th shrink></vn-th>
|
||||||
|
</vn-tr>
|
||||||
|
</vn-thead>
|
||||||
|
<vn-tbody>
|
||||||
|
<vn-tr ng-repeat="document in $ctrl.workerDms">
|
||||||
|
<vn-td number shrink>{{::document.dmsFk}}</vn-td>
|
||||||
|
<vn-td shrink>
|
||||||
|
<span title="{{::document.dms.dmsType.name}}">
|
||||||
|
{{::document.dms.dmsType.name}}
|
||||||
|
</span>
|
||||||
|
</vn-td>
|
||||||
|
<vn-td shrink number>
|
||||||
|
<span class="chip" title="{{::document.dms.hardCopyNumber}}"
|
||||||
|
ng-class="{'message': document.dms.hardCopyNumber}">
|
||||||
|
{{::document.dms.hardCopyNumber}}
|
||||||
|
</span>
|
||||||
|
</vn-td>
|
||||||
|
<vn-td shrink>
|
||||||
|
<span title="{{::document.dms.reference}}">
|
||||||
|
{{::document.dms.reference}}
|
||||||
|
</span>
|
||||||
|
</vn-td>
|
||||||
|
<vn-td expand>
|
||||||
|
<span title="{{::document.dms.description}}">
|
||||||
|
{{::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}}"
|
||||||
|
href="api/dms/{{::document.dmsFk}}/downloadFile?access_token={{::$ctrl.accessToken}}">{{::document.dms.file}}
|
||||||
|
</a>
|
||||||
|
</vn-td>
|
||||||
|
<vn-td shrink>
|
||||||
|
<span class="link"
|
||||||
|
ng-click="$ctrl.showWorkerDescriptor($event, document.dms.workerFk)">
|
||||||
|
{{::document.dms.worker.user.nickname | dashIfEmpty}}
|
||||||
|
</span></vn-td>
|
||||||
|
<vn-td>
|
||||||
|
{{::document.dms.created | date:'dd/MM/yyyy HH:mm'}}
|
||||||
|
</vn-td>
|
||||||
|
<vn-td shrink>
|
||||||
|
<a target="_blank"
|
||||||
|
href="api/dms/{{::document.dmsFk}}/downloadFile?access_token={{::$ctrl.accessToken}}">
|
||||||
|
<vn-icon-button
|
||||||
|
icon="cloud_download"
|
||||||
|
title="{{'Download file' | translate}}">
|
||||||
|
</vn-icon-button>
|
||||||
|
</a>
|
||||||
|
</vn-td>
|
||||||
|
<vn-td shrink>
|
||||||
|
<vn-icon-button ui-sref="worker.card.dms.edit({dmsId: {{::document.dmsFk}}})"
|
||||||
|
icon="edit"
|
||||||
|
title="{{'Edit file' | translate}}">
|
||||||
|
</vn-icon-button>
|
||||||
|
</vn-td>
|
||||||
|
<vn-td shrink>
|
||||||
|
<vn-icon-button
|
||||||
|
icon="delete"
|
||||||
|
ng-click="$ctrl.showDeleteConfirm($index)"
|
||||||
|
title="{{'Remove file' | translate}}"
|
||||||
|
tabindex="-1">
|
||||||
|
</vn-icon-button>
|
||||||
|
</vn-td>
|
||||||
|
</vn-tr>
|
||||||
|
</vn-tbody>
|
||||||
|
</vn-table>
|
||||||
|
</vn-card>
|
||||||
|
</vn-data-viewer>
|
||||||
|
<vn-worker-descriptor-popover
|
||||||
|
vn-id="workerDescriptor">
|
||||||
|
</vn-worker-descriptor-popover>
|
||||||
|
<a ui-sref="worker.card.dms.create"
|
||||||
|
vn-tooltip="Upload file"
|
||||||
|
vn-bind="+"
|
||||||
|
fixed-bottom-right>
|
||||||
|
<vn-float-button icon="add"></vn-float-button>
|
||||||
|
</a>
|
||||||
|
<vn-confirm
|
||||||
|
vn-id="confirm"
|
||||||
|
message="This file will be deleted"
|
||||||
|
question="Are you sure you want to continue?"
|
||||||
|
on-response="$ctrl.deleteDms($response)">
|
||||||
|
</vn-confirm>
|
|
@ -0,0 +1,76 @@
|
||||||
|
import ngModule from '../../module';
|
||||||
|
import Component from 'core/lib/component';
|
||||||
|
import './style.scss';
|
||||||
|
|
||||||
|
class Controller extends Component {
|
||||||
|
constructor($element, $, vnToken) {
|
||||||
|
super($element, $);
|
||||||
|
this.accessToken = vnToken.token;
|
||||||
|
this.filter = {
|
||||||
|
include: {
|
||||||
|
relation: 'dms',
|
||||||
|
scope: {
|
||||||
|
fields: [
|
||||||
|
'dmsTypeFk',
|
||||||
|
'reference',
|
||||||
|
'hardCopyNumber',
|
||||||
|
'workerFk',
|
||||||
|
'description',
|
||||||
|
'hasFile',
|
||||||
|
'file',
|
||||||
|
'created',
|
||||||
|
],
|
||||||
|
include: [{
|
||||||
|
relation: 'dmsType',
|
||||||
|
scope: {
|
||||||
|
fields: ['name']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
relation: 'worker',
|
||||||
|
scope: {
|
||||||
|
fields: ['userFk'],
|
||||||
|
include: {
|
||||||
|
relation: 'user',
|
||||||
|
scope: {
|
||||||
|
fields: ['nickname']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
showWorkerDescriptor(event, workerFk) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopImmediatePropagation();
|
||||||
|
this.$.workerDescriptor.parent = event.target;
|
||||||
|
this.$.workerDescriptor.workerFk = workerFk;
|
||||||
|
this.$.workerDescriptor.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
showDeleteConfirm(index) {
|
||||||
|
this.dmsIndex = index;
|
||||||
|
this.$.confirm.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteDms(response) {
|
||||||
|
if (response === 'accept') {
|
||||||
|
const dmsFk = this.workerDms[this.dmsIndex].dmsFk;
|
||||||
|
const query = `WorkerDms/${dmsFk}/removeFile`;
|
||||||
|
this.$http.post(query).then(() => {
|
||||||
|
this.$.model.remove(this.dmsIndex);
|
||||||
|
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Controller.$inject = ['$element', '$scope', 'vnToken'];
|
||||||
|
|
||||||
|
ngModule.component('vnWorkerDmsIndex', {
|
||||||
|
template: require('./index.html'),
|
||||||
|
controller: Controller,
|
||||||
|
});
|
|
@ -0,0 +1,42 @@
|
||||||
|
import './index';
|
||||||
|
import crudModel from 'core/mocks/crud-model';
|
||||||
|
|
||||||
|
describe('Worker', () => {
|
||||||
|
describe('Component vnWorkerDmsIndex', () => {
|
||||||
|
let $componentController;
|
||||||
|
let $scope;
|
||||||
|
let $element;
|
||||||
|
let $httpBackend;
|
||||||
|
let controller;
|
||||||
|
|
||||||
|
beforeEach(ngModule('worker'));
|
||||||
|
|
||||||
|
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_) => {
|
||||||
|
$componentController = _$componentController_;
|
||||||
|
$httpBackend = _$httpBackend_;
|
||||||
|
$scope = $rootScope.$new();
|
||||||
|
$element = angular.element(`<vn-worker-dms-index></vn-worker-dms-index`);
|
||||||
|
controller = $componentController('vnWorkerDmsIndex', {$element, $scope});
|
||||||
|
controller.$.model = crudModel;
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('deleteDms()', () => {
|
||||||
|
it('should make an HTTP Post query', () => {
|
||||||
|
const dmsId = 4;
|
||||||
|
const dmsIndex = 0;
|
||||||
|
spyOn(controller.vnApp, 'showSuccess');
|
||||||
|
spyOn(controller.$.model, 'remove');
|
||||||
|
controller.workerDms = [{dmsFk: 4}];
|
||||||
|
controller.dmsIndex = dmsIndex;
|
||||||
|
|
||||||
|
$httpBackend.when('POST', `WorkerDms/${dmsId}/removeFile`).respond({});
|
||||||
|
$httpBackend.expect('POST', `WorkerDms/${dmsId}/removeFile`);
|
||||||
|
controller.deleteDms('accept');
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.$.model.remove).toHaveBeenCalledWith(dmsIndex);
|
||||||
|
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,9 @@
|
||||||
|
Type: Tipo
|
||||||
|
File management: Gestión documental
|
||||||
|
File: Fichero
|
||||||
|
Hard copy: Copia
|
||||||
|
This file will be deleted: Este fichero va a ser borrado
|
||||||
|
Are you sure?: Estas seguro?
|
||||||
|
File deleted: Fichero eliminado
|
||||||
|
Remove file: Eliminar fichero
|
||||||
|
Download file: Descargar fichero
|
|
@ -0,0 +1,6 @@
|
||||||
|
vn-client-risk-index {
|
||||||
|
.totalBox {
|
||||||
|
display: table;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
ClientFileDescription: "{{dmsTypeName}} from client {{clientName}} id {{clientId}}"
|
||||||
|
ContentTypesInfo: Allowed file types {{allowedContentTypes}}
|
|
@ -0,0 +1,20 @@
|
||||||
|
Reference: Referencia
|
||||||
|
Description: Descripción
|
||||||
|
Company: Empresa
|
||||||
|
Upload file: Subir fichero
|
||||||
|
Edit file: Editar fichero
|
||||||
|
Upload: Subir
|
||||||
|
File: Fichero
|
||||||
|
WorkerFileDescription: "{{dmsTypeName}} del empleado {{workerName}} id {{workerId}}"
|
||||||
|
ContentTypesInfo: "Tipos de archivo permitidos: {{allowedContentTypes}}"
|
||||||
|
Generate identifier for original file: Generar identificador para archivo original
|
||||||
|
Are you sure you want to continue?: ¿Seguro que quieres continuar?
|
||||||
|
File management: Gestión documental
|
||||||
|
Hard copy: Copia
|
||||||
|
This file will be deleted: Este fichero va a ser borrado
|
||||||
|
Are you sure?: ¿Seguro?
|
||||||
|
File deleted: Fichero eliminado
|
||||||
|
Remove file: Eliminar fichero
|
||||||
|
Download file: Descargar fichero
|
||||||
|
Created: Creado
|
||||||
|
Employee: Empleado
|
|
@ -14,3 +14,6 @@ import './calendar';
|
||||||
import './time-control';
|
import './time-control';
|
||||||
import './log';
|
import './log';
|
||||||
import './phones';
|
import './phones';
|
||||||
|
import './dms/index';
|
||||||
|
import './dms/create';
|
||||||
|
import './dms/edit';
|
||||||
|
|
|
@ -13,7 +13,8 @@
|
||||||
{"state": "worker.card.pbx", "icon": "icon-pbx"},
|
{"state": "worker.card.pbx", "icon": "icon-pbx"},
|
||||||
{"state": "worker.card.calendar", "icon": "icon-calendar"},
|
{"state": "worker.card.calendar", "icon": "icon-calendar"},
|
||||||
{"state": "worker.card.timeControl", "icon": "access_time"},
|
{"state": "worker.card.timeControl", "icon": "access_time"},
|
||||||
{"state": "worker.card.phones", "icon": "contact_phone"}
|
{"state": "worker.card.phones", "icon": "contact_phone"},
|
||||||
|
{"state": "worker.card.dms.index", "icon": "cloud_upload"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"routes": [
|
"routes": [
|
||||||
|
@ -89,6 +90,36 @@
|
||||||
"params": {
|
"params": {
|
||||||
"worker": "$ctrl.worker"
|
"worker": "$ctrl.worker"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "/dms",
|
||||||
|
"state": "worker.card.dms",
|
||||||
|
"abstract": true,
|
||||||
|
"component": "ui-view"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "/index",
|
||||||
|
"state": "worker.card.dms.index",
|
||||||
|
"component": "vn-worker-dms-index",
|
||||||
|
"description": "File management"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "/create",
|
||||||
|
"state": "worker.card.dms.create",
|
||||||
|
"component": "vn-worker-dms-create",
|
||||||
|
"description": "Upload file",
|
||||||
|
"params": {
|
||||||
|
"worker": "$ctrl.worker"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "/:dmsId/edit",
|
||||||
|
"state": "worker.card.dms.edit",
|
||||||
|
"component": "vn-worker-dms-edit",
|
||||||
|
"description": "Edit file",
|
||||||
|
"params": {
|
||||||
|
"worker": "$ctrl.worker"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
Loading…
Reference in New Issue