identity-admin 1.28.30 → 1.28.32
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 -1
- package/lib/controllers/DashboardController.js +36 -14
- package/lib/helpers/PopulationHelper.d.ts +2 -1
- package/lib/helpers/PopulationHelper.js +10 -1
- package/lib/helpers/ReportsGenerator.d.ts +4 -0
- package/lib/helpers/ReportsGenerator.js +64 -8
- package/lib/repositories/Repository.d.ts +1 -0
- package/lib/repositories/Repository.js +4 -0
- package/lib/types/IResourceFile.d.ts +5 -0
- package/package.json +2 -1
|
@@ -36,7 +36,7 @@ export default class DashboardController {
|
|
|
36
36
|
index(req: IRequest, res: Response): Promise<void | Response<any, Record<string, any>>>;
|
|
37
37
|
create(req: IRequest, res: Response): Promise<void>;
|
|
38
38
|
update(req: IRequest, res: Response): Promise<void | Response<any, Record<string, any>>>;
|
|
39
|
-
report(req: IRequest, res: Response): Promise<void
|
|
39
|
+
report(req: IRequest, res: Response): Promise<void | Response<any, Record<string, any>>>;
|
|
40
40
|
show(req: IRequest, res: Response): Promise<void | Response<any, Record<string, any>>>;
|
|
41
41
|
deleteAll(req: IRequest, res: Response): Promise<void | Response<any, Record<string, any>>>;
|
|
42
42
|
delete(req: IRequest, res: Response): Promise<void | Response<any, Record<string, any>>>;
|
|
@@ -479,21 +479,27 @@ let DashboardController = DashboardController_1 = class DashboardController {
|
|
|
479
479
|
if (crudOperations && crudOperations.index && crudOperations.index.before) {
|
|
480
480
|
filter = yield crudOperations.index.before(req, filter, currentUser);
|
|
481
481
|
}
|
|
482
|
+
const fields = ReportsGenerator_1.default.parseFields(req.query.fields);
|
|
483
|
+
if (fields.length === 0) {
|
|
484
|
+
return ResponseUtils_1.default.send(res, 400, 'fields query parameter is required');
|
|
485
|
+
}
|
|
486
|
+
const select = ReportsGenerator_1.default.buildSelect(fields);
|
|
487
|
+
const columnFieldKeys = ReportsGenerator_1.default.getColumnFieldKeys(fields);
|
|
482
488
|
var records = [];
|
|
483
|
-
const populatedString = modifiedResource.properties.populatedString
|
|
484
|
-
|
|
489
|
+
const populatedString = modifiedResource.properties.populatedString
|
|
490
|
+
.split(' ')
|
|
491
|
+
.filter((field) => columnFieldKeys.some((key) => field === key || field.startsWith(key + '.')))
|
|
492
|
+
.join(' ');
|
|
493
|
+
const populationHelper = new PopulationHelper_1.PopulationHelper(resource, PopulationHelper_1.PopulationType.REPORT, populatedString);
|
|
485
494
|
const modifiedPopulatedObject = yield populationHelper.get();
|
|
486
495
|
records = yield repository.findMany({
|
|
487
496
|
sort: sortQuery,
|
|
488
497
|
filter,
|
|
489
498
|
populate: modifiedPopulatedObject,
|
|
499
|
+
select,
|
|
500
|
+
lean: true,
|
|
490
501
|
});
|
|
491
|
-
var documents =
|
|
492
|
-
for (var i = 0; i < records.length; i++) {
|
|
493
|
-
const record = records[i];
|
|
494
|
-
const recordFlatten = record.toObject();
|
|
495
|
-
documents.push(recordFlatten);
|
|
496
|
-
}
|
|
502
|
+
var documents = records;
|
|
497
503
|
if (crudOperations && crudOperations.index && crudOperations.index.after) {
|
|
498
504
|
try {
|
|
499
505
|
documents = yield crudOperations.index.after(req, documents, currentUser);
|
|
@@ -502,18 +508,15 @@ let DashboardController = DashboardController_1 = class DashboardController {
|
|
|
502
508
|
documents = yield crudOperations.index.after(req, records, currentUser);
|
|
503
509
|
}
|
|
504
510
|
}
|
|
505
|
-
const fields = req.query.fields.map((v) => JSON.parse(v));
|
|
506
511
|
const fileType = req.query.fileType;
|
|
507
512
|
if (fileType === 'xlsx') {
|
|
508
|
-
const buffer = ReportsGenerator_1.default.CreateXlsxFile(fields, documents, modelName, language, resource);
|
|
509
513
|
res.writeHead(200, {
|
|
510
514
|
'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
511
|
-
'Content-disposition':
|
|
512
|
-
'Content-Length': buffer.length,
|
|
515
|
+
'Content-disposition': `attachment;filename=${modelName}.xlsx`,
|
|
513
516
|
});
|
|
514
|
-
|
|
517
|
+
yield ReportsGenerator_1.default.CreateXlsxStream(fields, documents, modelName, language, resource, res);
|
|
515
518
|
}
|
|
516
|
-
if (fileType === 'pdf') {
|
|
519
|
+
else if (fileType === 'pdf') {
|
|
517
520
|
const buffer = yield ReportsGenerator_1.default.CreatePdfFile(fields, documents, modelName, language, resource);
|
|
518
521
|
res.writeHead(200, {
|
|
519
522
|
'Content-Type': 'application/pdf',
|
|
@@ -522,6 +525,25 @@ let DashboardController = DashboardController_1 = class DashboardController {
|
|
|
522
525
|
});
|
|
523
526
|
res.end(buffer);
|
|
524
527
|
}
|
|
528
|
+
else if (fileType === 'csv') {
|
|
529
|
+
res.writeHead(200, {
|
|
530
|
+
'Content-Type': 'text/csv; charset=utf-8',
|
|
531
|
+
'Content-disposition': `attachment;filename=${modelName}.csv`,
|
|
532
|
+
});
|
|
533
|
+
res.write('\uFEFF');
|
|
534
|
+
res.write(fields.map((f) => `"${f.label}"`).join(',') + '\r\n');
|
|
535
|
+
documents.forEach((record) => {
|
|
536
|
+
const row = fields.map((f) => {
|
|
537
|
+
const val = ReportsGenerator_1.default.getFieldValue(f, record, language, resource);
|
|
538
|
+
return `"${String(val !== null && val !== void 0 ? val : '').replace(/"/g, '""')}"`;
|
|
539
|
+
}).join(',');
|
|
540
|
+
res.write(row + '\r\n');
|
|
541
|
+
});
|
|
542
|
+
res.end();
|
|
543
|
+
}
|
|
544
|
+
if (!fileType) {
|
|
545
|
+
return ResponseUtils_1.default.send(res, 400, 'fileType query parameter is required');
|
|
546
|
+
}
|
|
525
547
|
});
|
|
526
548
|
}
|
|
527
549
|
show(req, res) {
|
|
@@ -14,6 +14,7 @@ var PopulationType;
|
|
|
14
14
|
(function (PopulationType) {
|
|
15
15
|
PopulationType["LIST"] = "LIST";
|
|
16
16
|
PopulationType["SHOW"] = "SHOW";
|
|
17
|
+
PopulationType["REPORT"] = "REPORT";
|
|
17
18
|
})(PopulationType = exports.PopulationType || (exports.PopulationType = {}));
|
|
18
19
|
class PopulationHelper {
|
|
19
20
|
constructor(resource, populationType, populatedString) {
|
|
@@ -27,7 +28,7 @@ class PopulationHelper {
|
|
|
27
28
|
if (!populate) {
|
|
28
29
|
return this.populatedString;
|
|
29
30
|
}
|
|
30
|
-
if (!populate.all && !populate.list && !populate.show) {
|
|
31
|
+
if (!populate.all && !populate.list && !populate.show && !populate.report) {
|
|
31
32
|
return this.populatedString;
|
|
32
33
|
}
|
|
33
34
|
if (populate.all) {
|
|
@@ -38,6 +39,14 @@ class PopulationHelper {
|
|
|
38
39
|
return yield populate.list(this.populatedString);
|
|
39
40
|
}
|
|
40
41
|
}
|
|
42
|
+
else if (this.populationType === PopulationType.REPORT) {
|
|
43
|
+
if (populate.report) {
|
|
44
|
+
return yield populate.report(this.populatedString);
|
|
45
|
+
}
|
|
46
|
+
if (populate.list) {
|
|
47
|
+
return yield populate.list(this.populatedString);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
41
50
|
else {
|
|
42
51
|
if (populate.show) {
|
|
43
52
|
return yield populate.show(this.populatedString);
|
|
@@ -17,10 +17,14 @@ export interface ILanguage {
|
|
|
17
17
|
value?: string;
|
|
18
18
|
}
|
|
19
19
|
export default class ReportsGenerator {
|
|
20
|
+
static CreateXlsxStream(columns: Columns[], data: any[], name: string, language: Languages, resource: IResourceFile, stream: any): Promise<void>;
|
|
20
21
|
static CreateXlsxFile(columns: Columns[], data: any[], name: string, language: Languages, resource: IResourceFile): Buffer;
|
|
21
22
|
static CreatePdfFile(columns: Columns[], data: any[], name: string, language: Languages, resource: IResourceFile): Promise<Buffer>;
|
|
22
23
|
static getRows(columns: Columns[], data: any[], language: Languages, resource: IResourceFile): any[][];
|
|
23
24
|
static getFieldValue(field: Columns, row: any, language: Languages, resource: IResourceFile): any;
|
|
24
25
|
static checkLocalizedStringExistence(columns: Columns[]): boolean;
|
|
26
|
+
static parseFields(queryFields: any): Columns[];
|
|
27
|
+
static buildSelect(fields: Columns[]): Record<string, number>;
|
|
28
|
+
static getColumnFieldKeys(fields: Columns[]): string[];
|
|
25
29
|
static getReferenceValueByTitleType(rowValue: any, language: Languages, titleType?: FieldTypes): any;
|
|
26
30
|
}
|
|
@@ -49,6 +49,24 @@ var Languages;
|
|
|
49
49
|
Languages["ENGLISH"] = "en";
|
|
50
50
|
})(Languages = exports.Languages || (exports.Languages = {}));
|
|
51
51
|
class ReportsGenerator {
|
|
52
|
+
static CreateXlsxStream(columns, data, name, language, resource, stream) {
|
|
53
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
54
|
+
const ExcelJS = require('exceljs');
|
|
55
|
+
const workbook = new ExcelJS.stream.xlsx.WorkbookWriter({
|
|
56
|
+
stream,
|
|
57
|
+
useStyles: false,
|
|
58
|
+
useSharedStrings: false,
|
|
59
|
+
});
|
|
60
|
+
const worksheet = workbook.addWorksheet(name);
|
|
61
|
+
worksheet.addRow(columns.map(f => f.label)).commit();
|
|
62
|
+
data.forEach((record) => {
|
|
63
|
+
const row = columns.map((f) => this.getFieldValue(f, record, language, resource));
|
|
64
|
+
worksheet.addRow(row).commit();
|
|
65
|
+
});
|
|
66
|
+
worksheet.commit();
|
|
67
|
+
yield workbook.commit();
|
|
68
|
+
});
|
|
69
|
+
}
|
|
52
70
|
static CreateXlsxFile(columns, data, name, language, resource) {
|
|
53
71
|
const header = columns.map((field) => field.label);
|
|
54
72
|
const rows = this.getRows(columns, data, language, resource);
|
|
@@ -64,7 +82,6 @@ class ReportsGenerator {
|
|
|
64
82
|
}
|
|
65
83
|
static CreatePdfFile(columns, data, name, language, resource) {
|
|
66
84
|
return __awaiter(this, void 0, void 0, function* () {
|
|
67
|
-
const rows = this.getRows(columns, data, language, resource);
|
|
68
85
|
const ArabicFont = new pdfjs_1.default.Font(fs.readFileSync(__dirname + '/../assets/Amiri-Regular.ttf'));
|
|
69
86
|
const localizedStringIsExisted = this.checkLocalizedStringExistence(columns);
|
|
70
87
|
const doc = new pdfjs_1.default.Document({
|
|
@@ -85,14 +102,17 @@ class ReportsGenerator {
|
|
|
85
102
|
textAlign: 'center',
|
|
86
103
|
alignment: 'center',
|
|
87
104
|
}));
|
|
88
|
-
|
|
105
|
+
data.forEach((record) => {
|
|
89
106
|
const tableRow = table.row();
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
107
|
+
columns.forEach((field) => {
|
|
108
|
+
const value = this.getFieldValue(field, record, language, resource);
|
|
109
|
+
tableRow.cell(`${value !== null && value !== void 0 ? value : '---'}`, {
|
|
110
|
+
textAlign: 'center',
|
|
111
|
+
alignment: 'center',
|
|
112
|
+
paddingBottom: 5,
|
|
113
|
+
paddingTop: 5,
|
|
114
|
+
});
|
|
115
|
+
});
|
|
96
116
|
});
|
|
97
117
|
return yield doc.asBuffer();
|
|
98
118
|
});
|
|
@@ -132,6 +152,42 @@ class ReportsGenerator {
|
|
|
132
152
|
static checkLocalizedStringExistence(columns) {
|
|
133
153
|
return columns.some((column) => column.type === helpers_1.FieldTypes.LOCALIZEDSTRING);
|
|
134
154
|
}
|
|
155
|
+
static parseFields(queryFields) {
|
|
156
|
+
if (!queryFields)
|
|
157
|
+
return [];
|
|
158
|
+
if (Array.isArray(queryFields)) {
|
|
159
|
+
return queryFields.map((v) => (typeof v === 'string' ? JSON.parse(v) : v));
|
|
160
|
+
}
|
|
161
|
+
return [];
|
|
162
|
+
}
|
|
163
|
+
static buildSelect(fields) {
|
|
164
|
+
const select = {};
|
|
165
|
+
fields.forEach((field) => {
|
|
166
|
+
const topField = field.value.split('.')[0];
|
|
167
|
+
select[topField] = 1;
|
|
168
|
+
if (field.titlePath) {
|
|
169
|
+
const topTitlePath = field.titlePath.split('.')[0];
|
|
170
|
+
select[topTitlePath] = 1;
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
return select;
|
|
174
|
+
}
|
|
175
|
+
static getColumnFieldKeys(fields) {
|
|
176
|
+
const keys = [];
|
|
177
|
+
fields.forEach((field) => {
|
|
178
|
+
const topField = field.value.split('.')[0];
|
|
179
|
+
if (!keys.includes(topField)) {
|
|
180
|
+
keys.push(topField);
|
|
181
|
+
}
|
|
182
|
+
if (field.titlePath) {
|
|
183
|
+
const topTitlePath = field.titlePath.split('.')[0];
|
|
184
|
+
if (!keys.includes(topTitlePath)) {
|
|
185
|
+
keys.push(topTitlePath);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
return keys;
|
|
190
|
+
}
|
|
135
191
|
static getReferenceValueByTitleType(rowValue, language, titleType) {
|
|
136
192
|
if (!titleType)
|
|
137
193
|
return rowValue;
|
|
@@ -49,6 +49,7 @@ let Repository = Repository_1 = class Repository {
|
|
|
49
49
|
const limit = this.getLimit(queryOptions);
|
|
50
50
|
const skip = this.getSkip(queryOptions);
|
|
51
51
|
const populate = queryOptions.populate;
|
|
52
|
+
const lean = queryOptions.lean;
|
|
52
53
|
var query = this.model.find(filter);
|
|
53
54
|
if (select) {
|
|
54
55
|
query = query.select(select);
|
|
@@ -65,6 +66,9 @@ let Repository = Repository_1 = class Repository {
|
|
|
65
66
|
if (populate) {
|
|
66
67
|
query = query.populate(populate);
|
|
67
68
|
}
|
|
69
|
+
if (lean) {
|
|
70
|
+
query = query.lean();
|
|
71
|
+
}
|
|
68
72
|
return yield query;
|
|
69
73
|
});
|
|
70
74
|
}
|
|
@@ -36,6 +36,11 @@ interface IPopulate {
|
|
|
36
36
|
* This function is called for the get one endpoint either in show or form an access over the populated string
|
|
37
37
|
*/
|
|
38
38
|
show?: PopulateFunction;
|
|
39
|
+
/**
|
|
40
|
+
* This function is called for the report endpoint to have an access over the populated string.
|
|
41
|
+
* Falls back to populate.list if not defined.
|
|
42
|
+
*/
|
|
43
|
+
report?: PopulateFunction;
|
|
39
44
|
}
|
|
40
45
|
interface Action {
|
|
41
46
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "identity-admin",
|
|
3
|
-
"version": "1.28.
|
|
3
|
+
"version": "1.28.32",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "lib/Dashboard.js",
|
|
6
6
|
"types": "lib/Dashbord.d.ts",
|
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
"connect-mongo": "^4.6.0",
|
|
51
51
|
"cookie-parser": "^1.4.6",
|
|
52
52
|
"deep-diff": "^1.0.2",
|
|
53
|
+
"exceljs": "^4.4.0",
|
|
53
54
|
"express-session": "^1.17.3",
|
|
54
55
|
"lodash": "^4.17.21",
|
|
55
56
|
"memory-cache": "^0.2.0",
|