diff --git a/src/components/collect-qr.vue b/src/components/collect-qr.vue index e0172881e..2c07fe756 100644 --- a/src/components/collect-qr.vue +++ b/src/components/collect-qr.vue @@ -21,7 +21,6 @@ import pako from 'pako/lib/deflate'; export default { name: 'CollectQr', props: { - // General settings only (not admin settings) settings: { type: Object, required: true @@ -36,19 +35,9 @@ export default { } }, computed: { - fullSettings() { - return { - general: { - ...this.settings, - server_url: `${window.location.origin}${this.settings.server_url}` - }, - // Collect requires the settings to have an `admin` property. - admin: {} - }; - }, imgHtml() { const code = qrcode(0, this.errorCorrectionLevel); - const json = JSON.stringify(this.fullSettings); + const json = JSON.stringify(this.settings); code.addData(btoa(pako.deflate(json, { to: 'string' }))); code.make(); return code.createImgTag(this.cellSize, 0); diff --git a/src/components/field-key/qr-panel.vue b/src/components/field-key/qr-panel.vue index 125e3e309..2ae0ab4a0 100644 --- a/src/components/field-key/qr-panel.vue +++ b/src/components/field-key/qr-panel.vue @@ -73,26 +73,31 @@ import SentenceSeparator from '../sentence-separator.vue'; import FieldKey from '../../presenters/field-key'; import { apiPaths } from '../../util/request'; +import { requestData } from '../../store/modules/request'; export default { name: 'FieldKeyQrPanel', components: { CollectQr, DocLink, SentenceSeparator }, props: { - fieldKey: FieldKey, // eslint-disable-line vue/require-default-prop - managed: { - type: Boolean, - default: false - } + fieldKey: FieldKey, + managed: Boolean }, computed: { + ...requestData(['project']), settings() { - const { token, projectId } = this.fieldKey; + const url = apiPaths.serverUrlForFieldKey( + this.fieldKey.token, + this.project.id + ); const settings = { - server_url: apiPaths.serverUrlForFieldKey(token, projectId) + general: { server_url: `${window.location.origin}${url}` }, + project: { name: this.project.name }, + // Collect requires the settings to have an `admin` property. + admin: {} }; if (this.managed) { - settings.form_update_mode = 'match_exactly'; - settings.autosend = 'wifi_and_cellular'; + settings.general.form_update_mode = 'match_exactly'; + settings.general.autosend = 'wifi_and_cellular'; } return settings; } diff --git a/src/components/form-draft/testing.vue b/src/components/form-draft/testing.vue index 646b384ba..56d5891c0 100644 --- a/src/components/form-draft/testing.vue +++ b/src/components/form-draft/testing.vue @@ -93,16 +93,24 @@ export default { // component is created. ...requestData([{ key: 'formDraft', getOption: true }, 'keys']), qrSettings() { + const url = apiPaths.serverUrlForFormDraft( + this.formDraft.draftToken, + this.projectId, + this.xmlFormId + ); return { - server_url: apiPaths.serverUrlForFormDraft( - this.formDraft.draftToken, - this.projectId, - this.xmlFormId - ) + general: { + server_url: `${window.location.origin}${url}`, + form_update_mode: 'match_exactly', + autosend: 'wifi_and_cellular' + }, + project: { + name: this.$t('collectProjectName', this.formDraft), + icon: '📝' + }, + // Collect requires the settings to have an `admin` property. + admin: {} }; - }, - baseUrl() { - return apiPaths.formDraft(this.projectId, this.xmlFormId); } }, created() { @@ -155,7 +163,10 @@ export default { "body": [ "You can use the configuration code to the right to set up a mobile device to download this Draft. You can also click the New button above to create a new Submission from your web browser.", "Draft Submissions go into the test table below, where you can preview and download them. When you publish this Draft Form, its test Submissions will be permanently removed." - ] + ], + // This text will be shown in ODK Collect when testing a Draft Form. {name} + // is the title of the Draft Form. + "collectProjectName": "[Draft] {name}" } } diff --git a/test/components/collect-qr.spec.js b/test/components/collect-qr.spec.js index 7785050ae..b8af9530b 100644 --- a/test/components/collect-qr.spec.js +++ b/test/components/collect-qr.spec.js @@ -8,7 +8,10 @@ import { wait } from '../util/util'; const mountComponent = (propsData) => mount(CollectQr, { propsData: { - settings: { server_url: '/path' }, + settings: { + general: { server_url: 'http://localhost:9876/path' }, + admin: {} + }, errorCorrectionLevel: 'L', cellSize: 1, ...propsData @@ -40,28 +43,20 @@ describe('CollectQr', () => { childNodes[0].tagName.should.equal('IMG'); }); - describe('settings', () => { - it('prepends the origin to server_url', async () => { - const component = mountComponent({ - settings: { server_url: '/path' } - }); - // I think we need to wait for the image to render? - await wait(); - qrData(component).should.eql({ + it('encodes the settings', async () => { + const component = mountComponent({ + settings: { general: { server_url: 'http://localhost:9876/path' }, + project: { name: 'My Project' }, admin: {} - }); + } }); - - it('encodes other settings', async () => { - const component = mountComponent({ - settings: { server_url: '/path', x: 'y' } - }); - await wait(); - qrData(component).should.eql({ - general: { server_url: 'http://localhost:9876/path', x: 'y' }, - admin: {} - }); + // I think we need to wait for the image to render? + await wait(); + qrData(component).should.eql({ + general: { server_url: 'http://localhost:9876/path' }, + project: { name: 'My Project' }, + admin: {} }); }); diff --git a/test/components/field-key/qr-panel.spec.js b/test/components/field-key/qr-panel.spec.js index 85cce7c3d..b83ae4274 100644 --- a/test/components/field-key/qr-panel.spec.js +++ b/test/components/field-key/qr-panel.spec.js @@ -9,11 +9,13 @@ const mountComponent = (propsData) => mount(FieldKeyQrPanel, { propsData: { fieldKey: new FieldKey(testData.extendedFieldKeys.last()), ...propsData - } + }, + requestData: { project: testData.extendedProjects.last() } }); describe('FieldKeyQrPanel', () => { beforeEach(() => { + testData.extendedProjects.createPast(1, { name: 'My Project' }); testData.extendedFieldKeys.createPast(1, { displayName: 'My App User' }); }); @@ -22,9 +24,13 @@ describe('FieldKeyQrPanel', () => { const panel = mountComponent({ managed: true }); const { token } = testData.extendedFieldKeys.last(); panel.first(CollectQr).getProp('settings').should.eql({ - server_url: `/v1/key/${token}/projects/1`, - form_update_mode: 'match_exactly', - autosend: 'wifi_and_cellular' + general: { + server_url: `http://localhost:9876/v1/key/${token}/projects/1`, + form_update_mode: 'match_exactly', + autosend: 'wifi_and_cellular' + }, + project: { name: 'My Project' }, + admin: {} }); }); @@ -32,7 +38,11 @@ describe('FieldKeyQrPanel', () => { const panel = mountComponent({ managed: false }); const { token } = testData.extendedFieldKeys.last(); panel.first(CollectQr).getProp('settings').should.eql({ - server_url: `/v1/key/${token}/projects/1` + general: { + server_url: `http://localhost:9876/v1/key/${token}/projects/1` + }, + project: { name: 'My Project' }, + admin: {} }); }); }); diff --git a/test/components/form-draft/testing.spec.js b/test/components/form-draft/testing.spec.js index 8f9abb419..36de84f00 100644 --- a/test/components/form-draft/testing.spec.js +++ b/test/components/form-draft/testing.spec.js @@ -19,13 +19,19 @@ describe('FormDraftTesting', () => { it('shows a QR code that encodes the correct settings', async () => { mockLogin(); - testData.extendedForms.createPast(1, { draft: true }); + testData.extendedForms.createPast(1, { name: 'My Form', draft: true }); const component = await load('/projects/1/forms/f/draft/testing', { root: false }); const { draftToken } = testData.extendedFormDrafts.last(); component.first(CollectQr).getProp('settings').should.eql({ - server_url: `/v1/test/${draftToken}/projects/1/forms/f/draft` + general: { + server_url: `http://localhost:9876/v1/test/${draftToken}/projects/1/forms/f/draft`, + form_update_mode: 'match_exactly', + autosend: 'wifi_and_cellular' + }, + project: { name: '[Draft] My Form', icon: '📝' }, + admin: {} }); }); diff --git a/transifex/strings_en.json b/transifex/strings_en.json index bf7f1d894..6b4d3774c 100644 --- a/transifex/strings_en.json +++ b/transifex/strings_en.json @@ -1790,6 +1790,10 @@ "1": { "string": "Draft Submissions go into the test table below, where you can preview and download them. When you publish this Draft Form, its test Submissions will be permanently removed." } + }, + "collectProjectName": { + "string": "[Draft] {name}", + "developer_comment": "This text will be shown in ODK Collect when testing a Draft Form. {name} is the title of the Draft Form." } }, "FormHead": {