1
0
mirror of https://github.com/bpatrik/pigallery2.git synced 2025-01-12 04:23:09 +02:00

improving code quality

This commit is contained in:
Patrik J. Braun 2020-01-02 22:11:59 +01:00
parent 4dbfff5206
commit 17139c692b
32 changed files with 123 additions and 85 deletions

View File

@ -1,5 +1,6 @@
# PiGallery2
[![npm version](https://badge.fury.io/js/pigallery2.svg)](https://badge.fury.io/js/pigallery2)
[![Language grade: JavaScript](https://img.shields.io/lgtm/grade/javascript/g/bpatrik/pigallery2.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/bpatrik/pigallery2/context:javascript)
[![Build Status](https://travis-ci.org/bpatrik/pigallery2.svg?branch=master)](https://travis-ci.org/bpatrik/pigallery2)
[![Heroku](https://heroku-badge.herokuapp.com/?app=pigallery2&style=flat)](https://pigallery2.herokuapp.com)
[![Docker build](https://github.com/bpatrik/pigallery2/workflows/docker-buildx/badge.svg)](https://github.com/bpatrik/pigallery2/actions)

78
package-lock.json generated
View File

@ -2911,9 +2911,9 @@
}
},
"@k3rn31p4nic/google-translate-api": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/@k3rn31p4nic/google-translate-api/-/google-translate-api-1.0.6.tgz",
"integrity": "sha512-84tHqaQsfHvBR8jejRCv/xEedoYs6Evxrl/KFRiI4ikrYus0+pq8g1d6j16UCHXaT5c+MjTAlPz++TwX+tEarQ==",
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@k3rn31p4nic/google-translate-api/-/google-translate-api-1.1.0.tgz",
"integrity": "sha512-IojXbuzP/9ykEOEGIAXTh7JRTXeHnp5vEJzg7aauVzft1X5dj9jny1MpWsRSGh2Z6b/KrNndCYiFBZZf9NssQw==",
"dev": true,
"requires": {
"got": "^9.2.2"
@ -3160,6 +3160,16 @@
"@types/keygrip": "*"
}
},
"@types/csurf": {
"version": "1.9.36",
"resolved": "https://registry.npmjs.org/@types/csurf/-/csurf-1.9.36.tgz",
"integrity": "sha512-arAJD++ZGT9eZVR+BQa1eaT7Id5pZ9nt4/x2Emxg8OEo6WAQV0ztVXS7A8n0RDd4KAaw2YYcwZUdjUvqg2k9tw==",
"dev": true,
"requires": {
"@types/express": "*",
"@types/express-serve-static-core": "*"
}
},
"@types/ejs": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.0.0.tgz",
@ -6991,6 +7001,16 @@
"randomfill": "^1.0.3"
}
},
"csrf": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/csrf/-/csrf-3.1.0.tgz",
"integrity": "sha512-uTqEnCvWRk042asU6JtapDTcJeeailFy4ydOQS28bj1hcLnYRiqi8SsD2jS412AY1I/4qdOwWZun774iqywf9w==",
"requires": {
"rndm": "1.2.0",
"tsscmp": "1.0.6",
"uid-safe": "2.1.5"
}
},
"css-parse": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/css-parse/-/css-parse-1.7.0.tgz",
@ -7057,6 +7077,17 @@
"integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=",
"dev": true
},
"csurf": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/csurf/-/csurf-1.10.0.tgz",
"integrity": "sha512-fh725p0R83wA5JukCik5hdEko/LizW/Vl7pkKDa1WJUVCosg141mqaAWCScB+nkEaRMFMGbutHMOr6oBNc/j9A==",
"requires": {
"cookie": "0.3.1",
"cookie-signature": "1.0.6",
"csrf": "3.1.0",
"http-errors": "~1.7.2"
}
},
"currently-unhandled": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
@ -15104,6 +15135,11 @@
"inherits": "~2.0.3"
}
},
"random-bytes": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
"integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs="
},
"randombytes": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
@ -15716,6 +15752,11 @@
"inherits": "^2.0.1"
}
},
"rndm": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz",
"integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w="
},
"run-async": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
@ -17560,6 +17601,11 @@
}
}
},
"tsscmp": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz",
"integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA=="
},
"tsutils": {
"version": "2.29.0",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
@ -17728,6 +17774,14 @@
}
}
},
"uid-safe": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
"integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==",
"requires": {
"random-bytes": "~1.0.0"
}
},
"ultron": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz",
@ -20154,23 +20208,23 @@
}
},
"xlf-google-translate": {
"version": "1.0.0-beta.18",
"resolved": "https://registry.npmjs.org/xlf-google-translate/-/xlf-google-translate-1.0.0-beta.18.tgz",
"integrity": "sha512-BDsJm+i6rNNuFqm3EYXhojTb9V/PYdgt3zt0X56kIrWqJKrI08iDOdhIXcujqdYwiPxnS4nVPW4DKbXy8UA1gw==",
"version": "1.0.0-beta.19",
"resolved": "https://registry.npmjs.org/xlf-google-translate/-/xlf-google-translate-1.0.0-beta.19.tgz",
"integrity": "sha512-zeZTvH3ijeh0/F73jrKr4/Ojr61ds6NHP+KN792uamMzCY3Fv0wfjLXSzdXINXEK+CKKNyV333i6zPMzt7fz0Q==",
"dev": true,
"requires": {
"@k3rn31p4nic/google-translate-api": "1.0.6",
"typeconfig": "1.0.7",
"@k3rn31p4nic/google-translate-api": "1.1.0",
"typeconfig": "1.0.9",
"xml2js": "0.4.23"
},
"dependencies": {
"typeconfig": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/typeconfig/-/typeconfig-1.0.7.tgz",
"integrity": "sha512-s5Ur+k9Kvgc31FO5m4eZHm3xmr3lJSpr+QmXZVWw3sTOj9fBpj0UL1eDyRUH8TKZccFc/6ApqrWNxSXs8Ea6SQ==",
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/typeconfig/-/typeconfig-1.0.9.tgz",
"integrity": "sha512-s8iCnCTSVNP6S7yF6KdkyhbvV0BDmPE/RnJOZf77sjMdfB5B/QlqrFFQWmnz+818xsP38bieD5OcP1iqzUKW/A==",
"dev": true,
"requires": {
"optimist": "^0.6.1"
"optimist": "0.6.1"
}
}
}

View File

@ -31,6 +31,7 @@
"body-parser": "1.19.0",
"cookie-parser": "1.4.4",
"cookie-session": "2.0.0-beta.3",
"csurf": "1.10.0",
"ejs": "3.0.1",
"exifreader": "2.12.0",
"express": "4.17.1",
@ -67,6 +68,7 @@
"@types/chai": "4.2.6",
"@types/cookie-parser": "1.4.2",
"@types/cookie-session": "2.0.37",
"@types/csurf": "1.9.36",
"@types/ejs": "3.0.0",
"@types/express": "4.17.2",
"@types/fluent-ffmpeg": "2.1.11",

View File

@ -2,7 +2,8 @@ import * as cluster from 'cluster';
if (cluster.isMaster) {
const Server = require('./server').Server;
const srv = new Server();
// tslint:disable-next-line:no-unused-expression
new Server();
} else {
const Worker = require('./model/threading/Worker').Worker;
Worker.process();

View File

@ -1,5 +1,5 @@
import * as path from 'path';
import * as fs from 'fs';
import {promises as fsp} from 'fs';
import {NextFunction, Request, Response} from 'express';
import {ErrorCodes, ErrorDTO} from '../../common/entities/Error';
import {DirectoryDTO} from '../../common/entities/DirectoryDTO';
@ -18,8 +18,6 @@ import {QueryParams} from '../../common/QueryParams';
import {VideoProcessing} from '../model/fileprocessing/VideoProcessing';
const LOG_TAG = '[GalleryMWs]';
export class GalleryMWs {
@ -27,8 +25,11 @@ export class GalleryMWs {
const directoryName = req.params.directory || '/';
const absoluteDirectoryName = path.join(ProjectPath.ImageFolder, directoryName);
if (!fs.existsSync(absoluteDirectoryName) ||
!fs.statSync(absoluteDirectoryName).isDirectory()) {
try {
if ((await fsp.stat(absoluteDirectoryName)).isDirectory() === false) {
return next();
}
} catch (e) {
return next();
}
@ -160,48 +161,54 @@ export class GalleryMWs {
}
}
public static loadFile(req: Request, res: Response, next: NextFunction) {
public static async loadFile(req: Request, res: Response, next: NextFunction) {
if (!(req.params.mediaPath)) {
return next();
}
const fullMediaPath = path.join(ProjectPath.ImageFolder, req.params.mediaPath);
// check if file exist
if (fs.existsSync(fullMediaPath) === false) {
try {
if ((await fsp.stat(fullMediaPath)).isDirectory()) {
return next();
}
} catch (e) {
return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'no such file:' + req.params.mediaPath, 'can\'t find file: ' + fullMediaPath));
}
if (fs.statSync(fullMediaPath).isDirectory()) {
return next();
}
req.resultPipe = fullMediaPath;
return next();
}
public static loadBestFitVideo(req: Request, res: Response, next: NextFunction) {
public static async loadBestFitVideo(req: Request, res: Response, next: NextFunction) {
if (!(req.resultPipe)) {
return next();
}
const fullMediaPath: string = req.resultPipe;
if (fs.statSync(fullMediaPath).isDirectory()) {
return next();
try {
if ((await fsp.stat(fullMediaPath)).isDirectory()) {
return next();
}
} catch (e) {
return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'no such file:' + req.params.mediaPath, 'can\'t find file: ' + fullMediaPath));
}
// check if video does not exist
if (fs.existsSync(fullMediaPath) === false) {
return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'no such file:' + req.resultPipe, 'can\'t find file: ' + fullMediaPath));
}
req.resultPipe = fullMediaPath;
const convertedVideo = VideoProcessing.generateConvertedFilePath(fullMediaPath);
// check if transcoded video exist
if (fs.existsSync(convertedVideo) === true) {
try {
await fsp.access(fullMediaPath);
req.resultPipe = convertedVideo;
} catch (e) {
}
return next();
}

View File

@ -2,7 +2,6 @@ import {NextFunction, Request, Response} from 'express';
import {UserRoles} from '../../common/entities/UserDTO';
import {NotificationManager} from '../model/NotifocationManager';
const LOG_TAG = '[NotificationMWs]';
export class NotificationMWs {

View File

@ -5,8 +5,6 @@ import {PersonDTO} from '../../common/entities/PersonDTO';
import {PhotoDTO} from '../../common/entities/PhotoDTO';
const LOG_TAG = '[PersonMWs]';
export class PersonMWs {

View File

@ -6,7 +6,6 @@ import {Config} from '../../common/config/private/Config';
import {QueryParams} from '../../common/QueryParams';
import * as path from 'path';
const LOG_TAG = '[SharingMWs]';
export class SharingMWs {

View File

@ -4,8 +4,6 @@ import {ErrorCodes, ErrorDTO} from '../../common/entities/Error';
import {CustomHeaders} from '../../common/CustomHeaders';
const LOG_TAG = '[VersionMWs]';
export class VersionMWs {

View File

@ -5,7 +5,6 @@ import {Config} from '../../../common/config/private/Config';
import {ISQLGalleryManager} from '../../model/database/sql/IGalleryManager';
import {ServerConfig} from '../../../common/config/private/IPrivateConfig';
const LOG_TAG = '[AdminMWs]';
export class AdminMWs {

View File

@ -2,8 +2,6 @@ import {LoginCredential} from '../../../common/entities/LoginCredential';
import {UserEntity} from '../../model/database/sql/enitites/UserEntity';
declare global {
namespace Express {
interface Request {
@ -18,6 +16,7 @@ declare global {
interface Response {
tpl?: any;
}
interface Session {
user?: UserEntity;
rememberMe?: boolean;

View File

@ -8,7 +8,6 @@ import {PersonDTO} from '../../../../common/entities/PersonDTO';
import {Utils} from '../../../../common/Utils';
import {SelectQueryBuilder} from 'typeorm';
const LOG_TAG = '[PersonManager]';
export class PersonManager implements IPersonManager {
samplePhotos: { [key: string]: PhotoDTO } = {};
@ -73,7 +72,8 @@ export class PersonManager implements IPersonManager {
for (let i = 0; i < rawAndEntities.raw.length; ++i) {
this.samplePhotos[rawAndEntities.raw[i].person_name.toLowerCase()] =
Utils.clone(rawAndEntities.entities.find(m => m.name === rawAndEntities.raw[i].media_name));
this.samplePhotos[rawAndEntities.raw[i].person_name.toLowerCase()].metadata.faces = [FaceRegionEntry.fromRawToDTO(rawAndEntities.raw[i])];
this.samplePhotos[rawAndEntities.raw[i].person_name.toLowerCase()].metadata.faces =
[FaceRegionEntry.fromRawToDTO(rawAndEntities.raw[i])];
}
}

View File

@ -185,7 +185,7 @@ export class SQLConnection {
return driver;
}
public static getSQLiteDB(config: ServerConfig.DataBaseConfig){
public static getSQLiteDB(config: ServerConfig.DataBaseConfig) {
return path.join(ProjectPath.getAbsolutePath(config.dbFolder), 'sqlite.db');
}

View File

@ -5,8 +5,6 @@ import {SQLConnection} from './SQLConnection';
import {DirectoryEntity} from './enitites/DirectoryEntity';
import {MediaEntity} from './enitites/MediaEntity';
const LOG_TAG = '[VersionManager]';
export class VersionManager implements IVersionManager {
private allMediaCount = 0;

View File

@ -1,4 +1,4 @@
import {Column, Entity, ManyToOne, PrimaryGeneratedColumn, Index} from 'typeorm';
import {Column, Entity, Index, ManyToOne, PrimaryGeneratedColumn} from 'typeorm';
import {DirectoryEntity} from './DirectoryEntity';
import {FileDTO} from '../../../../../common/entities/FileDTO';
import {columnCharsetCS} from './EntityUtils';

View File

@ -33,7 +33,6 @@ export class JobProgressManager {
}
onJobProgressUpdate(progress: JobProgressDTO) {
this.db.progresses[progress.HashName] = {progress: progress, timestamp: Date.now()};
this.delayedSave();

View File

@ -4,7 +4,6 @@ import {ConfigTemplateEntry, DefaultsJobs} from '../../../../common/entities/job
import {Job} from './Job';
import {ServerConfig} from '../../../../common/config/private/IPrivateConfig';
const LOG_TAG = '[DBRestJob]';
export class DBRestJob extends Job {
public readonly Name = DefaultsJobs[DefaultsJobs['Database Reset']];

View File

@ -101,7 +101,7 @@ export abstract class FileJob<S extends { indexedOnly: boolean } = { indexedOnly
for (let i = 0; i < scanned.directories.length; i++) {
this.directoryQueue.push(path.join(scanned.directories[i].path, scanned.directories[i].name));
}
if (this.scanFilter.noVideo !== true || this.scanFilter.noVideo !== true) {
if (this.scanFilter.noPhoto !== true || this.scanFilter.noVideo !== true) {
this.fileQueue.push(...(await this.filterMediaFiles(scanned.media))
.map(f => path.join(ProjectPath.ImageFolder, f.directory.path, f.directory.name, f.name)));
}

View File

@ -1,12 +1,7 @@
import {Config} from '../../../../common/config/private/Config';
import {DefaultsJobs} from '../../../../common/entities/job/JobDTO';
import {ProjectPath} from '../../../ProjectPath';
import * as path from 'path';
import {FileJob} from './FileJob';
import {PhotoProcessing} from '../../fileprocessing/PhotoProcessing';
import {FileDTO} from '../../../../common/entities/FileDTO';
const LOG_TAG = '[PhotoConvertingJob]';
export class PhotoConvertingJob extends FileJob {

View File

@ -8,8 +8,6 @@ import {PhotoProcessing} from '../../fileprocessing/PhotoProcessing';
import {VideoProcessing} from '../../fileprocessing/VideoProcessing';
import * as rimraf from 'rimraf';
const LOG_TAG = '[TempFolderCleaningJob]';
const rimrafPR = util.promisify(rimraf);
@ -74,7 +72,6 @@ export class TempFolderCleaningJob extends Job {
}
return true;

View File

@ -3,7 +3,6 @@ import {DefaultsJobs} from '../../../../common/entities/job/JobDTO';
import {FileJob} from './FileJob';
import {VideoProcessing} from '../../fileprocessing/VideoProcessing';
const LOG_TAG = '[VideoConvertingJob]';
declare const global: any;

View File

@ -12,8 +12,6 @@ import {SupportedFormats} from '../../../common/SupportedFormats';
import {VideoProcessing} from '../fileprocessing/VideoProcessing';
import {PhotoProcessing} from '../fileprocessing/PhotoProcessing';
const LOG_TAG = '[DiskMangerWorker]';
export class DiskMangerWorker {

View File

@ -84,7 +84,6 @@ export class VideoRendererFactory {
if (!width || !height) {
return reject('[FFmpeg] Can not read video dimension');
}
const ratio = height / width;
const command: FfmpegCommand = ffmpeg(input.mediaPath);
const fileName = path.basename(input.outPath);
const folder = path.dirname(input.outPath);
@ -192,16 +191,7 @@ export class ImageRendererFactory {
const image: Sharp = sharp(input.mediaPath, {failOnError: false});
const metadata: Metadata = await image.metadata();
/**
* newWidth * newHeight = size*size
* newHeight/newWidth = height/width
*
* newHeight = (height/width)*newWidth
* newWidth * newWidth = (size*size) / (height/width)
*
* @type {number}
*/
const ratio = metadata.height / metadata.width;
const kernel = input.qualityPriority === true ? sharp.kernel.lanczos3 : sharp.kernel.nearest;
if (input.cut) {

View File

@ -1,6 +1,6 @@
import {DiskMangerWorker} from './DiskMangerWorker';
import {Logger} from '../../Logger';
import {RendererInput, PhotoWorker} from './PhotoWorker';
import {PhotoWorker, RendererInput} from './PhotoWorker';
import {DirectoryDTO} from '../../../common/entities/DirectoryDTO';
import {Utils} from '../../../common/Utils';
import {ServerConfig} from '../../../common/config/private/IPrivateConfig';

View File

@ -1,9 +1,7 @@
import {RenderingMWs} from '../middlewares/RenderingMWs';
import {ErrorCodes, ErrorDTO} from '../../common/entities/Error';
import {Logger} from '../Logger';
import Request = Express.Request;
import Response = Express.Response;
import {Express} from 'express';
import {Express, Request, Response} from 'express';
export class ErrorRouter {
public static route(app: Express) {

View File

@ -9,7 +9,6 @@ import {ObjectManagers} from './model/ObjectManagers';
import {Logger} from './Logger';
import {Config} from '../common/config/private/Config';
import {LoggerRouter} from './routes/LoggerRouter';
import {ThumbnailGeneratorMWs} from './middlewares/thumbnail/ThumbnailGeneratorMWs';
import {DiskManager} from './model/DiskManger';
import {ConfigDiagnostics} from './model/diagnostics/ConfigDiagnostics';
import {Localizations} from './model/Localizations';
@ -17,6 +16,7 @@ import {CookieNames} from '../common/CookieNames';
import {Router} from './routes/Router';
import {ServerConfig} from '../common/config/private/IPrivateConfig';
import {PhotoProcessing} from './model/fileprocessing/PhotoProcessing';
import * as _csrf from 'csurf';
const _session = require('cookie-session');
@ -56,15 +56,10 @@ export class Server {
/**
* Session above all
*/
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
this.app.use(_session({
name: CookieNames.session,
keys: ['key1' + s4() + s4() + s4() + s4(), 'key2' + s4() + s4() + s4() + s4(), 'key3' + s4() + s4() + s4() + s4()]
keys: Config.Server.sessionSecret
}));
@ -74,6 +69,7 @@ export class Server {
// for parsing application/json
this.app.use(_bodyParser.json());
this.app.use(cookieParser());
this.app.use(_csrf({cookie: true}));
DiskManager.init();
PhotoProcessing.init();

View File

@ -60,6 +60,17 @@ export class ConfigClass extends PrivateConfigDefaultsClass implements IPrivateC
throw new Error('Unknown Server.log.level, found: ' + this.Server.Log.sqlLevel);
}
if (Array.isArray(this.Server.sessionSecret) === false) {
const s4 = (): string => {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
};
this.Server.sessionSecret = ['key1' + s4() + s4() + s4() + s4(),
'key2' + s4() + s4() + s4() + s4(),
'key3' + s4() + s4() + s4() + s4()];
}
}
public save() {

View File

@ -115,6 +115,7 @@ export module ServerConfig {
export interface Config {
sessionSecret: string[];
port: number;
host: string;
Media: MediaConfig;

View File

@ -10,6 +10,7 @@ export class PrivateConfigDefaultsClass extends PublicConfigClass implements IPr
public Server: ServerConfig.Config = {
port: 80,
sessionSecret: null,
host: '0.0.0.0',
Media: {
folder: 'demo/images',

View File

@ -25,7 +25,7 @@ export class AppComponent implements OnInit, OnDestroy {
async ngOnInit() {
this._title.setTitle(Config.Client.applicationTitle);
await this._shareService.wait();
this.subscription = this._authenticationService.user.subscribe((user: UserDTO) => {
this.subscription = this._authenticationService.user.subscribe(() => {
if (this._authenticationService.isAuthenticated()) {
if (this.isLoginPage()) {
return this.toGallery();

View File

@ -34,7 +34,7 @@ export class GalleryComponent implements OnInit, OnDestroy {
public directories: DirectoryDTO[] = [];
public isPhotoWithLocation = false;
public countDown: { day: number, hour: number, minute: number, second: number } = null;
public mapEnabled = true;
public readonly mapEnabled: boolean;
readonly SearchTypes: typeof SearchTypes;
private $counter: Observable<number>;
private subscription: { [key: string]: Subscription } = {

View File

@ -10,7 +10,6 @@ import {ScheduledJobsService} from '../scheduled-jobs.service';
import {ServerConfig} from '../../../../../common/config/private/IPrivateConfig';
import {Utils} from '../../../../../common/Utils';
import {DefaultsJobs, JobDTO} from '../../../../../common/entities/job/JobDTO';
import {ErrorDTO} from '../../../../../common/entities/Error';
import {JobProgressStates} from '../../../../../common/entities/job/JobProgressDTO';