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 f8c8bf6d1..c86aba0f9 100644 --- a/src/components/field-key/qr-panel.vue +++ b/src/components/field-key/qr-panel.vue @@ -70,26 +70,31 @@ import DocLink from '../doc-link.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 }, 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 c53ec5ad9..e5ec87435 100644 --- a/src/components/form-draft/testing.vue +++ b/src/components/form-draft/testing.vue @@ -90,16 +90,20 @@ 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}` }, + 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() { @@ -152,7 +156,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..ceab8cbc7 100644 --- a/test/components/form-draft/testing.spec.js +++ b/test/components/form-draft/testing.spec.js @@ -19,13 +19,17 @@ 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` + }, + project: { name: '[Draft] My Form', icon: '📝' }, + admin: {} }); }); diff --git a/transifex/strings_en.json b/transifex/strings_en.json index 171f52238..ac6606f4d 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": {