diff --git a/.eslintrc.json b/.eslintrc.json index b140dd479..0d3439df5 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -9,27 +9,12 @@ "structuredClone": true }, "extends": ["airbnb", "prettier"], - "plugins": [ - "chai-friendly", - "jsdoc", - "prettier", - "unicorn", - "@typescript-eslint" - ], - "parser": "@typescript-eslint/parser", + "plugins": ["chai-friendly", "jsdoc", "prettier", "unicorn"], "parserOptions": { "sourceType": "module", "ecmaVersion": 2021 }, "settings": { - "import/parsers": { - "@typescript-eslint/parser": [".js", ".ts", ".tsx"] - }, - "import/resolver": { - "typescript": { - "alwaysTryTypes": true - } - }, "jsdoc": { "tagNamePreference": { "returns": "return" @@ -46,8 +31,7 @@ "enketo/widgets", "enketo/translator", "enketo/dialog", - "enketo/file-manager", - "enketo-transformer/web" + "enketo/file-manager" ] } ], diff --git a/CHANGELOG.md b/CHANGELOG.md index cdf876274..392a403b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,35 +3,6 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). -## 6.2.0 - 2023-07-03 - -- Make pdf generation timeout configurable (#560) -- Added the Ukrainian translation (#569) -- Optimizations: do less redundant work, part 2 (enketo-core#976) -- Fix: gracefully handle undefined key (enketo-core#978) -- Fix: TOC navigation in pages theme (enketo-core#983) -- Fix: Respect existing val of type='time' (enketo-core#980) - -## 6.1.0 - 2023-05-10 - -- removed: analog-scale widget (#525) _Note: now maintained by OpenClinica (https://github.com/OpenClinica/enketo-express-oc/tree/master/widget/analog-scale). Not considered a breaking change because usage outside of OpenClinica is not known_ -- fixed: The app UI strings in newly created repeats are not translated (#527) -- Fix: validate CSV header names according to XML spec (#530) -- Use pm2-runtime on docker/start.sh (#533) -- Fix: revert jQuery upgrade (#539) -- Use client-side transform for preview-by-URL (#540) -- changed: updated Slovak translation (#542) -- Use exponential backoff for submission attempts in offline mode (#543) -- feat(app): add enketo namespace to all debug statements (#547) -- Add support for LineString and Polygon GeoJSON types (#554) -- Fix: further simplify geopicker widget selector (#954) -- Fix: undesired newlines in print view in select/select1 labels (#957) -- Add browser-based transformation (#171) -- Reimplement draw/signature/annotate widget to preserve original image size when annotating and improve resize performance (#960) -- Fix: focus first active input/widget on load, page navigation, user-added repeat (#969) -- Performance improvements: NumberInput widgets, `excludeNonRelevant` (#971) -- Fix: localized numeral entry by keyboard in number input widgets (#973) - ## 6.0.0 - 2023-02-08 - **BREAKING CHANGE**: Removed IE11 support (enketo-core#946) diff --git a/Gruntfile.js b/Gruntfile.js index 59f304c97..3bbfb9222 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -6,7 +6,7 @@ module.exports = (grunt) => { '!.nyc_output', '!**/node_modules/**', '!test/client/forms/forms.js', - '!public/js/build/**', + '!public/js/build/*', '!docs/**', '!test-coverage/**', ]; @@ -105,7 +105,7 @@ module.exports = (grunt) => { 'find locales -name "translation-combined.json" -delete && rm -fr locales/??', }, 'clean-js': { - command: 'rm -rf public/js/build/* && rm -f public/js/*.js', + command: 'rm -f public/js/build/* && rm -f public/js/*.js', }, translation: { command: diff --git a/README.md b/README.md index f40d7df62..ff3b9d99a 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ OpenClinica users, in addition to the configuration documentation linked above, Enketo was initiated in 2009 by Martijn van de Rijdt as a web-based alternative or complement to [ODK Collect](https://docs.getodk.org/collect-intro/). It has become a core component of the ODK ecosystem and been adopted by several organizations beyond that ecosystem. -As of 2022, Enketo is maintained by the [ODK team](https://getodk.org/about/team.html) (primarily [Trevor Schmidt](https://github.com/eyelidlessness/)). Martijn continues to provide advice and continuity. The ODK project sets priorities in collaboration with its [Technical Advisory Board](https://getodk.org/about/ecosystem.html). +As of 2022, Enketo is maintained by [Trevor Schmidt](https://github.com/eyelidlessness/) and [the ODK team](https://getodk.org/about/team.html). Martijn continues to provide advice and continuity. The ODK project sets priorities in collaboration with its [Technical Advisory Board](https://getodk.org/about/ecosystem.html). Our current primary goals are: @@ -49,7 +49,7 @@ Feature requests and project discussion are welcome on the [ODK forum](https://f ### Translation -The user interface was translated by: Oleg Zhyliak (Ukrainian), Karol Kozyra (Swedish), Badisches Rotes Kreuz (German), Serkan Tümbaş (Turkish), Hélène Martin (French), Gurjot Sidhu(Hindi, Panjabi), "Abcmen" (Turkish), Otto Saldadze, Makhare Atchaidze, David Sichinava, Elene Ergeshidze (Georgian), Nancy Shapsough (Arabic), Noel O'Boyle (French), Miguel Moreno (Spanish), Tortue Torche (French), Bekim Kajtazi (Albanian), Marc Kreidler (German), Darío Hereñú (Spanish), Viktor S. (Russian), Alexander Torrado Leon (Spanish), Peter Smith (Portugese, Spanish), Przemysław Gumułka (Polish), Niklas Ljungkvist, Sid Patel (Swedish), Katri Jalava (Finnish), Francesc Garre (Spanish), Sounay Phothisane (Lao), Linxin Guo (Chinese), Emmanuel Jean, Renaud Gaudin (French), Trần Quý Phi (Vietnamese), Reza Doosti, Hossein Azad, Davood Mottalee (Persian), Tomas Skripcak (Slovak, Czech, German), Daniela Baldova (Czech), Robert Michael Lundin (Norwegian), Margaret Ndisha, Charles Mutisya (Swahili), Panzero Mauro (Italian), Gabriel Kreindler (Romanian), Jason Reeder, Omar Nazar, Sara Sameer, David Gessel (Arabic), Tino Kreutzer (German), Wasilis Mandratzis-Walz (German, Greek), Luis Molina (Spanish), Martijn van de Rijdt (Dutch). +The user interface was translated by: Karol Kozyra (Swedish), Badisches Rotes Kreuz (German), Serkan Tümbaş (Turkish), Hélène Martin (French), Gurjot Sidhu(Hindi, Panjabi), "Abcmen" (Turkish), Otto Saldadze, Makhare Atchaidze, David Sichinava, Elene Ergeshidze (Georgian), Nancy Shapsough (Arabic), Noel O'Boyle (French), Miguel Moreno (Spanish), Tortue Torche (French), Bekim Kajtazi (Albanian), Marc Kreidler (German), Darío Hereñú (Spanish), Viktor S. (Russian), Alexander Torrado Leon (Spanish), Peter Smith (Portugese, Spanish), Przemysław Gumułka (Polish), Niklas Ljungkvist, Sid Patel (Swedish), Katri Jalava (Finnish), Francesc Garre (Spanish), Sounay Phothisane (Lao), Linxin Guo (Chinese), Emmanuel Jean, Renaud Gaudin (French), Trần Quý Phi (Vietnamese), Reza Doosti, Hossein Azad, Davood Mottalee (Persian), Tomas Skripcak (Slovak, Czech, German), Daniela Baldova (Czech), Robert Michael Lundin (Norwegian), Margaret Ndisha, Charles Mutisya (Swahili), Panzero Mauro (Italian), Gabriel Kreindler (Romanian), Jason Reeder, Omar Nazar, Sara Sameer, David Gessel (Arabic), Tino Kreutzer (German), Wasilis Mandratzis-Walz (German, Greek), Luis Molina (Spanish), Martijn van de Rijdt (Dutch). _Send a message if you'd like to contribute! We use an easy web interface provided by [Transifex](https://www.transifex.com/projects/p/enketo-express/)._ @@ -80,15 +80,13 @@ OpenClinica has a few [additional text strings](./locales/src/en/translation-add ### Funding -The development of this application is now led by [ODK](https://getodk.org) and funded by customers of the ODK Cloud hosted service. - -Past funders include [KoBo Toolbox (Harvard Humanitarian Initiative)](http://www.kobotoolbox.org), [iMMAP](http://immap.org), [OpenClinica](https://openclinica.com), [London School of Hygiene and Tropical Medicine](https://opendatakit.lshtm.ac.uk/), [DIAL Open Source Center](https://www.osc.dial.community/) and [Enketo LLC](https://www.linkedin.com/company/enketo-llc). Also see [Enketo Core sponsors](https://github.com/enketo/enketo-core#sponsors). +The development of this application was funded by [KoBo Toolbox (Harvard Humanitarian Initiative)](http://www.kobotoolbox.org), [iMMAP](http://immap.org), [OpenClinica](https://openclinica.com), [London School of Hygiene and Tropical Medicine](https://opendatakit.lshtm.ac.uk/), [DIAL Open Source Center](https://www.osc.dial.community/) and [Enketo LLC](https://www.linkedin.com/company/enketo-llc). The [Enketo-core](https://github.com/enketo/enketo-core) library (the form engine + themes) used in this application obtained significant funding from [SEL (Columbia University)](http://modi.mech.columbia.edu/), the [Santa Fe Institute](http://www.santafe.edu/), [Ona](https://ona.io) and the [HRP project](http://www.who.int/reproductivehealth/topics/mhealth/en/). ### License See [the license document](https://github.com/enketo/enketo-express/blob/master/LICENSE) for this application's license. -Note that some of the libraries used in this app have a different license. +Note that some of the libraries used in this app have a different license. In particular note [this one](https://github.com/enketo/enketo-xpathjs). Note the 'Powered by Enketo' footer requirement as explained in [enketo-core](https://github.com/enketo/enketo-core#license). This requirement is applicable to all Enketo apps, including this one, unless an exemption was granted. diff --git a/app/controllers/media-controller.js b/app/controllers/media-controller.js index 7f639487d..d7b025e68 100644 --- a/app/controllers/media-controller.js +++ b/app/controllers/media-controller.js @@ -8,7 +8,7 @@ const request = require('request'); const express = require('express'); const router = express.Router(); -const debug = require('debug')('enketo:media-controller'); +const debug = require('debug')('media-controller'); const { RequestFilteringHttpAgent, RequestFilteringHttpsAgent, diff --git a/app/controllers/transformation-controller.js b/app/controllers/transformation-controller.js index 6d1290f5f..8541eecd1 100644 --- a/app/controllers/transformation-controller.js +++ b/app/controllers/transformation-controller.js @@ -4,7 +4,7 @@ const transformer = require('enketo-transformer'); const communicator = require('../lib/communicator'); -const { ResponseError, TranslatedError } = require('../lib/custom-error'); +const { TranslatedError } = require('../lib/custom-error'); const surveyModel = require('../models/survey-model'); const cacheModel = require('../models/cache-model'); const account = require('../models/account-model'); @@ -13,6 +13,7 @@ const config = require('../models/config-model').server; const utils = require('../lib/utils'); const routerUtils = require('../lib/router-utils'); const express = require('express'); +const url = require('url'); const mediaLib = require('../lib/media'); const router = express.Router(); @@ -100,15 +101,27 @@ async function getSurveyParts(req, res, next) { /** @type {string | null} */ let formId = null; + /** @type {string | null} */ + let formFileName = null; + try { let survey = await _getSurveyParams(req); - formId = survey.openRosaId; + // A request with "xformUrl" body parameter was used (unlaunched form) + if (survey.info != null) { + formFileName = survey.info.downloadUrl.replace( + /.*\/([^/]+)$/, + '$1' + ); + survey = await _getFormDirectly(survey); + + _respond(res, survey); - if (formId == null) { - throw new ResponseError(404); + return; } + formId = survey.openRosaId; + const authenticated = await _authenticate(survey); const cached = await _getFormFromCache(authenticated); @@ -129,10 +142,14 @@ async function getSurveyParts(req, res, next) { }); } catch (error) { if (error.status === 403) { - const notFoundError = new TranslatedError( - 'error.notfoundinformlist', - { formId } - ); + const notFoundError = + formId == null + ? new TranslatedError('error.notfounddirectformurl', { + formFileName, + }) + : new TranslatedError('error.notfoundinformlist', { + formId, + }); notFoundError.status = 404; @@ -166,6 +183,17 @@ function getSurveyHash(req, res, next) { .catch(next); } +/** + * @param {module:survey-model~SurveyObject} survey - survey object + * + * @return { Promise } a Promise resolving with survey object with form transformation result + * + */ +function _getFormDirectly(survey) { + survey.openclinica = true; + return communicator.getXForm(survey).then(transformer.transform); +} + /** * @param {module:survey-model~SurveyObject} survey - survey object * @@ -205,11 +233,8 @@ function _updateCache(survey) { delete survey.mediaHash; delete survey.mediaUrlHash; delete survey.formHash; - survey.openclinica = true; - return communicator - .getXForm(survey) - .then(transformer.transform) - .then(cacheModel.set); + + return _getFormDirectly(survey).then(cacheModel.set); } return survey; @@ -334,6 +359,7 @@ function _setCookieAndCredentials(survey, req) { * @return { Promise } a Promise resolving with survey object */ function _getSurveyParams(req) { + const params = req.body; const customParamName = req.app.get( 'query parameter to pass to submission' ); @@ -350,7 +376,32 @@ function _getSurveyParams(req) { return _setCookieAndCredentials(survey, req); }); } - + if (params.xformUrl) { + const urlObj = url.parse(params.xformUrl); + if (!urlObj || !urlObj.protocol || !urlObj.host) { + const error = new Error('Bad Request. Form URL is invalid.'); + error.status = 400; + throw error; + } + const xUrl = `${urlObj.protocol}//${urlObj.host}${urlObj.pathname}`; + + return account + .check({ + openRosaServer: xUrl, + }) + .then( + ( + survey // no need to check quota + ) => + Promise.resolve({ + info: { + downloadUrl: params.xformUrl, + }, + account: survey.account, + }) + ) + .then((survey) => _setCookieAndCredentials(survey, req)); + } const error = new Error('Bad Request. Survey information not complete.'); error.status = 400; throw error; diff --git a/app/lib/communicator.js b/app/lib/communicator.js index 49b91aa7e..64ce88d30 100644 --- a/app/lib/communicator.js +++ b/app/lib/communicator.js @@ -6,7 +6,7 @@ const request = require('request'); const { Auth } = require('request/lib/auth'); const TError = require('./custom-error').TranslatedError; const config = require('../models/config-model').server; -const debug = require('debug')('enketo:openrosa-communicator'); +const debug = require('debug')('openrosa-communicator'); const Xml2Js = require('xml2js'); const parser = new Xml2Js.Parser(); diff --git a/app/lib/pdf.js b/app/lib/pdf.js index e5ab76031..78142dbaf 100644 --- a/app/lib/pdf.js +++ b/app/lib/pdf.js @@ -121,7 +121,6 @@ async function get( }, scale, printBackground: true, - timeout, }); } catch (e) { e.status = e.status || 400; diff --git a/app/models/cache-model.js b/app/models/cache-model.js index 8de7b1369..5d1355583 100644 --- a/app/models/cache-model.js +++ b/app/models/cache-model.js @@ -9,7 +9,7 @@ const utils = require('../lib/utils'); const prefix = 'ca:'; const expiry = 30 * 24 * 60 * 60; -const debug = require('debug')('enketo:cache-model'); +const debug = require('debug')('cache-model'); const clientGet = promisify(cacheClient.get).bind(cacheClient); const clientSet = promisify(cacheClient.set).bind(cacheClient); diff --git a/app/models/survey-model.js b/app/models/survey-model.js index 03a2f1a0f..5393a04cb 100644 --- a/app/models/survey-model.js +++ b/app/models/survey-model.js @@ -8,7 +8,7 @@ const TError = require('../lib/custom-error').TranslatedError; const config = require('./config-model').server; const pending = {}; -const debug = require('debug')('enketo:survey-model'); +const debug = require('debug')('survey-model'); /** * @typedef {import('./account-model').AccountObj} AccountObj diff --git a/app/views/index.pug b/app/views/index.pug index d8594ef57..17118c774 100644 --- a/app/views/index.pug +++ b/app/views/index.pug @@ -57,8 +57,6 @@ block content li= t("langs.sv") when "lo" li= t("langs.lo") - when "uk" - li= t("langs.uk") when "sk" li= t("langs.sk") when "tr" diff --git a/app/views/surveys/webform.pug b/app/views/surveys/webform.pug index 40e997894..7e513dec5 100644 --- a/app/views/surveys/webform.pug +++ b/app/views/surveys/webform.pug @@ -20,7 +20,7 @@ block style block script - var suffix = (type && type !== 'single') ? '-' + (type === 'full' || type === 'preview' || type === 'fieldsubmission' ? 'oc' : type): '' - script#main-script(defer, type='module', src=`${basePath}${offlinePath || ''}/js/build/enketo-webform${suffix}.js`) + script#main-script(defer, module, src=`${basePath}${offlinePath || ''}/js/build/enketo-webform${suffix}.js`) -// load jini stuff asynchronously (OC) if jini && !headless diff --git a/config/build.js b/config/build.js index 07e30bffe..fa9437f5f 100644 --- a/config/build.js +++ b/config/build.js @@ -1,5 +1,4 @@ -// @ts-check - +const alias = require('esbuild-plugin-alias'); const path = require('path'); const pkg = require('../package.json'); @@ -7,22 +6,24 @@ const cwd = process.cwd(); const entryPoints = pkg.entries.map((entry) => path.resolve(cwd, entry)); -module.exports = /** @satisfies {import('esbuild').BuildOptions} */ ({ - alias: Object.fromEntries( - Object.entries(pkg.browser).map(([key, value]) => [ - key, - path.resolve(cwd, `${value}.js`), - ]) - ), +const isProduction = process.env.NODE_ENV === 'production'; + +module.exports = { bundle: true, - chunkNames: 'chunks/[name]-[hash]', entryPoints, - entryNames: '[name]', - external: ['crypto', 'libxslt'], - format: 'esm', - minify: true, + format: 'iife', + minify: isProduction, outdir: path.resolve(cwd, './public/js/build'), - sourcemap: true, - splitting: true, + plugins: [ + alias( + Object.fromEntries( + Object.entries(pkg.browser).map(([key, value]) => [ + key, + path.resolve(cwd, `${value}.js`), + ]) + ) + ), + ], + sourcemap: isProduction ? false : 'inline', target: ['chrome89', 'edge89', 'firefox90', 'safari13'], -}); +}; diff --git a/config/express.js b/config/express.js index b4b78a89e..b201d0c92 100644 --- a/config/express.js +++ b/config/express.js @@ -14,7 +14,7 @@ const errorHandler = require('../app/controllers/error-handler'); const controllersPath = path.join(__dirname, '../app/controllers'); const app = express(); -const debug = require('debug')('enketo:express'); +const debug = require('debug')('express'); const config = require('../app/models/config-model'); // general diff --git a/docs/app_controllers_api-controller.js.html b/docs/app_controllers_api-controller.js.html index 43d1cdba0..1cc969ebb 100644 --- a/docs/app_controllers_api-controller.js.html +++ b/docs/app_controllers_api-controller.js.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/app_controllers_api-v1-controller.js.html b/docs/app_controllers_api-v1-controller.js.html index 3d30a5fba..0192c170f 100644 --- a/docs/app_controllers_api-v1-controller.js.html +++ b/docs/app_controllers_api-v1-controller.js.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/app_controllers_api-v2-controller.js.html b/docs/app_controllers_api-v2-controller.js.html index 2f9d0af12..4581746b9 100644 --- a/docs/app_controllers_api-v2-controller.js.html +++ b/docs/app_controllers_api-v2-controller.js.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/app_controllers_authentication-controller.js.html b/docs/app_controllers_authentication-controller.js.html index 2abb748eb..ef9be1c27 100644 --- a/docs/app_controllers_authentication-controller.js.html +++ b/docs/app_controllers_authentication-controller.js.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/app_controllers_error-handler.js.html b/docs/app_controllers_error-handler.js.html index d93a80309..a93c77a55 100644 --- a/docs/app_controllers_error-handler.js.html +++ b/docs/app_controllers_error-handler.js.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/app_controllers_media-controller.js.html b/docs/app_controllers_media-controller.js.html index 259500a08..eb18f02e7 100644 --- a/docs/app_controllers_media-controller.js.html +++ b/docs/app_controllers_media-controller.js.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

@@ -57,7 +57,7 @@

app/controllers/media-controller.js

const express = require('express'); const router = express.Router(); -const debug = require('debug')('enketo:media-controller'); +const debug = require('debug')('media-controller'); const { RequestFilteringHttpAgent, RequestFilteringHttpsAgent, diff --git a/docs/app_controllers_offline-controller.js.html b/docs/app_controllers_offline-controller.js.html index ba36f5b4d..6957722aa 100644 --- a/docs/app_controllers_offline-controller.js.html +++ b/docs/app_controllers_offline-controller.js.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/app_controllers_pages-controller.js.html b/docs/app_controllers_pages-controller.js.html index 6ceb9ef2a..18a4d1022 100644 --- a/docs/app_controllers_pages-controller.js.html +++ b/docs/app_controllers_pages-controller.js.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/app_controllers_submission-controller.js.html b/docs/app_controllers_submission-controller.js.html index 8040e7084..f4bd12dc3 100644 --- a/docs/app_controllers_submission-controller.js.html +++ b/docs/app_controllers_submission-controller.js.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/app_controllers_survey-controller.js.html b/docs/app_controllers_survey-controller.js.html index b66be66ba..e9200edd1 100644 --- a/docs/app_controllers_survey-controller.js.html +++ b/docs/app_controllers_survey-controller.js.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/app_controllers_transformation-controller.js.html b/docs/app_controllers_transformation-controller.js.html index ddf28135a..471a9e85b 100644 --- a/docs/app_controllers_transformation-controller.js.html +++ b/docs/app_controllers_transformation-controller.js.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

@@ -53,7 +53,7 @@

app/controllers/transformation-controller.js

const transformer = require('enketo-transformer'); const communicator = require('../lib/communicator'); -const { ResponseError, TranslatedError } = require('../lib/custom-error'); +const { TranslatedError } = require('../lib/custom-error'); const surveyModel = require('../models/survey-model'); const cacheModel = require('../models/cache-model'); const account = require('../models/account-model'); @@ -62,6 +62,7 @@

app/controllers/transformation-controller.js

const utils = require('../lib/utils'); const routerUtils = require('../lib/router-utils'); const express = require('express'); +const url = require('url'); const mediaLib = require('../lib/media'); const router = express.Router(); @@ -99,15 +100,27 @@

app/controllers/transformation-controller.js

/** @type {string | null} */ let formId = null; + /** @type {string | null} */ + let formFileName = null; + try { let survey = await _getSurveyParams(req); - formId = survey.openRosaId; + // A request with "xformUrl" body parameter was used (unlaunched form) + if (survey.info != null) { + formFileName = survey.info.downloadUrl.replace( + /.*\/([^/]+)$/, + '$1' + ); + survey = await _getFormDirectly(survey); + + _respond(res, survey); - if (formId == null) { - throw new ResponseError(404); + return; } + formId = survey.openRosaId; + const authenticated = await _authenticate(survey); const cached = await _getFormFromCache(authenticated); @@ -128,10 +141,14 @@

app/controllers/transformation-controller.js

}); } catch (error) { if (error.status === 403) { - const notFoundError = new TranslatedError( - 'error.notfoundinformlist', - { formId } - ); + const notFoundError = + formId == null + ? new TranslatedError('error.notfounddirectformurl', { + formFileName, + }) + : new TranslatedError('error.notfoundinformlist', { + formId, + }); notFoundError.status = 404; @@ -165,6 +182,16 @@

app/controllers/transformation-controller.js

.catch(next); } +/** + * @param {module:survey-model~SurveyObject} survey - survey object + * + * @return { Promise<module:survey-model~SurveyObject> } a Promise resolving with survey object with form transformation result + * + */ +function _getFormDirectly(survey) { + return communicator.getXForm(survey).then(transformer.transform); +} + /** * @param {module:survey-model~SurveyObject} survey - survey object * @@ -205,10 +232,7 @@

app/controllers/transformation-controller.js

delete survey.mediaUrlHash; delete survey.formHash; - return communicator - .getXForm(survey) - .then(transformer.transform) - .then(cacheModel.set); + return _getFormDirectly(survey).then(cacheModel.set); } return survey; @@ -333,6 +357,7 @@

app/controllers/transformation-controller.js

* @return { Promise<module:survey-model~SurveyObject> } a Promise resolving with survey object */ function _getSurveyParams(req) { + const params = req.body; const customParamName = req.app.get( 'query parameter to pass to submission' ); @@ -349,7 +374,32 @@

app/controllers/transformation-controller.js

return _setCookieAndCredentials(survey, req); }); } - + if (params.xformUrl) { + const urlObj = url.parse(params.xformUrl); + if (!urlObj || !urlObj.protocol || !urlObj.host) { + const error = new Error('Bad Request. Form URL is invalid.'); + error.status = 400; + throw error; + } + const xUrl = `${urlObj.protocol}//${urlObj.host}${urlObj.pathname}`; + + return account + .check({ + openRosaServer: xUrl, + }) + .then( + ( + survey // no need to check quota + ) => + Promise.resolve({ + info: { + downloadUrl: params.xformUrl, + }, + account: survey.account, + }) + ) + .then((survey) => _setCookieAndCredentials(survey, req)); + } const error = new Error('Bad Request. Survey information not complete.'); error.status = 400; throw error; diff --git a/docs/app_lib_communicator.js.html b/docs/app_lib_communicator.js.html index 715038305..5c78ff47b 100644 --- a/docs/app_lib_communicator.js.html +++ b/docs/app_lib_communicator.js.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

@@ -55,7 +55,7 @@

app/lib/communicator.js

const { Auth } = require('request/lib/auth'); const TError = require('./custom-error').TranslatedError; const config = require('../models/config-model').server; -const debug = require('debug')('enketo:openrosa-communicator'); +const debug = require('debug')('openrosa-communicator'); const Xml2Js = require('xml2js'); const parser = new Xml2Js.Parser(); diff --git a/docs/app_lib_custom-error.js.html b/docs/app_lib_custom-error.js.html index a7b7be15b..a89faac0c 100644 --- a/docs/app_lib_custom-error.js.html +++ b/docs/app_lib_custom-error.js.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/app_lib_media.js.html b/docs/app_lib_media.js.html index 72c5268c1..b1aa15294 100644 --- a/docs/app_lib_media.js.html +++ b/docs/app_lib_media.js.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/app_lib_pdf.js.html b/docs/app_lib_pdf.js.html index e7bf9a0fc..38d655a32 100644 --- a/docs/app_lib_pdf.js.html +++ b/docs/app_lib_pdf.js.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

@@ -152,7 +152,6 @@

app/lib/pdf.js

}, scale: options.scale, printBackground: true, - timeout, }); } catch (e) { e.status = e.status || 400; diff --git a/docs/app_lib_router-utils.js.html b/docs/app_lib_router-utils.js.html index 87832be91..5c97fac74 100644 --- a/docs/app_lib_router-utils.js.html +++ b/docs/app_lib_router-utils.js.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/app_lib_utils.js.html b/docs/app_lib_utils.js.html index 3d34ac675..6bc886c52 100644 --- a/docs/app_lib_utils.js.html +++ b/docs/app_lib_utils.js.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/app_models_account-model.js.html b/docs/app_models_account-model.js.html index e9642a21b..a4795cdf8 100644 --- a/docs/app_models_account-model.js.html +++ b/docs/app_models_account-model.js.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/app_models_cache-model.js.html b/docs/app_models_cache-model.js.html index 30d4d9c6c..f4ebf4e5d 100644 --- a/docs/app_models_cache-model.js.html +++ b/docs/app_models_cache-model.js.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

@@ -58,7 +58,7 @@

app/models/cache-model.js

const prefix = 'ca:'; const expiry = 30 * 24 * 60 * 60; -const debug = require('debug')('enketo:cache-model'); +const debug = require('debug')('cache-model'); const clientGet = promisify(cacheClient.get).bind(cacheClient); const clientSet = promisify(cacheClient.set).bind(cacheClient); diff --git a/docs/app_models_config-model.js.html b/docs/app_models_config-model.js.html index 8e30ae171..a7aa286f5 100644 --- a/docs/app_models_config-model.js.html +++ b/docs/app_models_config-model.js.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/app_models_instance-model.js.html b/docs/app_models_instance-model.js.html index 92faa4e9e..27f6b7bd1 100644 --- a/docs/app_models_instance-model.js.html +++ b/docs/app_models_instance-model.js.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/app_models_record-model.js.html b/docs/app_models_record-model.js.html index a6d09ed06..552f0b571 100644 --- a/docs/app_models_record-model.js.html +++ b/docs/app_models_record-model.js.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/app_models_submission-model.js.html b/docs/app_models_submission-model.js.html index 7085813f0..7a5e057fa 100644 --- a/docs/app_models_submission-model.js.html +++ b/docs/app_models_submission-model.js.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/app_models_survey-model.js.html b/docs/app_models_survey-model.js.html index ed5564dd3..51bf7b41a 100644 --- a/docs/app_models_survey-model.js.html +++ b/docs/app_models_survey-model.js.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

@@ -57,7 +57,7 @@

app/models/survey-model.js

const config = require('./config-model').server; const pending = {}; -const debug = require('debug')('enketo:survey-model'); +const debug = require('debug')('survey-model'); /** * @typedef {import('./account-model').AccountObj} AccountObj diff --git a/docs/app_models_user-model.js.html b/docs/app_models_user-model.js.html index 19c39c4c7..dd61f2bf2 100644 --- a/docs/app_models_user-model.js.html +++ b/docs/app_models_user-model.js.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/global.html b/docs/global.html index b7afcd45a..7aa2af6de 100644 --- a/docs/global.html +++ b/docs/global.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/index.html b/docs/index.html index 6cf06ae26..a7571544f 100644 --- a/docs/index.html +++ b/docs/index.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

@@ -67,7 +67,7 @@

To get started visit our technical documentation.

Project status

Enketo was initiated in 2009 by Martijn van de Rijdt as a web-based alternative or complement to ODK Collect. It has become a core component of the ODK ecosystem and been adopted by several organizations beyond that ecosystem.

-

As of 2022, Enketo is maintained by the ODK team (primarily Trevor Schmidt). Martijn continues to provide advice and continuity. The ODK project sets priorities in collaboration with its Technical Advisory Board.

+

As of 2022, Enketo is maintained by Trevor Schmidt and the ODK team. Martijn continues to provide advice and continuity. The ODK project sets priorities in collaboration with its Technical Advisory Board.

Our current primary goals are:

  • Increasing alignment with ODK Collect, particularly in service of submission edits.
  • @@ -76,7 +76,7 @@

    Project status

Feature requests and project discussion are welcome on the ODK forum.

Translation

-

The user interface was translated by: Oleg Zhyliak (Ukrainian), Karol Kozyra (Swedish), Badisches Rotes Kreuz (German), Serkan Tümbaş (Turkish), Hélène Martin (French), Gurjot Sidhu(Hindi, Panjabi), "Abcmen" (Turkish), Otto Saldadze, Makhare Atchaidze, David Sichinava, Elene Ergeshidze (Georgian), Nancy Shapsough (Arabic), Noel O'Boyle (French), Miguel Moreno (Spanish), Tortue Torche (French), Bekim Kajtazi (Albanian), Marc Kreidler (German), Darío Hereñú (Spanish), Viktor S. (Russian), Alexander Torrado Leon (Spanish), Peter Smith (Portugese, Spanish), Przemysław Gumułka (Polish), Niklas Ljungkvist, Sid Patel (Swedish), Katri Jalava (Finnish), Francesc Garre (Spanish), Sounay Phothisane (Lao), Linxin Guo (Chinese), Emmanuel Jean, Renaud Gaudin (French), Trần Quý Phi (Vietnamese), Reza Doosti, Hossein Azad, Davood Mottalee (Persian), Tomas Skripcak (Slovak, Czech, German), Daniela Baldova (Czech), Robert Michael Lundin (Norwegian), Margaret Ndisha, Charles Mutisya (Swahili), Panzero Mauro (Italian), Gabriel Kreindler (Romanian), Jason Reeder, Omar Nazar, Sara Sameer, David Gessel (Arabic), Tino Kreutzer (German), Wasilis Mandratzis-Walz (German, Greek), Luis Molina (Spanish), Martijn van de Rijdt (Dutch).

+

The user interface was translated by: Badisches Rotes Kreuz (German), Serkan Tümbaş (Turkish), Hélène Martin (French), Gurjot Sidhu(Hindi, Panjabi), "Abcmen" (Turkish), Otto Saldadze, Makhare Atchaidze, David Sichinava, Elene Ergeshidze (Georgian), Nancy Shapsough (Arabic), Noel O'Boyle (French), Miguel Moreno (Spanish), Tortue Torche (French), Bekim Kajtazi (Albanian), Marc Kreidler (German), Darío Hereñú (Spanish), Viktor S. (Russian), Alexander Torrado Leon (Spanish), Peter Smith (Portugese, Spanish), Przemysław Gumułka (Polish), Niklas Ljungkvist, Sid Patel (Swedish), Katri Jalava (Finnish), Francesc Garre (Spanish), Sounay Phothisane (Lao), Linxin Guo (Chinese), Emmanuel Jean, Renaud Gaudin (French), Trần Quý Phi (Vietnamese), Reza Doosti, Hossein Azad, Davood Mottalee (Persian), Tomas Skripcak (Slovak, Czech, German), Daniela Baldova (Czech), Robert Michael Lundin (Norwegian), Margaret Ndisha, Charles Mutisya (Swahili), Panzero Mauro (Italian), Gabriel Kreindler (Romanian), Jason Reeder, Omar Nazar, Sara Sameer, David Gessel (Arabic), Tino Kreutzer (German), Wasilis Mandratzis-Walz (German, Greek), Luis Molina (Spanish), Martijn van de Rijdt (Dutch).

Send a message if you'd like to contribute! We use an easy web interface provided by Transifex.

Releases

    @@ -110,11 +110,10 @@

    Releases

Funding

-

The development of this application is now led by ODK and funded by customers of the ODK Cloud hosted service.

-

Past funders include KoBo Toolbox (Harvard Humanitarian Initiative), iMMAP, OpenClinica, London School of Hygiene and Tropical Medicine, DIAL Open Source Center and Enketo LLC. Also see Enketo Core sponsors.

+

The development of this application was funded by KoBo Toolbox (Harvard Humanitarian Initiative), iMMAP, OpenClinica, London School of Hygiene and Tropical Medicine, DIAL Open Source Center and Enketo LLC. The Enketo-core library (the form engine + themes) used in this application obtained significant funding from SEL (Columbia University), the Santa Fe Institute, Ona and the HRP project.

License

See the license document for this application's license.

-

Note that some of the libraries used in this app have a different license.

+

Note that some of the libraries used in this app have a different license. In particular note this one.

Note the 'Powered by Enketo' footer requirement as explained in enketo-core. This requirement is applicable to all Enketo apps, including this one, unless an exemption was granted.

The Enketo logo and Icons are trademarked by Enketo LLC and should only be used for the 'Powered by Enketo' requirement mentioned above (if applicable). To prevent infringement simply replace the logo images in /public/images with your own or contact Enketo LLC to discuss the use inside your app.

Change log

diff --git a/docs/module-account-model.html b/docs/module-account-model.html index 6a51efe72..8c61cbaf7 100644 --- a/docs/module-account-model.html +++ b/docs/module-account-model.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/module-api-controller.html b/docs/module-api-controller.html index e34aae1d0..425043586 100644 --- a/docs/module-api-controller.html +++ b/docs/module-api-controller.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/module-api-v1-controller.html b/docs/module-api-v1-controller.html index 3cb588e88..9086669bd 100644 --- a/docs/module-api-v1-controller.html +++ b/docs/module-api-v1-controller.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/module-api-v2-controller.html b/docs/module-api-v2-controller.html index fb55d0648..bcc58e0ae 100644 --- a/docs/module-api-v2-controller.html +++ b/docs/module-api-v2-controller.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/module-authentication-controller.html b/docs/module-authentication-controller.html index 16a2614aa..f53576381 100644 --- a/docs/module-authentication-controller.html +++ b/docs/module-authentication-controller.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/module-cache-model.html b/docs/module-cache-model.html index 0a709c799..a4263f323 100644 --- a/docs/module-cache-model.html +++ b/docs/module-cache-model.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/module-communicator.html b/docs/module-communicator.html index 97b4b7f32..3d3424bc6 100644 --- a/docs/module-communicator.html +++ b/docs/module-communicator.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/module-config-model.html b/docs/module-config-model.html index fb827e44c..eadd37f6a 100644 --- a/docs/module-config-model.html +++ b/docs/module-config-model.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/module-custom-error.html b/docs/module-custom-error.html index d44bc4fc5..552485cf6 100644 --- a/docs/module-custom-error.html +++ b/docs/module-custom-error.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/module-duplicates.html b/docs/module-duplicates.html index 56babaef5..6714831e0 100644 --- a/docs/module-duplicates.html +++ b/docs/module-duplicates.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/module-error-handler.html b/docs/module-error-handler.html index 6746dca79..489868ebf 100644 --- a/docs/module-error-handler.html +++ b/docs/module-error-handler.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/module-instance-model.html b/docs/module-instance-model.html index b91f6bc72..bc5173c2c 100644 --- a/docs/module-instance-model.html +++ b/docs/module-instance-model.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/module-media-controller.html b/docs/module-media-controller.html index b93dcb89c..457bd1f40 100644 --- a/docs/module-media-controller.html +++ b/docs/module-media-controller.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/module-offline-resources-controller.html b/docs/module-offline-resources-controller.html index 91d418dc9..c05a4c915 100644 --- a/docs/module-offline-resources-controller.html +++ b/docs/module-offline-resources-controller.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/module-pages-controller.html b/docs/module-pages-controller.html index 2538b2f48..532f1ef27 100644 --- a/docs/module-pages-controller.html +++ b/docs/module-pages-controller.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/module-pdf.html b/docs/module-pdf.html index 75a161bbc..d6cc99f7d 100644 --- a/docs/module-pdf.html +++ b/docs/module-pdf.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/module-router-utils.html b/docs/module-router-utils.html index 4eac30c58..0738862de 100644 --- a/docs/module-router-utils.html +++ b/docs/module-router-utils.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/module-submission-model.html b/docs/module-submission-model.html index bfc9d1be8..5ca9286f7 100644 --- a/docs/module-submission-model.html +++ b/docs/module-submission-model.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/module-submissions-controller.html b/docs/module-submissions-controller.html index 5b9cde825..1aedc56a0 100644 --- a/docs/module-submissions-controller.html +++ b/docs/module-submissions-controller.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/module-survey-controller.html b/docs/module-survey-controller.html index c957abb95..6345bb2d7 100644 --- a/docs/module-survey-controller.html +++ b/docs/module-survey-controller.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/module-survey-model.html b/docs/module-survey-model.html index e5d89a0cd..8efe4fc68 100644 --- a/docs/module-survey-model.html +++ b/docs/module-survey-model.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/module-transformation-controller.html b/docs/module-transformation-controller.html index c9cea8b5e..da2be147f 100644 --- a/docs/module-transformation-controller.html +++ b/docs/module-transformation-controller.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

@@ -98,7 +98,7 @@

(inner) Source:
@@ -252,7 +252,7 @@

(inner) Source:
@@ -406,7 +406,7 @@

(inner) _
Source:
@@ -560,7 +560,7 @@

(inner) Source:
@@ -704,6 +704,160 @@
Returns:
+

(inner) _getFormDirectly(survey) → {Promise.<module:survey-model~SurveyObject>}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
survey + + +module:survey-model~SurveyObject + + + +

survey object

+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+

a Promise resolving with survey object with form transformation result

+
+ + + +
+
+ Type +
+
+ +Promise.<module:survey-model~SurveyObject> + + +
+
+ + + + + + + + + +

(inner) _getFormFromCache(survey) → {Promise.<module:survey-model~SurveyObject>}

@@ -716,7 +870,7 @@

(inner) Source:
@@ -870,7 +1024,7 @@

(inner) Source:
@@ -1024,7 +1178,7 @@

(inner) _res
Source:
@@ -1179,7 +1333,7 @@

(in
Source:
@@ -1356,7 +1510,7 @@

(inner)
Source:
@@ -1514,7 +1668,7 @@

(inner) Source:
@@ -1696,7 +1850,7 @@

(async, inner
Source:
diff --git a/docs/module-user-model.html b/docs/module-user-model.html index 429b003c0..3c877b84b 100644 --- a/docs/module-user-model.html +++ b/docs/module-user-model.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/module-utils.html b/docs/module-utils.html index 77127d86c..7e37bb42a 100644 --- a/docs/module-utils.html +++ b/docs/module-utils.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/tools_duplicates.js.html b/docs/tools_duplicates.js.html index 2b3584aeb..e5536d56e 100644 --- a/docs/tools_duplicates.js.html +++ b/docs/tools_duplicates.js.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/tutorial-00-getting-started.html b/docs/tutorial-00-getting-started.html index cf10e00d1..e1c9e5439 100644 --- a/docs/tutorial-00-getting-started.html +++ b/docs/tutorial-00-getting-started.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

@@ -96,10 +96,6 @@

How to configure

How to run

Run with npm start from project root.

You can now check that the app is running by going to e.g. http://localhost:8005 (depending on your server and port set in config/config.json or the port forwarding set up in Vagrant (default is 8006))

-

How to enable debug logs

-

Enketo uses the npm debug module. All debug statements are prefixed with enketo: and will not appear unless the environment variable is set. To enable debugging logs for enketo specifically, set DEBUG as follows:

-
export DEBUG=enketo*
-
diff --git a/docs/tutorial-02-heroku.html b/docs/tutorial-02-heroku.html index 478b48f53..15d90359f 100644 --- a/docs/tutorial-02-heroku.html +++ b/docs/tutorial-02-heroku.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/tutorial-10-configure.html b/docs/tutorial-10-configure.html index 48f011705..0aa50736d 100644 --- a/docs/tutorial-10-configure.html +++ b/docs/tutorial-10-configure.html @@ -32,7 +32,7 @@ -

Home

Github repo

Change log

Tutorials

Modules

Global

+

Home

Github repo

Change log

Tutorials

Modules

Global

diff --git a/docs/tutorial-12-ordinals.html b/docs/tutorial-12-ordinals.html index 9c19022f4..f0eb33c13 100644 --- a/docs/tutorial-12-ordinals.html +++ b/docs/tutorial-12-ordinals.html @@ -1,14 +1,14 @@ - + Tutorial: Repeats & Ordinals - Enketo Express - + - - - + + +