Skip to content

Commit

Permalink
Merge pull request #475 from getodk/collect-project
Browse files Browse the repository at this point in the history
Add project settings to Collect QR codes
  • Loading branch information
matthew-white authored Jun 25, 2021
2 parents 8282e47 + 0d4efe5 commit 959401d
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 57 deletions.
13 changes: 1 addition & 12 deletions src/components/collect-qr.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
Expand Down
23 changes: 14 additions & 9 deletions src/components/field-key/qr-panel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
29 changes: 20 additions & 9 deletions src/components/form-draft/testing.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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}"
}
}
</i18n>
Expand Down
35 changes: 15 additions & 20 deletions test/components/collect-qr.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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: {}
});
});

Expand Down
20 changes: 15 additions & 5 deletions test/components/field-key/qr-panel.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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' });
});

Expand All @@ -22,17 +24,25 @@ 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: {}
});
});

it('shows a legacy QR code with the correct data', () => {
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: {}
});
});
});
Expand Down
10 changes: 8 additions & 2 deletions test/components/form-draft/testing.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: {}
});
});

Expand Down
4 changes: 4 additions & 0 deletions transifex/strings_en.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down

0 comments on commit 959401d

Please sign in to comment.