Refactor v2
gitea/salix/pipeline/head There was a failure building this commit
Details
|
@ -1,7 +1,7 @@
|
|||
coverage
|
||||
node_modules
|
||||
dist
|
||||
storage
|
||||
#storage
|
||||
npm-debug.log
|
||||
.eslintcache
|
||||
datasources.*.json
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
const UserError = require('vn-loopback/util/user-error');
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('updateFile', {
|
||||
|
@ -84,66 +85,46 @@ module.exports = Self => {
|
|||
};
|
||||
|
||||
async function uploadNewFile(ctx, dms, myOptions) {
|
||||
const storageConnector = Self.app.dataSources.dmsStorage.connector;
|
||||
const models = Self.app.models;
|
||||
const TempContainer = models.TempContainer;
|
||||
const DmsContainer = models.DmsContainer;
|
||||
const fileOptions = {};
|
||||
|
||||
const tempContainer = await getContainer('temp');
|
||||
const makeUpload = await models.Container.upload(tempContainer.name, ctx.req, ctx.result, fileOptions);
|
||||
const tempContainer = await TempContainer.container('dms');
|
||||
const makeUpload = await TempContainer.upload(tempContainer.name, ctx.req, ctx.result, fileOptions);
|
||||
const keys = Object.values(makeUpload.files);
|
||||
const files = keys.map(file => file[0]);
|
||||
const file = files[0];
|
||||
const uploadedFile = files[0];
|
||||
|
||||
if (file) {
|
||||
const oldExtension = storageConnector.getFileExtension(dms.file);
|
||||
const newExtension = storageConnector.getFileExtension(file.name);
|
||||
if (uploadedFile) {
|
||||
const oldExtension = DmsContainer.getFileExtension(dms.file);
|
||||
const newExtension = DmsContainer.getFileExtension(uploadedFile.name);
|
||||
const fileName = `${dms.id}.${newExtension}`;
|
||||
|
||||
try {
|
||||
if (oldExtension != newExtension) {
|
||||
const pathHash = storageConnector.getPathHash(dms.id);
|
||||
const pathHash = DmsContainer.getHash(dms.id);
|
||||
|
||||
await models.Container.removeFile(pathHash, dms.file);
|
||||
await DmsContainer.removeFile(pathHash, dms.file);
|
||||
}
|
||||
} catch (err) {}
|
||||
|
||||
const updatedDms = await dms.updateAttributes({
|
||||
contentType: file.type,
|
||||
contentType: uploadedFile.type,
|
||||
file: fileName
|
||||
}, myOptions);
|
||||
|
||||
const pathHash = storageConnector.getPathHash(updatedDms.id);
|
||||
const container = await getContainer(pathHash);
|
||||
const file = await TempContainer.getFile(tempContainer.name, uploadedFile.name);
|
||||
const srcFile = path.join(file.client.root, file.container, file.name);
|
||||
|
||||
const originPath = `${tempContainer.client.root}/${tempContainer.name}/${file.name}`;
|
||||
const destinationPath = `${container.client.root}/${pathHash}/${updatedDms.file}`;
|
||||
const pathHash = DmsContainer.getHash(updatedDms.id);
|
||||
const dmsContainer = await DmsContainer.container(pathHash);
|
||||
const dstFile = path.join(dmsContainer.client.root, pathHash, updatedDms.file);
|
||||
|
||||
fs.rename(originPath, destinationPath);
|
||||
await fs.move(srcFile, dstFile, {
|
||||
overwrite: true
|
||||
});
|
||||
|
||||
return updatedDms;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a container instance
|
||||
* If doesn't exists creates a new one
|
||||
*
|
||||
* @param {String} name Container name
|
||||
* @return {Object} Container instance
|
||||
*/
|
||||
async function getContainer(name) {
|
||||
const models = Self.app.models;
|
||||
let container;
|
||||
try {
|
||||
container = await models.Container.getContainer(name);
|
||||
} catch (err) {
|
||||
if (err.code === 'ENOENT') {
|
||||
container = await models.Container.createContainer({
|
||||
name: name
|
||||
});
|
||||
} else throw err;
|
||||
}
|
||||
|
||||
return container;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
const UserError = require('vn-loopback/util/user-error');
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('uploadFile', {
|
||||
|
@ -46,8 +47,9 @@ module.exports = Self => {
|
|||
});
|
||||
|
||||
Self.uploadFile = async(ctx, options) => {
|
||||
const storageConnector = Self.app.dataSources.dmsStorage.connector;
|
||||
const models = Self.app.models;
|
||||
const TempContainer = models.TempContainer;
|
||||
const DmsContainer = models.DmsContainer;
|
||||
const fileOptions = {};
|
||||
const args = ctx.args;
|
||||
|
||||
|
@ -62,28 +64,33 @@ module.exports = Self => {
|
|||
myOptions.transaction = tx;
|
||||
}
|
||||
|
||||
let srcFile;
|
||||
try {
|
||||
const hasWriteRole = await models.DmsType.hasWriteRole(ctx, args.dmsTypeId, myOptions);
|
||||
if (!hasWriteRole)
|
||||
throw new UserError(`You don't have enough privileges`);
|
||||
|
||||
// Upload file to temporary path
|
||||
const tempContainer = await getContainer('temp');
|
||||
const uploaded = await models.Container.upload(tempContainer.name, ctx.req, ctx.result, fileOptions);
|
||||
const tempContainer = await TempContainer.container('dms');
|
||||
const uploaded = await TempContainer.upload(tempContainer.name, ctx.req, ctx.result, fileOptions);
|
||||
const files = Object.values(uploaded.files).map(file => {
|
||||
return file[0];
|
||||
});
|
||||
|
||||
const addedDms = [];
|
||||
for (const file of files) {
|
||||
const newDms = await createDms(ctx, file, myOptions);
|
||||
const pathHash = storageConnector.getPathHash(newDms.id);
|
||||
const container = await getContainer(pathHash);
|
||||
for (const uploadedFile of files) {
|
||||
const newDms = await createDms(ctx, uploadedFile, myOptions);
|
||||
const pathHash = DmsContainer.getHash(newDms.id);
|
||||
|
||||
const originPath = `${tempContainer.client.root}/${tempContainer.name}/${file.name}`;
|
||||
const destinationPath = `${container.client.root}/${pathHash}/${newDms.file}`;
|
||||
const file = await TempContainer.getFile(tempContainer.name, uploadedFile.name);
|
||||
srcFile = path.join(file.client.root, file.container, file.name);
|
||||
|
||||
await fs.rename(originPath, destinationPath);
|
||||
const dmsContainer = await DmsContainer.container(pathHash);
|
||||
const dstFile = path.join(dmsContainer.client.root, pathHash, newDms.file);
|
||||
|
||||
await fs.move(srcFile, dstFile, {
|
||||
overwrite: true
|
||||
});
|
||||
|
||||
addedDms.push(newDms);
|
||||
}
|
||||
|
@ -92,13 +99,16 @@ module.exports = Self => {
|
|||
return addedDms;
|
||||
} catch (e) {
|
||||
if (tx) await tx.rollback();
|
||||
|
||||
if (fs.existsSync(srcFile))
|
||||
await fs.unlink(srcFile);
|
||||
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
||||
async function createDms(ctx, file, myOptions) {
|
||||
const models = Self.app.models;
|
||||
const storageConnector = Self.app.dataSources.dmsStorage.connector;
|
||||
const myUserId = ctx.req.accessToken.userId;
|
||||
const myWorker = await models.Worker.findOne({where: {userFk: myUserId}}, myOptions);
|
||||
const args = ctx.args;
|
||||
|
@ -115,32 +125,9 @@ module.exports = Self => {
|
|||
}, myOptions);
|
||||
|
||||
let fileName = file.name;
|
||||
const extension = storageConnector.getFileExtension(fileName);
|
||||
const extension = models.DmsContainer.getFileExtension(fileName);
|
||||
fileName = `${newDms.id}.${extension}`;
|
||||
|
||||
return newDms.updateAttribute('file', fileName, myOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a container instance
|
||||
* If doesn't exists creates a new one
|
||||
*
|
||||
* @param {String} name Container name
|
||||
* @return {Object} Container instance
|
||||
*/
|
||||
async function getContainer(name) {
|
||||
const models = Self.app.models;
|
||||
let container;
|
||||
try {
|
||||
container = await models.Container.getContainer(name);
|
||||
} catch (err) {
|
||||
if (err.code === 'ENOENT') {
|
||||
container = await models.Container.createContainer({
|
||||
name: name
|
||||
});
|
||||
} else throw err;
|
||||
}
|
||||
|
||||
return container;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
const UserError = require('vn-loopback/util/user-error');
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('download', {
|
||||
|
@ -69,8 +70,9 @@ module.exports = Self => {
|
|||
|
||||
const container = await models.ImageContainer.getContainer(collection);
|
||||
const rootPath = container.client.root;
|
||||
const fileSrc = path.join(rootPath, collection, size);
|
||||
const file = {
|
||||
path: `${rootPath}/${collection}/${size}/${image.name}.png`,
|
||||
path: `${fileSrc}/${image.name}.png`,
|
||||
contentType: 'image/png',
|
||||
name: `${image.name}.png`
|
||||
};
|
||||
|
|
|
@ -29,8 +29,8 @@ describe('image upload()', () => {
|
|||
expect(error.message).toEqual(`You don't have enough privileges`);
|
||||
});
|
||||
|
||||
it('should call to the ImageContainer upload method for the collection "catalog"', async() => {
|
||||
const containerModel = app.models.ImageContainer;
|
||||
it('should call to the TempContainer upload method for the collection "catalog"', async() => {
|
||||
const containerModel = app.models.TempContainer;
|
||||
spyOn(containerModel, 'upload');
|
||||
|
||||
const ctx = {req: {accessToken: {userId: buyerId}},
|
||||
|
@ -73,8 +73,8 @@ describe('image upload()', () => {
|
|||
const workerId = 106;
|
||||
const itemId = 4;
|
||||
|
||||
it('should be able to call to the ImageContainer upload method for the collection "user"', async() => {
|
||||
const containerModel = app.models.ImageContainer;
|
||||
it('should be able to call to the TempContainer upload method for the collection "user"', async() => {
|
||||
const containerModel = app.models.TempContainer;
|
||||
spyOn(containerModel, 'upload');
|
||||
|
||||
const ctx = {req: {accessToken: {userId: marketingId}},
|
||||
|
@ -91,8 +91,8 @@ describe('image upload()', () => {
|
|||
expect(containerModel.upload).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should be able to call to the ImageContainer upload method for the collection "catalog"', async() => {
|
||||
const containerModel = app.models.ImageContainer;
|
||||
it('should be able to call to the TempContainer upload method for the collection "catalog"', async() => {
|
||||
const containerModel = app.models.TempContainer;
|
||||
spyOn(containerModel, 'upload');
|
||||
|
||||
const ctx = {req: {accessToken: {userId: marketingId}},
|
||||
|
@ -115,8 +115,8 @@ describe('image upload()', () => {
|
|||
const workerId = 106;
|
||||
const itemId = 4;
|
||||
|
||||
it('should upload a file for the collection "user" and call to the ImageContainer upload method', async() => {
|
||||
const containerModel = app.models.ImageContainer;
|
||||
it('should upload a file for the collection "user" and call to the TempContainer upload method', async() => {
|
||||
const containerModel = app.models.TempContainer;
|
||||
spyOn(containerModel, 'upload');
|
||||
|
||||
const ctx = {req: {accessToken: {userId: hhrrId}},
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
const UserError = require('vn-loopback/util/user-error');
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('upload', {
|
||||
|
@ -17,6 +18,12 @@ module.exports = Self => {
|
|||
type: 'string',
|
||||
description: 'The collection name',
|
||||
required: true
|
||||
},
|
||||
{
|
||||
arg: 'fileName',
|
||||
type: 'string',
|
||||
description: 'The file name',
|
||||
required: true
|
||||
}],
|
||||
returns: {
|
||||
type: 'Object',
|
||||
|
@ -30,48 +37,36 @@ module.exports = Self => {
|
|||
|
||||
Self.upload = async ctx => {
|
||||
const models = Self.app.models;
|
||||
const TempContainer = models.TempContainer;
|
||||
const fileOptions = {};
|
||||
const args = ctx.args;
|
||||
|
||||
const hasWriteRole = await models.ImageCollection.hasWriteRole(ctx, args.collection);
|
||||
if (!hasWriteRole)
|
||||
throw new UserError(`You don't have enough privileges`);
|
||||
|
||||
if (process.env.NODE_ENV == 'test')
|
||||
throw new UserError(`You can't upload images on the test instance`);
|
||||
|
||||
// Upload file to temporary path
|
||||
const container = await getContainer(args.collection);
|
||||
const uploaded = await models.ImageContainer.upload(container.name, ctx.req, ctx.result, fileOptions);
|
||||
const [uploadedFile] = Object.values(uploaded.files).map(file => {
|
||||
return file[0];
|
||||
});
|
||||
|
||||
const file = await models.ImageContainer.getFile(container.name, uploadedFile.name);
|
||||
const srcFile = `${file.client.root}/${file.container}/${file.name}`;
|
||||
await models.Image.registerImage(container.name, srcFile, args.id);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a container instance
|
||||
* If doesn't exists creates a new one
|
||||
*
|
||||
* @param {String} name Container name
|
||||
* @return {Object} Container instance
|
||||
*/
|
||||
async function getContainer(name) {
|
||||
const models = Self.app.models;
|
||||
let container;
|
||||
let srcFile;
|
||||
try {
|
||||
container = await models.ImageContainer.getContainer(name);
|
||||
} catch (err) {
|
||||
if (err.code === 'ENOENT') {
|
||||
container = await models.ImageContainer.createContainer({
|
||||
name: name
|
||||
});
|
||||
} else throw err;
|
||||
}
|
||||
const hasWriteRole = await models.ImageCollection.hasWriteRole(ctx, args.collection);
|
||||
if (!hasWriteRole)
|
||||
throw new UserError(`You don't have enough privileges`);
|
||||
|
||||
return container;
|
||||
}
|
||||
if (process.env.NODE_ENV == 'test')
|
||||
throw new UserError(`You can't upload images on the test instance`);
|
||||
|
||||
await TempContainer.allowedContentTypes();
|
||||
|
||||
// Upload file to temporary path
|
||||
const tempContainer = await TempContainer.container(args.collection);
|
||||
const uploaded = await TempContainer.upload(tempContainer.name, ctx.req, ctx.result, fileOptions);
|
||||
const [uploadedFile] = Object.values(uploaded.files).map(file => {
|
||||
return file[0];
|
||||
});
|
||||
const file = await TempContainer.getFile(tempContainer.name, uploadedFile.name);
|
||||
srcFile = path.join(file.client.root, file.container, file.name);
|
||||
|
||||
await models.Image.registerImage(args.collection, srcFile, args.fileName, args.id);
|
||||
} catch (e) {
|
||||
if (fs.existsSync(srcFile))
|
||||
await fs.unlink(srcFile);
|
||||
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
@ -17,9 +17,6 @@
|
|||
"Company": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"Container": {
|
||||
"dataSource": "dmsStorage"
|
||||
},
|
||||
"Continent": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
|
@ -35,6 +32,9 @@
|
|||
"Delivery": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"DmsContainer": {
|
||||
"dataSource": "dmsStorage"
|
||||
},
|
||||
"Image": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
|
@ -53,6 +53,9 @@
|
|||
"Province": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"TempContainer": {
|
||||
"dataSource": "tempStorage"
|
||||
},
|
||||
"UserConfig": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
{
|
||||
"name": "Container",
|
||||
"base": "VnModel",
|
||||
"idInjection": true,
|
||||
"options": {
|
||||
"validateUpsert": true
|
||||
},
|
||||
"properties": {},
|
||||
"validations": [],
|
||||
"relations": {},
|
||||
"acls": [],
|
||||
"methods": []
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"name": "DmsContainer",
|
||||
"base": "Container",
|
||||
"acls": [{
|
||||
"accessType": "READ",
|
||||
"principalType": "ROLE",
|
||||
"principalId": "$everyone",
|
||||
"permission": "ALLOW"
|
||||
}]
|
||||
}
|
|
@ -14,12 +14,12 @@ module.exports = Self => {
|
|||
};
|
||||
|
||||
Self.getFile = async function(id) {
|
||||
const storageConnector = Self.app.dataSources.dmsStorage.connector;
|
||||
const models = Self.app.models;
|
||||
const DmsContainer = models.DmsContainer;
|
||||
const dms = await Self.findById(id);
|
||||
const pathHash = storageConnector.getPathHash(dms.id);
|
||||
const pathHash = DmsContainer.getHash(dms.id);
|
||||
try {
|
||||
await models.Container.getFile(pathHash, dms.file);
|
||||
await DmsContainer.getFile(pathHash, dms.file);
|
||||
} catch (e) {
|
||||
if (e.code != 'ENOENT')
|
||||
throw e;
|
||||
|
@ -30,7 +30,7 @@ module.exports = Self => {
|
|||
throw error;
|
||||
}
|
||||
|
||||
const stream = models.Container.downloadStream(pathHash, dms.file);
|
||||
const stream = DmsContainer.downloadStream(pathHash, dms.file);
|
||||
|
||||
return [stream, dms.contentType, `filename="${dms.file}"`];
|
||||
};
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
{
|
||||
"name": "ImageContainer",
|
||||
"base": "VnModel",
|
||||
"idInjection": true,
|
||||
"options": {
|
||||
"validateUpsert": true
|
||||
},
|
||||
"properties": {},
|
||||
"validations": [],
|
||||
"relations": {},
|
||||
"acls": [],
|
||||
"methods": []
|
||||
}
|
||||
"base": "Container",
|
||||
"acls": [{
|
||||
"accessType": "READ",
|
||||
"principalType": "ROLE",
|
||||
"principalId": "$everyone",
|
||||
"permission": "ALLOW"
|
||||
}]
|
||||
}
|
|
@ -6,7 +6,7 @@ module.exports = Self => {
|
|||
require('../methods/image/download')(Self);
|
||||
require('../methods/image/upload')(Self);
|
||||
|
||||
Self.registerImage = async(collectionName, srcFile, entityId) => {
|
||||
Self.registerImage = async(collectionName, srcFilePath, fileName, entityId) => {
|
||||
const models = Self.app.models;
|
||||
const tx = await Self.beginTransaction({});
|
||||
const myOptions = {transaction: tx};
|
||||
|
@ -30,13 +30,10 @@ module.exports = Self => {
|
|||
}
|
||||
}, myOptions);
|
||||
|
||||
const file = srcFile.split('/').pop();
|
||||
const fileName = file.split('.')[0];
|
||||
const data = {
|
||||
name: fileName,
|
||||
collectionFk: collectionName
|
||||
};
|
||||
|
||||
const newImage = await Self.upsertWithWhere(data, {
|
||||
name: fileName,
|
||||
collectionFk: collectionName,
|
||||
|
@ -44,9 +41,10 @@ module.exports = Self => {
|
|||
}, myOptions);
|
||||
|
||||
// Resizes and saves the image
|
||||
const container = await models.ImageContainer.getContainer(collectionName);
|
||||
const container = await models.ImageContainer.container(collectionName);
|
||||
const rootPath = container.client.root;
|
||||
const collectionDir = path.join(rootPath, collectionName);
|
||||
const file = `${fileName}.png`;
|
||||
const dstDir = path.join(collectionDir, 'full');
|
||||
const dstFile = path.join(dstDir, file);
|
||||
|
||||
|
@ -56,7 +54,7 @@ module.exports = Self => {
|
|||
};
|
||||
|
||||
await fs.mkdir(dstDir, {recursive: true});
|
||||
await sharp(srcFile, {failOnError: false})
|
||||
await sharp(srcFilePath, {failOnError: false})
|
||||
.resize(collection.maxWidth, collection.maxHeight, resizeOpts)
|
||||
.png()
|
||||
.toFile(dstFile);
|
||||
|
@ -71,7 +69,7 @@ module.exports = Self => {
|
|||
};
|
||||
|
||||
await fs.mkdir(dstDir, {recursive: true});
|
||||
await sharp(srcFile, {failOnError: false})
|
||||
await sharp(srcFilePath, {failOnError: false})
|
||||
.resize(size.width, size.height, resizeOpts)
|
||||
.png()
|
||||
.toFile(dstFile);
|
||||
|
@ -91,8 +89,8 @@ module.exports = Self => {
|
|||
);
|
||||
}
|
||||
|
||||
if (fs.existsSync(srcFile))
|
||||
await fs.unlink(srcFile);
|
||||
if (fs.existsSync(srcFilePath))
|
||||
await fs.unlink(srcFilePath);
|
||||
|
||||
await tx.commit();
|
||||
return newImage;
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"name": "TempContainer",
|
||||
"base": "Container",
|
||||
"acls": [{
|
||||
"accessType": "READ",
|
||||
"principalType": "ROLE",
|
||||
"principalId": "$everyone",
|
||||
"permission": "ALLOW"
|
||||
}]
|
||||
}
|
|
@ -767,19 +767,19 @@ INSERT INTO `vn`.`intrastat`(`id`, `description`, `taxClassFk`, `taxCodeFk`)
|
|||
|
||||
INSERT INTO `vn`.`item`(`id`, `typeFk`, `size`, `inkFk`, `stems`, `originFk`, `description`, `producerFk`, `intrastatFk`, `isOnOffer`, `expenceFk`, `isBargain`, `comment`, `relevancy`, `image`, `taxClassFk`, `subName`, `minPrice`)
|
||||
VALUES
|
||||
(1, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 0, 2000000000, 0, NULL, 0, '861e1ed0-3ab3-11eb-9ab8-27f6fc3b85fd', 1, NULL, 0),
|
||||
(2, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 0, 2000000000, 0, NULL, 0, '9b0316c0-3ab3-11eb-9ab8-27f6fc3b85fd', 1, NULL, 0),
|
||||
(3, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 0, 4751000000, 0, NULL, 0, 'a93bd600-3ab3-11eb-9ab8-27f6fc3b85fd', 1, NULL, 0),
|
||||
(4, 1, 60, 'YEL', 1, 1, 'Increases block', 1, 05080000, 1, 4751000000, 0, NULL, 0, '0e1c92d0-3ab4-11eb-9ab8-27f6fc3b85fd', 2, NULL, 0),
|
||||
(5, 3, 30, 'RED', 1, 2, NULL, 2, 06021010, 1, 4751000000, 0, NULL, 0, '189081e0-3ab4-11eb-9ab8-27f6fc3b85fd', 2, NULL, 0),
|
||||
(6, 5, 30, 'RED', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, '25238060-3ab4-11eb-9ab8-27f6fc3b85fd', 2, NULL, 0),
|
||||
(7, 5, 90, 'BLU', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 'c4097310-3ab4-11eb-9ab8-27f6fc3b85fd', 2, NULL, 0),
|
||||
(8, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 0, 2000000000, 0, NULL, 0, 'd3bf8380-3ab4-11eb-9ab8-27f6fc3b85fd', 1, NULL, 0),
|
||||
(9, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 0, 2000000000, 0, NULL, 0, '20e9fff0-3ab5-11eb-9ab8-27f6fc3b85fd', 1, NULL, 0),
|
||||
(10, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 0, 4751000000, 0, NULL, 0, '2c484f00-3ab5-11eb-9ab8-27f6fc3b85fd', 1, NULL, 0),
|
||||
(11, 1, 60, 'YEL', 1, 1, NULL, 1, 05080000, 1, 4751000000, 0, NULL, 0, 'a3d9bea0-3ab5-11eb-9ab8-27f6fc3b85fd', 2, NULL, 0),
|
||||
(12, 3, 30, 'RED', 1, 2, NULL, 2, 06021010, 1, 4751000000, 0, NULL, 0, 'e48b2d30-3ab5-11eb-9ab8-27f6fc3b85fd', 2, NULL, 0),
|
||||
(13, 5, 30, 'RED', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 'fb5cd9f0-3ab5-11eb-9ab8-27f6fc3b85fd', 2, NULL, 0),
|
||||
(1, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 0, 2000000000, 0, NULL, 0, '1', 1, NULL, 0),
|
||||
(2, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 0, 2000000000, 0, NULL, 0, '2', 1, NULL, 0),
|
||||
(3, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 0, 4751000000, 0, NULL, 0, '3', 1, NULL, 0),
|
||||
(4, 1, 60, 'YEL', 1, 1, 'Increases block', 1, 05080000, 1, 4751000000, 0, NULL, 0, '4', 2, NULL, 0),
|
||||
(5, 3, 30, 'RED', 1, 2, NULL, 2, 06021010, 1, 4751000000, 0, NULL, 0, '5', 2, NULL, 0),
|
||||
(6, 5, 30, 'RED', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, '6', 2, NULL, 0),
|
||||
(7, 5, 90, 'BLU', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, '7', 2, NULL, 0),
|
||||
(8, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 0, 2000000000, 0, NULL, 0, '8', 1, NULL, 0),
|
||||
(9, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 0, 2000000000, 0, NULL, 0, '9', 1, NULL, 0),
|
||||
(10, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 0, 4751000000, 0, NULL, 0, '10', 1, NULL, 0),
|
||||
(11, 1, 60, 'YEL', 1, 1, NULL, 1, 05080000, 1, 4751000000, 0, NULL, 0, '11', 2, NULL, 0),
|
||||
(12, 3, 30, 'RED', 1, 2, NULL, 2, 06021010, 1, 4751000000, 0, NULL, 0, '12', 2, NULL, 0),
|
||||
(13, 5, 30, 'RED', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, '13', 2, NULL, 0),
|
||||
(14, 5, 90, 'BLU', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, '', 2, NULL, 0),
|
||||
(15, 4, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, '', 2, NULL, 0),
|
||||
(16, 4, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, '', 2, NULL, 0),
|
||||
|
|
|
@ -6,13 +6,29 @@
|
|||
<vn-horizontal ng-show="file.value" class="photo vn-mb-md">
|
||||
<div><img vn-id="photo" ng-src=""/></div>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="File name"
|
||||
ng-model="$ctrl.newPhoto.fileName"
|
||||
required="true">
|
||||
</vn-input-file>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-input-file vn-id="file"
|
||||
vn-one
|
||||
label="File"
|
||||
ng-model="$ctrl.newPhoto.files"
|
||||
on-change="$ctrl.updatePhotoPreview(value)"
|
||||
accept="{{$ctrl.allowedContentTypes}}"
|
||||
required="true">
|
||||
<append>
|
||||
<vn-icon vn-none
|
||||
color-marginal
|
||||
title="{{$ctrl.contentTypesInfo}}"
|
||||
icon="info">
|
||||
</vn-icon>
|
||||
</append>
|
||||
</vn-input-file>
|
||||
</vn-horizontal>
|
||||
</tpl-body>
|
||||
|
|
|
@ -12,8 +12,26 @@ export default class UploadPhoto extends Component {
|
|||
* @param {*} id - Entity id
|
||||
*/
|
||||
show(collection, id) {
|
||||
this.newPhoto = {id, collection};
|
||||
this.newPhoto = {
|
||||
id: id,
|
||||
collection: collection,
|
||||
fileName: id
|
||||
};
|
||||
this.$.dialog.show();
|
||||
this.getAllowedContentTypes();
|
||||
}
|
||||
|
||||
getAllowedContentTypes() {
|
||||
this.$http.get('ImageContainers/allowedContentTypes').then(res => {
|
||||
const contentTypes = res.data.join(', ');
|
||||
this.allowedContentTypes = contentTypes;
|
||||
});
|
||||
}
|
||||
|
||||
get contentTypesInfo() {
|
||||
return this.$t('ContentTypesInfo', {
|
||||
allowedContentTypes: this.allowedContentTypes
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
Upload new photo: Subir una nueva foto
|
||||
Select an image: Selecciona una imagen
|
||||
Select an image: Selecciona una imagen
|
||||
File name: Nombre del fichero
|
|
@ -0,0 +1,57 @@
|
|||
const md5 = require('md5');
|
||||
|
||||
module.exports = function(Self) {
|
||||
Self.setup = function() {
|
||||
Self.super_.setup.call(this);
|
||||
|
||||
this.remoteMethod('allowedContentTypes', {
|
||||
description: 'Returns a list of allowed contentTypes',
|
||||
accessType: 'READ',
|
||||
returns: {
|
||||
type: ['Object'],
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/allowedContentTypes`,
|
||||
verb: 'GET'
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a container instance
|
||||
* If doesn't exists creates a new one
|
||||
*
|
||||
* @param {String} name Container name
|
||||
* @return {Object} Container instance
|
||||
*/
|
||||
Self.container = async function(name) {
|
||||
const models = Self.app.models;
|
||||
let container;
|
||||
try {
|
||||
container = await models[this.modelName].getContainer(name);
|
||||
} catch (err) {
|
||||
if (err.code === 'ENOENT') {
|
||||
container = await models[this.modelName].createContainer({
|
||||
name: name
|
||||
});
|
||||
} else throw err;
|
||||
}
|
||||
|
||||
return container;
|
||||
};
|
||||
|
||||
Self.getHash = function(id) {
|
||||
return md5(id.toString()).substring(0, 3);
|
||||
};
|
||||
|
||||
Self.getFileExtension = function(fileName) {
|
||||
return fileName.split('.').pop().toLowerCase();
|
||||
};
|
||||
|
||||
Self.allowedContentTypes = async function() {
|
||||
const connector = this.dataSource.connector;
|
||||
const allowedContentTypes = connector.allowedContentTypes;
|
||||
return allowedContentTypes;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"name": "Container",
|
||||
"base": "VnModel",
|
||||
"acls": [
|
||||
{
|
||||
"property": "status",
|
||||
"principalType": "ROLE",
|
||||
"principalId": "$everyone",
|
||||
"permission": "ALLOW"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
const uuid = require('uuid/v1');
|
||||
const md5 = require('md5');
|
||||
|
||||
module.exports = app => {
|
||||
const storageConnector = app.dataSources.dmsStorage.connector;
|
||||
|
||||
storageConnector.getFilename = function(file) {
|
||||
return `${uuid()}.${storageConnector.getFileExtension(file.name)}`;
|
||||
};
|
||||
|
||||
storageConnector.getFileExtension = function(fileName) {
|
||||
return fileName.split('.').pop().toLowerCase();
|
||||
};
|
||||
|
||||
storageConnector.getPathHash = function(id) {
|
||||
return md5(id.toString()).substring(0, 3);
|
||||
};
|
||||
|
||||
const imageStorageConnector = app.dataSources.imageStorage.connector;
|
||||
imageStorageConnector.getFilename = function(file) {
|
||||
return `${uuid()}.png`;
|
||||
};
|
||||
|
||||
/* imageStorageConnector.getFileExtension = function(fileName) {
|
||||
return fileName.split('.').pop().toLowerCase();
|
||||
};
|
||||
|
||||
imageStorageConnector.getPathHash = function(id) {
|
||||
return md5(id.toString()).substring(0, 3);
|
||||
}; */
|
||||
};
|
|
@ -17,6 +17,26 @@
|
|||
"connectTimeout": 40000,
|
||||
"acquireTimeout": 20000
|
||||
},
|
||||
"tempStorage": {
|
||||
"name": "tempStorage",
|
||||
"connector": "loopback-component-storage",
|
||||
"provider": "filesystem",
|
||||
"root": "./storage/tmp",
|
||||
"maxFileSize": "262144000",
|
||||
"allowedContentTypes": [
|
||||
"application/x-7z-compressed",
|
||||
"application/x-zip-compressed",
|
||||
"application/x-rar-compressed",
|
||||
"application/octet-stream",
|
||||
"application/pdf",
|
||||
"application/zip",
|
||||
"application/rar",
|
||||
"multipart/x-zip",
|
||||
"image/png",
|
||||
"image/jpeg",
|
||||
"image/jpg"
|
||||
]
|
||||
},
|
||||
"dmsStorage": {
|
||||
"name": "dmsStorage",
|
||||
"connector": "loopback-component-storage",
|
||||
|
|
|
@ -49,5 +49,8 @@
|
|||
},
|
||||
"Application": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"Container": {
|
||||
"dataSource": "vn"
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
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.dmsStorage.connector;
|
||||
const allowedContentTypes = storageConnector.allowedContentTypes;
|
||||
const modelAllowedContentTypes = Self.definition.settings.allowedContentTypes;
|
||||
|
||||
return modelAllowedContentTypes || allowedContentTypes;
|
||||
};
|
||||
};
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
module.exports = Self => {
|
||||
require('../methods/client-dms/removeFile')(Self);
|
||||
require('../methods/client-dms/allowedContentTypes')(Self);
|
||||
};
|
||||
|
|
|
@ -26,7 +26,7 @@ class Controller extends Section {
|
|||
}
|
||||
|
||||
getAllowedContentTypes() {
|
||||
this.$http.get('clientDms/allowedContentTypes').then(res => {
|
||||
this.$http.get('DmsContainers/allowedContentTypes').then(res => {
|
||||
const contentTypes = res.data.join(', ');
|
||||
this.allowedContentTypes = contentTypes;
|
||||
});
|
||||
|
|
|
@ -17,7 +17,7 @@ class Controller extends Section {
|
|||
}
|
||||
|
||||
getAllowedContentTypes() {
|
||||
this.$http.get('clientDms/allowedContentTypes').then(res => {
|
||||
this.$http.get('DmsContainers/allowedContentTypes').then(res => {
|
||||
const contentTypes = res.data.join(', ');
|
||||
this.allowedContentTypes = contentTypes;
|
||||
});
|
||||
|
|
|
@ -33,8 +33,10 @@ module.exports = Self => {
|
|||
// Exit loop
|
||||
if (!image) return clearInterval(timer);
|
||||
|
||||
const fileName = `${image.itemFk}.png`;
|
||||
const filePath = path.join(tempPath, fileName);
|
||||
const srcFile = image.url.split('/').pop();
|
||||
const fileName = srcFile.split('.')[0];
|
||||
const file = `${fileName}.png`;
|
||||
const filePath = path.join(tempPath, file);
|
||||
|
||||
const writeStream = fs.createWriteStream(filePath);
|
||||
writeStream.on('open', () => {
|
||||
|
@ -57,7 +59,7 @@ module.exports = Self => {
|
|||
|
||||
writeStream.on('finish', async function() {
|
||||
try {
|
||||
await models.Image.registerImage('catalog', filePath, image.itemFk);
|
||||
await models.Image.registerImage('catalog', filePath, fileName, image.itemFk);
|
||||
await image.destroy();
|
||||
} catch (error) {
|
||||
await errorHandler(image.itemFk, error, filePath);
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
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.dmsStorage.connector;
|
||||
const allowedContentTypes = storageConnector.allowedContentTypes;
|
||||
const modelAllowedContentTypes = Self.definition.settings.allowedContentTypes;
|
||||
|
||||
return modelAllowedContentTypes || allowedContentTypes;
|
||||
};
|
||||
};
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
module.exports = Self => {
|
||||
require('../methods/ticket-dms/removeFile')(Self);
|
||||
require('../methods/ticket-dms/allowedContentTypes')(Self);
|
||||
};
|
||||
|
|
|
@ -25,7 +25,7 @@ class Controller extends Section {
|
|||
}
|
||||
|
||||
getAllowedContentTypes() {
|
||||
this.$http.get('ticketDms/allowedContentTypes').then(res => {
|
||||
this.$http.get('DmsContainers/allowedContentTypes').then(res => {
|
||||
const contentTypes = res.data.join(', ');
|
||||
this.allowedContentTypes = contentTypes;
|
||||
});
|
||||
|
|
|
@ -16,7 +16,7 @@ class Controller extends Section {
|
|||
}
|
||||
|
||||
getAllowedContentTypes() {
|
||||
this.$http.get('ticketDms/allowedContentTypes').then(res => {
|
||||
this.$http.get('DmsContainers/allowedContentTypes').then(res => {
|
||||
const contentTypes = res.data.join(', ');
|
||||
this.allowedContentTypes = contentTypes;
|
||||
});
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
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.dmsStorage.connector;
|
||||
const allowedContentTypes = storageConnector.allowedContentTypes;
|
||||
const modelAllowedContentTypes = Self.definition.settings.allowedContentTypes;
|
||||
|
||||
return modelAllowedContentTypes || allowedContentTypes;
|
||||
};
|
||||
};
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
module.exports = Self => {
|
||||
require('../methods/travel-thermograph/allowedContentTypes')(Self);
|
||||
require('../methods/travel-thermograph/getThermographTemperatures')(Self);
|
||||
};
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ class Controller extends Section {
|
|||
}
|
||||
|
||||
getAllowedContentTypes() {
|
||||
this.$http.get('TravelThermographs/allowedContentTypes').then(res => {
|
||||
this.$http.get('DmsContainers/allowedContentTypes').then(res => {
|
||||
const contentTypes = res.data.join(', ');
|
||||
this.allowedContentTypes = contentTypes;
|
||||
});
|
||||
|
|
|
@ -17,7 +17,7 @@ class Controller extends Section {
|
|||
}
|
||||
|
||||
getAllowedContentTypes() {
|
||||
this.$http.get('TravelThermographs/allowedContentTypes').then(res => {
|
||||
this.$http.get('DmsContainers/allowedContentTypes').then(res => {
|
||||
const contentTypes = res.data.join(', ');
|
||||
this.allowedContentTypes = contentTypes;
|
||||
});
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
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.dmsStorage.connector;
|
||||
const allowedContentTypes = storageConnector.allowedContentTypes;
|
||||
const modelAllowedContentTypes = Self.definition.settings.allowedContentTypes;
|
||||
|
||||
return modelAllowedContentTypes || allowedContentTypes;
|
||||
};
|
||||
};
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
module.exports = Self => {
|
||||
require('../methods/worker-dms/downloadFile')(Self);
|
||||
require('../methods/worker-dms/removeFile')(Self);
|
||||
require('../methods/worker-dms/allowedContentTypes')(Self);
|
||||
require('../methods/worker-dms/filter')(Self);
|
||||
|
||||
Self.isMine = async function(ctx, dmsId) {
|
||||
|
|
|
@ -26,7 +26,7 @@ class Controller extends Section {
|
|||
}
|
||||
|
||||
getAllowedContentTypes() {
|
||||
this.$http.get('workerDms/allowedContentTypes').then(res => {
|
||||
this.$http.get('DmsContainers/allowedContentTypes').then(res => {
|
||||
const contentTypes = res.data.join(', ');
|
||||
this.allowedContentTypes = contentTypes;
|
||||
});
|
||||
|
|
|
@ -17,7 +17,7 @@ class Controller extends Section {
|
|||
}
|
||||
|
||||
getAllowedContentTypes() {
|
||||
this.$http.get('WorkerDms/allowedContentTypes').then(res => {
|
||||
this.$http.get('DmsContainers/allowedContentTypes').then(res => {
|
||||
const contentTypes = res.data.join(', ');
|
||||
this.allowedContentTypes = contentTypes;
|
||||
});
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
</vn-icon-button>
|
||||
</vn-td>
|
||||
<vn-td shrink>
|
||||
<vn-icon-button ui-sref="worker.card.edit({dmsId: {{::document.dmsFk}}})"
|
||||
<vn-icon-button ui-sref="worker.card.dms.edit({dmsId: {{::document.dmsFk}}})"
|
||||
icon="edit"
|
||||
title="{{'Edit file' | translate}}">
|
||||
</vn-icon-button>
|
||||
|
|
|
@ -43,6 +43,6 @@
|
|||
"pool": true
|
||||
},
|
||||
"storage": {
|
||||
"root": "./e2e/dms"
|
||||
"root": "./storage/dms"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 1.4 MiB After Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 1.4 MiB After Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 86 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 81 KiB |
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 74 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 98 KiB |
Before Width: | Height: | Size: 492 KiB After Width: | Height: | Size: 492 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 67 KiB |
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 65 KiB |
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 86 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 81 KiB |
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 74 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 98 KiB |
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 9.8 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 3.7 MiB After Width: | Height: | Size: 3.7 MiB |
Before Width: | Height: | Size: 1.7 MiB After Width: | Height: | Size: 1.7 MiB |
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 86 KiB |