Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
fa64913
feat: added possibility to set prefix key in user to service api conf…
RenzoPrats May 3, 2024
df15809
lint fixed
RenzoPrats May 3, 2024
550af49
Merge branch 'next-oort' into feat/HIT_integrate_kobo_in_oort
RenzoPrats May 9, 2024
f450313
feat: started import kobo questions
RenzoPrats May 10, 2024
46cd45f
lint fixed
RenzoPrats May 10, 2024
f312098
feat: started translate kobo questions to survey ones
RenzoPrats May 17, 2024
4900d89
lint fixed
RenzoPrats May 17, 2024
a3d69f4
last fix
RenzoPrats May 23, 2024
f47fc5d
lint fixed
RenzoPrats May 23, 2024
1f68566
Merge branch 'next-oort' into feat/HIT_integrate_kobo_in_oort
estelafs Jun 19, 2024
f4cf489
added fields to form and resource, added version to form, added speci…
estelafs Jun 19, 2024
fbac786
added questions types: audio, video, geoshape and select_one & added …
estelafs Jun 19, 2024
8b21472
created mapKoboSkipLogic method to map kobo expression to the questio…
estelafs Jun 20, 2024
849a491
updated mapKoboExpression method & wip: map kobo constraints into sur…
estelafs Jun 20, 2024
394eae9
added validators property to questions
estelafs Jun 24, 2024
684a0e1
added calculate questions, added mapping for iif function & refactore…
estelafs Jun 24, 2024
d51aa86
added mapping for endsWith, currentDate functions & fix questions nam…
estelafs Jun 24, 2024
a921e0a
added mapping for grous and repeating groups to panels and dynamic pa…
estelafs Jun 25, 2024
9588eb6
added mapping for the functions today, format-date-time, mod, div, co…
estelafs Jun 26, 2024
bc2bd78
added mapping for the functions indexed-repeat, position
estelafs Jun 27, 2024
8bdf3db
added mapping for the functions sum, max, min, join
estelafs Jun 28, 2024
7d4793a
added mapping choices visibleIf and fixes
estelafs Jul 1, 2024
5864086
correct elements order, and adapt group logic to when user edited gro…
estelafs Jul 1, 2024
c4eb46b
fix: get group's parentGroup after getElementsGroups refactor
estelafs Jul 2, 2024
94a75b0
Merge branch 'next-oort' into feat/HIT_integrate_kobo_in_oort
estelafs Jul 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@
"form": {
"add": {
"errors": {
"koboForm": "An error occurred when trying to create a new form from a Kobo form",
"resourceDuplicated": "An existing resource with that name already exists."
}
},
Expand Down
1 change: 1 addition & 0 deletions src/i18n/test.json
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@
"form": {
"add": {
"errors": {
"koboForm": "******",
"resourceDuplicated": "******"
}
},
Expand Down
4 changes: 3 additions & 1 deletion src/routes/proxy/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ const proxyAPIRequest = async (
url,
method: req.method,
headers: {
Authorization: `Bearer ${token}`,
// if user-to-service token may contain prefix so it's get directly in getToken
Authorization:
api.authType == 'user-to-service' ? token : `Bearer ${token}`,
'Content-Type': 'application/json',
},
maxRedirects: 35,
Expand Down
93 changes: 92 additions & 1 deletion src/schema/mutation/addForm.mutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,38 @@ import {
GraphQLError,
} from 'graphql';
import { validateGraphQLTypeName } from '@utils/validators';
import { Resource, Form, Role, ReferenceData } from '@models';
import {
extractFields,
extractKoboFields,
findDuplicateFields,
} from '@utils/form';
import {
Resource,
Form,
Role,
ReferenceData,
ApiConfiguration,
Version,
} from '@models';
import { FormType } from '../types';
import { AppAbility } from '@security/defineUserAbility';
import { status } from '@const/enumTypes';
import { logger } from '@services/logger.service';
import { graphQLAuthCheck } from '@schema/shared';
import { Types } from 'mongoose';
import { Context } from '@server/apollo/context';
import axios from 'axios';
import config from 'config';
import * as CryptoJS from 'crypto-js';
import checkDefaultFields from '@utils/form/checkDefaultFields';

/** Arguments for the addForm mutation */
type AddFormArgs = {
name: string;
resource?: string | Types.ObjectId;
template?: string | Types.ObjectId;
apiConfiguration?: string | Types.ObjectId;
kobo?: string;
};

/**
Expand All @@ -31,6 +49,8 @@ export default {
name: { type: new GraphQLNonNull(GraphQLString) },
resource: { type: GraphQLID },
template: { type: GraphQLID },
apiConfiguration: { type: GraphQLID },
kobo: { type: GraphQLString },
},
async resolve(parent, args: AddFormArgs, context: Context) {
graphQLAuthCheck(context);
Expand Down Expand Up @@ -72,6 +92,77 @@ export default {
canUpdateRecords: [],
canDeleteRecords: [],
};
try {
if (args.apiConfiguration) {
const apiConfiguration = await ApiConfiguration.findById(
args.apiConfiguration
);
const url =
apiConfiguration.endpoint + `assets/${args.kobo}?format=json`;
const settings = JSON.parse(
CryptoJS.AES.decrypt(
apiConfiguration.settings,
config.get('encryption.key')
).toString(CryptoJS.enc.Utf8)
);
// get kobo form data
const response = await axios.get(url, {
headers: {
Authorization: `${settings.tokenPrefix} ${settings.token}`,
},
});
const survey = response.data.content.survey;
const choices = response.data.content.choices;
const title = response.data.name;

// Get structure from the kobo form
const structure = JSON.stringify(
extractKoboFields(survey, title, choices)
);

// Extract fields
const fields = [];
const structureObj = JSON.parse(structure);
for (const page of structureObj.pages) {
await extractFields(page, fields, true);
findDuplicateFields(fields);
}
// Check if default fields are used
checkDefaultFields(fields);

// Create version with structure
const version = new Version({
data: structure,
});
await version.save();

// create resource and form
const resource = new Resource({
name: args.name,
permissions: defaultResourcePermissions,
fields,
});
await resource.save();
const form = new Form({
name: args.name,
graphQLTypeName,
status: status.pending,
resource,
core: true,
permissions: defaultFormPermissions,
structure,
fields,
versions: [version._id],
});
await form.save();
return form;
}
} catch (err) {
logger.error(err.message, { stack: err.stack });
throw new GraphQLError(
context.i18next.t('mutations.form.add.errors.koboForm:')
);
}
try {
if (!args.resource) {
// Check permission to create resource
Expand Down
Loading