identity-admin 1.25.18 → 1.25.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/controllers/DashboardController.d.ts +1 -0
- package/lib/controllers/DashboardController.js +108 -0
- package/lib/helpers/ReportsGenerator.d.ts +11 -0
- package/lib/helpers/ReportsGenerator.js +43 -0
- package/lib/helpers/RportsGenerator.d.ts +10 -0
- package/lib/helpers/RportsGenerator.js +21 -0
- package/lib/pdf/ReportTemplate.d.ts +71 -0
- package/lib/pdf/ReportTemplate.js +94 -0
- package/package.json +8 -2
|
@@ -34,6 +34,7 @@ export default class DashboardController {
|
|
|
34
34
|
index(req: IRequest, res: Response): Promise<void | Response<any, Record<string, any>>>;
|
|
35
35
|
create(req: IRequest, res: Response): Promise<void>;
|
|
36
36
|
update(req: IRequest, res: Response): Promise<void | Response<any, Record<string, any>>>;
|
|
37
|
+
report(req: IRequest, res: Response): Promise<void>;
|
|
37
38
|
show(req: IRequest, res: Response): Promise<void | Response<any, Record<string, any>>>;
|
|
38
39
|
deleteAll(req: IRequest, res: Response): Promise<void | Response<any, Record<string, any>>>;
|
|
39
40
|
delete(req: IRequest, res: Response): Promise<void | Response<any, Record<string, any>>>;
|
|
@@ -37,6 +37,7 @@ const LocalizedStringHelper_1 = __importDefault(require("../helpers/LocalizedStr
|
|
|
37
37
|
const ActionsGenerator_1 = __importDefault(require("../helpers/ActionsGenerator"));
|
|
38
38
|
const helpers_1 = require("../types/helpers");
|
|
39
39
|
const PopulationHelper_1 = require("../helpers/PopulationHelper");
|
|
40
|
+
const ReportsGenerator_1 = __importDefault(require("../helpers/ReportsGenerator"));
|
|
40
41
|
let DashboardController = DashboardController_1 = class DashboardController {
|
|
41
42
|
constructor(resource, repository, resources, modelConfigurations) {
|
|
42
43
|
this.resource = resource;
|
|
@@ -355,6 +356,108 @@ let DashboardController = DashboardController_1 = class DashboardController {
|
|
|
355
356
|
});
|
|
356
357
|
});
|
|
357
358
|
}
|
|
359
|
+
report(req, res) {
|
|
360
|
+
var _a, _b, _c;
|
|
361
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
362
|
+
if (!this.validateRequest(req, res)) {
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
const searchableSubString = req.query.filter
|
|
366
|
+
? new RegExp(req.query.filter, "i")
|
|
367
|
+
: undefined;
|
|
368
|
+
const scope = req.query.scope;
|
|
369
|
+
const currentUser = req.user;
|
|
370
|
+
const modelName = req.params.resource;
|
|
371
|
+
const filtersQuery = req.query.filters;
|
|
372
|
+
const filters = filtersQuery
|
|
373
|
+
? filtersQuery.split("^^")
|
|
374
|
+
: undefined;
|
|
375
|
+
const resource = (_a = this.resource) !== null && _a !== void 0 ? _a : (0, ResourceUtils_1.getResource)(modelName, (_b = this.resources) !== null && _b !== void 0 ? _b : []);
|
|
376
|
+
if (!resource) {
|
|
377
|
+
return ResponseUtils_1.default.notFound(res, "Resource not found", []);
|
|
378
|
+
}
|
|
379
|
+
if (!currentUser) {
|
|
380
|
+
return ResponseUtils_1.default.unauthorized(res);
|
|
381
|
+
}
|
|
382
|
+
const permissionCheck = resource.properties.isAllowed
|
|
383
|
+
? yield resource.properties.isAllowed(currentUser)
|
|
384
|
+
: true;
|
|
385
|
+
if (!permissionCheck) {
|
|
386
|
+
return ResponseUtils_1.default.forbidden(res);
|
|
387
|
+
}
|
|
388
|
+
const repository = (_c = this.repository) !== null && _c !== void 0 ? _c : new Repository_1.default(resource.properties.resource);
|
|
389
|
+
const modifiedResource = ResourceGenerator_1.default.generate(resource, currentUser, undefined, this.modelConfigurations);
|
|
390
|
+
const sort = req.query.order;
|
|
391
|
+
const sortBy = req.query.orderBy;
|
|
392
|
+
const sortQuery = {};
|
|
393
|
+
sortQuery[sortBy] = sort;
|
|
394
|
+
if (sortBy !== "_id") {
|
|
395
|
+
sortQuery._id = "asc";
|
|
396
|
+
}
|
|
397
|
+
var filter = {};
|
|
398
|
+
if (scope &&
|
|
399
|
+
resource.properties.filters &&
|
|
400
|
+
resource.properties.filters.scopes &&
|
|
401
|
+
resource.properties.filters.scopes.isAccessible) {
|
|
402
|
+
if (resource.properties.filters.scopes.manual) {
|
|
403
|
+
filter = yield resource.properties.filters.scopes.manual.handler(filter, scope, currentUser);
|
|
404
|
+
}
|
|
405
|
+
else if (resource.properties.filters.scopes.auto) {
|
|
406
|
+
const key = resource.properties.filters.scopes.auto.key;
|
|
407
|
+
if (key) {
|
|
408
|
+
filter[key] = scope;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
if (searchableSubString) {
|
|
413
|
+
filter = this.getSearchableSubStringFilter(resource, filter, searchableSubString);
|
|
414
|
+
}
|
|
415
|
+
filter = yield FiltersHelper_1.default.appendFilters(filter, filters, resource);
|
|
416
|
+
const crudOperations = resource.properties.crudOperations;
|
|
417
|
+
if (crudOperations && crudOperations.index && crudOperations.index.before) {
|
|
418
|
+
filter = yield crudOperations.index.before(req, filter, currentUser);
|
|
419
|
+
}
|
|
420
|
+
var records = [];
|
|
421
|
+
const populatedString = modifiedResource.properties.populatedString;
|
|
422
|
+
const populationHelper = new PopulationHelper_1.PopulationHelper(resource, PopulationHelper_1.PopulationType.LIST, populatedString);
|
|
423
|
+
const modifiedPopulatedObject = yield populationHelper.get();
|
|
424
|
+
records = yield repository.findMany({
|
|
425
|
+
sort: sortQuery,
|
|
426
|
+
filter,
|
|
427
|
+
populate: modifiedPopulatedObject,
|
|
428
|
+
});
|
|
429
|
+
var documents = [];
|
|
430
|
+
var documents = [];
|
|
431
|
+
for (var i = 0; i < records.length; i++) {
|
|
432
|
+
const record = records[i];
|
|
433
|
+
const recordFlatten = record.toObject();
|
|
434
|
+
documents.push(recordFlatten);
|
|
435
|
+
}
|
|
436
|
+
if (crudOperations && crudOperations.index && crudOperations.index.after) {
|
|
437
|
+
documents = yield crudOperations.index.after(req, documents, currentUser);
|
|
438
|
+
}
|
|
439
|
+
const fields = req.query.fields.map(v => JSON.parse(v));
|
|
440
|
+
const fileType = req.query.fileType;
|
|
441
|
+
if (fileType === 'xlsx') {
|
|
442
|
+
const buffer = ReportsGenerator_1.default.CreateXlsxFile(fields, documents, modelName);
|
|
443
|
+
res.writeHead(200, {
|
|
444
|
+
'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
445
|
+
'Content-disposition': 'attachment;filename=' + `${modelName}.xlsx`,
|
|
446
|
+
'Content-Length': buffer.length,
|
|
447
|
+
});
|
|
448
|
+
res.end(buffer);
|
|
449
|
+
}
|
|
450
|
+
if (fileType === 'pdf') {
|
|
451
|
+
const buffer = yield ReportsGenerator_1.default.CreatePdfFile(fields, documents, modelName);
|
|
452
|
+
res.writeHead(200, {
|
|
453
|
+
'Content-Type': 'application/pdf',
|
|
454
|
+
'Content-disposition': 'attachment;filename=' + `${modelName}.pdf`,
|
|
455
|
+
'Content-Length': buffer.length,
|
|
456
|
+
});
|
|
457
|
+
res.end(buffer);
|
|
458
|
+
}
|
|
459
|
+
});
|
|
460
|
+
}
|
|
358
461
|
show(req, res) {
|
|
359
462
|
var _a, _b, _c, _d, _e;
|
|
360
463
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -572,6 +675,11 @@ __decorate([
|
|
|
572
675
|
__param(0, (0, inversify_express_utils_1.request)()),
|
|
573
676
|
__param(1, (0, inversify_express_utils_1.response)())
|
|
574
677
|
], DashboardController.prototype, "update", null);
|
|
678
|
+
__decorate([
|
|
679
|
+
(0, inversify_express_utils_1.httpGet)("/report"),
|
|
680
|
+
__param(0, (0, inversify_express_utils_1.request)()),
|
|
681
|
+
__param(1, (0, inversify_express_utils_1.response)())
|
|
682
|
+
], DashboardController.prototype, "report", null);
|
|
575
683
|
__decorate([
|
|
576
684
|
(0, inversify_express_utils_1.httpGet)("/:id"),
|
|
577
685
|
__param(0, (0, inversify_express_utils_1.request)()),
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { FieldTypes } from '../types/helpers';
|
|
3
|
+
export interface Columns {
|
|
4
|
+
label: string;
|
|
5
|
+
value: string;
|
|
6
|
+
type: FieldTypes;
|
|
7
|
+
}
|
|
8
|
+
export default class ReportsGenerator {
|
|
9
|
+
static CreateXlsxFile(columns: Columns[], data: any[], name: string): Buffer;
|
|
10
|
+
static CreatePdfFile(columns: Columns[], data: any[], name: string): Promise<Buffer>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const node_xlsx_1 = __importDefault(require("node-xlsx"));
|
|
16
|
+
const lodash_1 = require("lodash");
|
|
17
|
+
const helpers_1 = require("../types/helpers");
|
|
18
|
+
const renderer_1 = require("@react-pdf/renderer");
|
|
19
|
+
const ReportTemplate_1 = __importDefault(require("../pdf/ReportTemplate"));
|
|
20
|
+
class ReportsGenerator {
|
|
21
|
+
static CreateXlsxFile(columns, data, name) {
|
|
22
|
+
const header = columns.map((field) => field.label);
|
|
23
|
+
const rows = data.map((row) => columns.map((field) => (field.type === helpers_1.FieldTypes.OBJECTID ? (0, lodash_1.get)(row, field.value).toString() : (0, lodash_1.get)(row, field.value))));
|
|
24
|
+
const sheets = [
|
|
25
|
+
{
|
|
26
|
+
name,
|
|
27
|
+
data: [header, ...rows],
|
|
28
|
+
options: {},
|
|
29
|
+
},
|
|
30
|
+
];
|
|
31
|
+
const buffer = node_xlsx_1.default.build(sheets);
|
|
32
|
+
return buffer;
|
|
33
|
+
}
|
|
34
|
+
static CreatePdfFile(columns, data, name) {
|
|
35
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
36
|
+
const header = columns.map((field) => field.label);
|
|
37
|
+
const rows = data.map((row) => columns.map((field) => (field.type === helpers_1.FieldTypes.OBJECTID ? (0, lodash_1.get)(row, field.value).toString() : (0, lodash_1.get)(row, field.value))));
|
|
38
|
+
const pdf = yield (0, renderer_1.renderToBuffer)((0, ReportTemplate_1.default)({ columns: header, rows }));
|
|
39
|
+
return pdf;
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
exports.default = ReportsGenerator;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { FieldTypes } from "../types/helpers";
|
|
2
|
+
interface Columns {
|
|
3
|
+
label: string;
|
|
4
|
+
value: string;
|
|
5
|
+
type: FieldTypes;
|
|
6
|
+
}
|
|
7
|
+
export default class ReportsGenerator {
|
|
8
|
+
static CreateXlsxFile(columns: Columns[], data: any[], name: string): void;
|
|
9
|
+
}
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const node_xlsx_1 = __importDefault(require("node-xlsx"));
|
|
7
|
+
const lodash_1 = require("lodash");
|
|
8
|
+
const helpers_1 = require("../types/helpers");
|
|
9
|
+
class ReportsGenerator {
|
|
10
|
+
static CreateXlsxFile(columns, data, name) {
|
|
11
|
+
const header = columns.map(field => field.label);
|
|
12
|
+
const rows = data.map(row => columns.map(field => field.type === helpers_1.FieldTypes.OBJECTID ? (0, lodash_1.get)(row, field.value).toString() : (0, lodash_1.get)(row, field.value)));
|
|
13
|
+
const sheets = [{
|
|
14
|
+
name,
|
|
15
|
+
data: [header, ...rows],
|
|
16
|
+
options: {}
|
|
17
|
+
}];
|
|
18
|
+
const buffer = node_xlsx_1.default.build(sheets);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
exports.default = ReportsGenerator;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export declare const styles: {
|
|
3
|
+
table: {
|
|
4
|
+
display: "flex";
|
|
5
|
+
width: string;
|
|
6
|
+
borderStyle: "solid";
|
|
7
|
+
borderWidth: number;
|
|
8
|
+
borderRightWidth: number;
|
|
9
|
+
borderBottomWidth: number;
|
|
10
|
+
};
|
|
11
|
+
tableRow: {
|
|
12
|
+
width: string;
|
|
13
|
+
margin: string;
|
|
14
|
+
flexDirection: "row";
|
|
15
|
+
};
|
|
16
|
+
tableCol: {
|
|
17
|
+
width: string;
|
|
18
|
+
borderStyle: "solid";
|
|
19
|
+
borderWidth: number;
|
|
20
|
+
borderLeftWidth: number;
|
|
21
|
+
borderTopWidth: number;
|
|
22
|
+
};
|
|
23
|
+
tableCell: {
|
|
24
|
+
width: string;
|
|
25
|
+
margin: string;
|
|
26
|
+
marginTop: number;
|
|
27
|
+
fontSize: number;
|
|
28
|
+
overflow: "hidden";
|
|
29
|
+
};
|
|
30
|
+
flexRow: {
|
|
31
|
+
display: "flex";
|
|
32
|
+
flexDirection: "row";
|
|
33
|
+
alignItems: "flex-start";
|
|
34
|
+
alignContent: "flex-start";
|
|
35
|
+
justifyContent: "flex-start";
|
|
36
|
+
marginTop: string;
|
|
37
|
+
};
|
|
38
|
+
detailsTitle: {
|
|
39
|
+
fontSize: string;
|
|
40
|
+
textAlign: "left";
|
|
41
|
+
color: string;
|
|
42
|
+
fontWeight: number;
|
|
43
|
+
marginBottom: string;
|
|
44
|
+
};
|
|
45
|
+
detailsBody: {
|
|
46
|
+
fontSize: string;
|
|
47
|
+
textAlign: "left";
|
|
48
|
+
color: string;
|
|
49
|
+
fontWeight: number;
|
|
50
|
+
marginBottom: string;
|
|
51
|
+
};
|
|
52
|
+
flexColumn: {
|
|
53
|
+
display: "flex";
|
|
54
|
+
flexDirection: "column";
|
|
55
|
+
alignItems: "flex-start";
|
|
56
|
+
alignContent: "flex-start";
|
|
57
|
+
justifyContent: "flex-start";
|
|
58
|
+
};
|
|
59
|
+
flexWrap: {
|
|
60
|
+
flexWrap: "wrap";
|
|
61
|
+
};
|
|
62
|
+
borderTopBottom: {
|
|
63
|
+
borderTop: string;
|
|
64
|
+
borderBottom: string;
|
|
65
|
+
padding: string;
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
export default function ReportTemplate({ columns, rows }: {
|
|
69
|
+
columns: string[];
|
|
70
|
+
rows: any[][];
|
|
71
|
+
}): React.JSX.Element;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.styles = void 0;
|
|
7
|
+
const react_1 = __importDefault(require("react"));
|
|
8
|
+
const renderer_1 = require("@react-pdf/renderer");
|
|
9
|
+
exports.styles = renderer_1.StyleSheet.create({
|
|
10
|
+
table: {
|
|
11
|
+
display: 'flex',
|
|
12
|
+
width: 'auto',
|
|
13
|
+
borderStyle: 'solid',
|
|
14
|
+
borderWidth: 1,
|
|
15
|
+
borderRightWidth: 0,
|
|
16
|
+
borderBottomWidth: 0,
|
|
17
|
+
},
|
|
18
|
+
tableRow: {
|
|
19
|
+
width: '100%',
|
|
20
|
+
margin: 'auto',
|
|
21
|
+
flexDirection: 'row',
|
|
22
|
+
},
|
|
23
|
+
tableCol: {
|
|
24
|
+
width: '100%',
|
|
25
|
+
borderStyle: 'solid',
|
|
26
|
+
borderWidth: 1,
|
|
27
|
+
borderLeftWidth: 0,
|
|
28
|
+
borderTopWidth: 0,
|
|
29
|
+
},
|
|
30
|
+
tableCell: {
|
|
31
|
+
width: '100%',
|
|
32
|
+
margin: 'auto',
|
|
33
|
+
marginTop: 5,
|
|
34
|
+
fontSize: 18,
|
|
35
|
+
overflow: 'hidden'
|
|
36
|
+
},
|
|
37
|
+
flexRow: {
|
|
38
|
+
display: 'flex',
|
|
39
|
+
flexDirection: 'row',
|
|
40
|
+
alignItems: 'flex-start',
|
|
41
|
+
alignContent: 'flex-start',
|
|
42
|
+
justifyContent: 'flex-start',
|
|
43
|
+
marginTop: '24t',
|
|
44
|
+
},
|
|
45
|
+
detailsTitle: {
|
|
46
|
+
fontSize: '18',
|
|
47
|
+
textAlign: 'left',
|
|
48
|
+
color: '#637381',
|
|
49
|
+
fontWeight: 500,
|
|
50
|
+
marginBottom: '8',
|
|
51
|
+
},
|
|
52
|
+
detailsBody: {
|
|
53
|
+
fontSize: '18',
|
|
54
|
+
textAlign: 'left',
|
|
55
|
+
color: '#000',
|
|
56
|
+
fontWeight: 500,
|
|
57
|
+
marginBottom: '8',
|
|
58
|
+
},
|
|
59
|
+
flexColumn: {
|
|
60
|
+
display: 'flex',
|
|
61
|
+
flexDirection: 'column',
|
|
62
|
+
alignItems: 'flex-start',
|
|
63
|
+
alignContent: 'flex-start',
|
|
64
|
+
justifyContent: 'flex-start',
|
|
65
|
+
},
|
|
66
|
+
flexWrap: {
|
|
67
|
+
flexWrap: 'wrap',
|
|
68
|
+
},
|
|
69
|
+
borderTopBottom: {
|
|
70
|
+
borderTop: '2px solid #000',
|
|
71
|
+
borderBottom: '2px solid #000',
|
|
72
|
+
padding: '10px',
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
function ReportTemplate({ columns, rows }) {
|
|
76
|
+
return (react_1.default.createElement(renderer_1.Document, null,
|
|
77
|
+
react_1.default.createElement(renderer_1.Page, { size: "A2", orientation: "landscape", style: {
|
|
78
|
+
padding: '4pt',
|
|
79
|
+
paddingTop: '8pt',
|
|
80
|
+
} },
|
|
81
|
+
react_1.default.createElement(renderer_1.View, { style: [exports.styles.flexRow, { marginTop: '8pt', marginBottom: '16pt', marginLeft: '48pt', marginRight: '64pt', justifyContent: 'space-between', alignItems: 'center' }] },
|
|
82
|
+
react_1.default.createElement(renderer_1.Image, { style: {
|
|
83
|
+
width: 'auto',
|
|
84
|
+
height: '32px',
|
|
85
|
+
}, src: `public/logo.png` })),
|
|
86
|
+
react_1.default.createElement(renderer_1.View, { style: exports.styles.table },
|
|
87
|
+
react_1.default.createElement(renderer_1.View, { style: Object.assign(Object.assign({}, exports.styles.tableRow), { backgroundColor: 'black', color: 'white' }) }, columns.map((column) => (react_1.default.createElement(renderer_1.View, { style: exports.styles.tableCol, key: column },
|
|
88
|
+
react_1.default.createElement(renderer_1.Text, { style: exports.styles.tableCell }, column))))),
|
|
89
|
+
rows.map((row, index) => {
|
|
90
|
+
return (react_1.default.createElement(renderer_1.View, { style: exports.styles.tableRow, key: index }, row.map((cell) => (react_1.default.createElement(renderer_1.View, { style: exports.styles.tableCol, key: index * 10 },
|
|
91
|
+
react_1.default.createElement(renderer_1.Text, { style: [exports.styles.tableCell] }, `${cell}`))))));
|
|
92
|
+
})))));
|
|
93
|
+
}
|
|
94
|
+
exports.default = ReportTemplate;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "identity-admin",
|
|
3
|
-
"version": "1.25.
|
|
3
|
+
"version": "1.25.19",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "lib/Dashboard.js",
|
|
6
6
|
"types": "lib/Dashbord.d.ts",
|
|
@@ -26,8 +26,10 @@
|
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/express": "^4.17.14",
|
|
28
28
|
"@types/i18n": "^0.13.4",
|
|
29
|
+
"@types/lodash": "^4.14.202",
|
|
29
30
|
"@types/mongoose": "^5.11.97",
|
|
30
31
|
"@types/passport-local-mongoose": "^6.1.1",
|
|
32
|
+
"@types/react": "^18.2.45",
|
|
31
33
|
"express": "^4.18.1",
|
|
32
34
|
"express-validator": "^6.14.2",
|
|
33
35
|
"i18n": "^0.15.0",
|
|
@@ -39,13 +41,17 @@
|
|
|
39
41
|
"reflect-metadata": "^0.1.13"
|
|
40
42
|
},
|
|
41
43
|
"dependencies": {
|
|
44
|
+
"@react-pdf/renderer": "^3.1.14",
|
|
42
45
|
"@types/express-session": "^1.17.5",
|
|
43
46
|
"bcryptjs": "^2.4.3",
|
|
44
47
|
"connect-mongo": "^4.6.0",
|
|
45
48
|
"cookie-parser": "^1.4.6",
|
|
46
49
|
"express-session": "^1.17.3",
|
|
50
|
+
"lodash": "^4.17.21",
|
|
51
|
+
"node-xlsx": "^0.21.0",
|
|
47
52
|
"passport": "^0.6.0",
|
|
48
53
|
"passport-local": "^1.0.0",
|
|
49
|
-
"pluralize": "^8.0.0"
|
|
54
|
+
"pluralize": "^8.0.0",
|
|
55
|
+
"typescript": "^4.7.4"
|
|
50
56
|
}
|
|
51
57
|
}
|