Skip to content

Commit 026cd69

Browse files
committed
Merge branch '2.0.x' into 2.1.x
2 parents f5ca2e6 + f4b9ba2 commit 026cd69

File tree

5 files changed

+96
-12
lines changed

5 files changed

+96
-12
lines changed
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { Form, Record, Resource } from '@models';
2+
import { startDatabaseForMigration } from '../src/utils/migrations/database.helper';
3+
import { deleteFolder } from '@utils/files/deleteFolder';
4+
import { logger } from '@services/logger.service';
5+
6+
/** This migration removes forms that are not linked to any resources */
7+
export const up = async () => {
8+
await startDatabaseForMigration();
9+
10+
const forms = await Form.find({});
11+
const resources = await Resource.find({});
12+
13+
const formsToDelete = forms.filter(
14+
(f) => !resources.find((r) => r._id.equals(f.resource))
15+
);
16+
17+
try {
18+
for (const form of forms) {
19+
await deleteFolder('forms', form.id || form._id);
20+
logger.info(`Files from form ${form.id} successfully removed.`);
21+
}
22+
} catch (err) {
23+
logger.error(`Deletion of files from forms failed: ${err.message}`);
24+
}
25+
26+
// delete and log how many forms were deleted
27+
const { deletedCount } = await Form.deleteMany({
28+
_id: { $in: formsToDelete.map((f) => f._id) },
29+
});
30+
logger.info(`${deletedCount} forms were deleted.`);
31+
32+
// delete records that are linked to the deleted forms and log how many were deleted
33+
const { deletedCount: deletedRecordsCount } = await Record.deleteMany({
34+
form: { $in: formsToDelete.map((f) => f._id) },
35+
});
36+
logger.info(`${deletedRecordsCount} records were deleted.`);
37+
};
38+
39+
/**
40+
* Sample function of down migration
41+
*
42+
* @returns just migrate data.
43+
*/
44+
export const down = async () => {
45+
/*
46+
Code you downgrade script here!
47+
*/
48+
};

src/models/resource.model.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -115,15 +115,23 @@ const resourceSchema = new Schema<Resource>(
115115

116116
// handle cascading deletion for resources
117117
addOnBeforeDeleteMany(resourceSchema, async (resources) => {
118+
const resourcesIds = resources.map((r) => r._id);
118119
try {
119-
const forms = await Form.find({ resource: { $in: resources } });
120-
for (const form of forms) {
121-
await deleteFolder('forms', form.id);
122-
logger.info(`Files from form ${form.id} successfully removed.`);
120+
const forms = await Form.find({ resource: { $in: resourcesIds } });
121+
122+
// adding try catch because on envs without storage this was throwing an error
123+
// and preventing the deletion of forms and records
124+
try {
125+
for (const form of forms) {
126+
await deleteFolder('forms', form.id);
127+
logger.info(`Files from form ${form.id} successfully removed.`);
128+
}
129+
} catch (err) {
130+
logger.error(`Deletion of files from forms failed: ${err.message}`);
123131
}
124132

125-
await Form.deleteMany({ resource: { $in: resources } });
126-
await Record.deleteMany({ resource: { $in: resources } });
133+
await Form.deleteMany({ resource: { $in: resourcesIds } });
134+
await Record.deleteMany({ resource: { $in: resourcesIds } });
127135
} catch (err) {
128136
logger.error(`Deletion of resources failed: ${err.message}`);
129137
}

src/utils/files/exportBatch.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ const getRowsCsv = async (
365365
// todo: optimize in order to avoid using graphQL?
366366
const query = buildQuery(params.query);
367367
let offset = 0;
368-
const batchSize = 2000;
368+
const batchSize = 1000;
369369
const csvData = [];
370370
do {
371371
await axios({

src/utils/schema/resolvers/Query/all.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,7 @@ export default (entityName: string, fieldsByName: any, idsByName: any) =>
607607
const relatedFilters = [];
608608
for (const item of items as any) {
609609
item._relatedRecords = {};
610+
item.data = item.data || {};
610611
for (const field of resourcesFields) {
611612
if (field.type === 'resource') {
612613
const record = item.data[field.name];

src/utils/schema/resolvers/Query/getFilter.ts

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import mongoose from 'mongoose';
22
import { getDateForMongo } from '@utils/filter/getDateForMongo';
33
import { getTimeForMongo } from '@utils/filter/getTimeForMongo';
44
import { MULTISELECT_TYPES, DATE_TYPES } from '@const/fieldTypes';
5+
import { Resource } from '@models';
56

67
/** The default fields */
78
const DEFAULT_FIELDS = [
@@ -64,16 +65,20 @@ export const extractFilterFields = (filter: any): string[] => {
6465
* @param prefix prefix to access field
6566
* @returns Mongo filter.
6667
*/
67-
const buildMongoFilter = (
68+
const buildMongoFilter = async (
6869
filter: any,
6970
fields: any[],
7071
context: any,
7172
prefix = ''
72-
): any => {
73+
): Promise<any> => {
7374
if (filter.filters) {
74-
const filters = filter.filters
75-
.map((x: any) => buildMongoFilter(x, fields, context, prefix))
76-
.filter((x) => x);
75+
const filters = (
76+
await Promise.all(
77+
filter.filters.map((x: any) =>
78+
buildMongoFilter(x, fields, context, prefix)
79+
)
80+
)
81+
).filter((x) => x);
7782
if (filters.length > 0) {
7883
switch (filter.logic) {
7984
case 'and': {
@@ -101,6 +106,28 @@ const buildMongoFilter = (
101106
(x) =>
102107
x.name === filter.field || x.name === filter.field.split('.')[0]
103108
)?.type || '';
109+
110+
// If type is resource and refers to a nested field, get the type of the nested field
111+
if (type === 'resource') {
112+
// find the resource field
113+
const resourceField = fields.find(
114+
(x) => x.name === filter.field.split('.')[0]
115+
);
116+
117+
if (resourceField?.resource) {
118+
const nestedResource = await Resource.findById(
119+
resourceField.resource
120+
);
121+
122+
// find the nested field
123+
const nestedField = nestedResource?.fields.find(
124+
(x) => x.name === filter.field.split('.')[1]
125+
);
126+
127+
// get the type of the nested field
128+
type = nestedField?.type || type;
129+
}
130+
}
104131
if (filter.field === 'ids') {
105132
return {
106133
_id: { $in: filter.value.map((x) => mongoose.Types.ObjectId(x)) },

0 commit comments

Comments
 (0)