Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Send requests needed for form infonav buttons #1134

Merged
merged 3 commits into from
Feb 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 4 additions & 5 deletions src/components/form-draft/status.vue
Original file line number Diff line number Diff line change
Expand Up @@ -120,12 +120,12 @@ export default {
required: true
}
},
emits: ['fetch-project', 'fetch-form', 'fetch-draft'],
emits: ['fetch-project', 'fetch-form', 'fetch-draft', 'fetch-linked-datasets'],
setup() {
const { form, publishedAttachments, formVersions, formDraft, datasets, formDatasetDiff, formDraftDatasetDiff } = useRequestData();
const { form, formVersions, formDraft, datasets, formDraftDatasetDiff } = useRequestData();
const { projectPath, publishedFormPath } = useRoutes();
return {
form, publishedAttachments, formVersions, formDraft, datasets, formDatasetDiff, formDraftDatasetDiff,
form, formVersions, formDraft, datasets, formDraftDatasetDiff,
projectPath, publishedFormPath
};
},
Expand Down Expand Up @@ -163,9 +163,8 @@ export default {
this.$emit('fetch-form');

// Other resources that may have changed after publish
this.publishedAttachments.reset();
this.$emit('fetch-linked-datasets');
this.datasets.reset();
this.formDatasetDiff.reset();
this.formDraftDatasetDiff.reset();

// We will update additional resources, but only after navigating to the
Expand Down
168 changes: 95 additions & 73 deletions src/components/form/show.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,96 +19,118 @@ except according to the terms contained in the LICENSE file.
responded to the requests from FormShow. -->
<router-view v-show="dataExists && !awaitingResponse"
@fetch-project="fetchProject" @fetch-form="fetchForm"
@fetch-draft="fetchDraft"/>
@fetch-draft="fetchDraft" @fetch-linked-datasets="fetchLinkedDatasets"/>
</page-body>
</div>
</template>

<script>
<script setup>
import { nextTick, watchEffect } from 'vue';
import { useRouter } from 'vue-router';

import FormHead from './head.vue';
import Loading from '../loading.vue';
import PageBody from '../page/body.vue';

import useForm from '../../request-data/form';
import useDatasets from '../../request-data/datasets';
import useForm from '../../request-data/form';
import useRequest from '../../composables/request';
import useRoutes from '../../composables/routes';
import { apiPaths } from '../../util/request';
import { noop } from '../../util/util';
import { useRequestData } from '../../request-data';

export default {
name: 'FormShow',
components: { FormHead, Loading, PageBody },
props: {
projectId: {
type: String,
required: true
},
xmlFormId: {
type: String,
required: true
}
defineOptions({
name: 'FormShow'
});
const props = defineProps({
projectId: {
type: String,
required: true
},
setup() {
const { project, resourceStates } = useRequestData();
const { form, formDraft, attachments } = useForm();
useDatasets();
xmlFormId: {
type: String,
required: true
}
});

const { request, awaitingResponse } = useRequest();
const { formPath } = useRoutes();
return {
project, form, formDraft, attachments,
...resourceStates([project, form, formDraft, attachments]),
request, awaitingResponse, formPath
};
},
created() {
this.fetchData();
},
methods: {
fetchProject(resend) {
this.project.request({
url: apiPaths.project(this.projectId),
extended: true,
resend
}).catch(noop);
},
fetchForm() {
const url = apiPaths.form(this.projectId, this.xmlFormId);
this.form.request({ url, extended: true })
.catch(noop);
},
fetchDraft() {
const draftUrl = apiPaths.formDraft(this.projectId, this.xmlFormId);
Promise.allSettled([
this.formDraft.request({
url: draftUrl,
extended: true,
fulfillProblem: ({ code }) => code === 404.1
}),
this.attachments.request({
url: apiPaths.formDraftAttachments(this.projectId, this.xmlFormId),
fulfillProblem: ({ code }) => code === 404.1
})
]);
},
fetchData() {
this.fetchProject(false);
this.fetchForm();
this.fetchDraft();
},
createDraft() {
this.request({
method: 'POST',
url: apiPaths.formDraft(this.projectId, this.xmlFormId)
})
.then(() => {
this.fetchDraft();
this.$router.push(this.formPath('draft'));
})
.catch(noop);
}
const { project, resourceStates } = useRequestData();
const { form, formDraft, attachments, publishedAttachments, formDatasetDiff, appUserCount } = useForm();
useDatasets();
const { initiallyLoading, dataExists } = resourceStates([project, form, formDraft, attachments]);

const fetchProject = (resend) => {
project.request({
url: apiPaths.project(props.projectId),
extended: true,
resend
}).catch(noop);
};
const fetchForm = () => {
form.request({
url: apiPaths.form(props.projectId, props.xmlFormId),
extended: true
}).catch(noop);
};
const fetchDraft = () => {
Promise.allSettled([
formDraft.request({
url: apiPaths.formDraft(props.projectId, props.xmlFormId),
extended: true,
fulfillProblem: ({ code }) => code === 404.1
}),
attachments.request({
url: apiPaths.formDraftAttachments(props.projectId, props.xmlFormId),
fulfillProblem: ({ code }) => code === 404.1
})
]);
};
const fetchLinkedDatasets = () => {
Promise.allSettled([
publishedAttachments.request({
url: apiPaths.publishedAttachments(props.projectId, props.xmlFormId)
}),
formDatasetDiff.request({
url: apiPaths.formDatasetDiff(props.projectId, props.xmlFormId)
})
]);
};

fetchProject(false);
fetchForm();
fetchDraft();
// Before sending certain requests, we wait for the project response in order to
// check whether the user has the correct permissions.
const stopWaitingForProject = watchEffect(() => {
if (!project.dataExists) return;
if (project.permits(['form.update', 'dataset.list'])) fetchLinkedDatasets();
if (project.permits('assignment.list')) {
appUserCount.request({
url: apiPaths.formActors(props.projectId, props.xmlFormId, 'app-user')
}).catch(noop);
}
/* It doesn't work to call stopWaitingForProject() synchronously. You can see
that if you remove the nextTick() and try running tests. I think the reason
why is that if you navigate from another page that has fetched `project`
already (e.g., the form list), then project.dataExists will be `true`, so the
watch effect will complete synchronously during component setup. But in that
case, watchEffect() won't have had a chance to return a value:
stopWaitingForProject won't be assigned yet. */
nextTick(() => stopWaitingForProject());
});

const { request, awaitingResponse } = useRequest();
const router = useRouter();
const { formPath } = useRoutes();
const createDraft = () => {
request({
method: 'POST',
url: apiPaths.formDraft(props.projectId, props.xmlFormId)
})
.then(() => {
fetchDraft();
router.push(formPath('draft'));
})
.catch(noop);
};
</script>
5 changes: 4 additions & 1 deletion src/request-data/form.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ export default () => {
.filter(a => a.datasetExists)
.map(a => a.name.replace(/\.csv$/i, '')))
}));
const appUserCount = createResource('appUserCount', () => ({
transformResponse: ({ data }) => data.length
}));

watchSyncEffect(() => {
if (form.dataExists && publicLinks.dataExists &&
Expand All @@ -42,6 +45,6 @@ export default () => {
});

return {
form, formDraft, attachments, formVersions, formVersionXml, publicLinks, formDraftDatasetDiff, formDatasetDiff, publishedAttachments
form, formDraft, attachments, formVersions, formVersionXml, publicLinks, formDraftDatasetDiff, formDatasetDiff, publishedAttachments, appUserCount
};
};
34 changes: 12 additions & 22 deletions test/components/form-attachment/list.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1129,12 +1129,8 @@ describe('FormAttachmentList', () => {
});
return load('/projects/1/forms/f/draft/attachments')
.complete()
.load('/projects/1/forms/f/draft', {
project: false,
form: false,
formDraft: false,
attachments: false
})
.route('/projects/1/forms/f/draft')
.respondWithData(() => testData.extendedFormVersions.published())
.complete()
.request(async (app) => {
await app.get('#form-draft-status-publish-button').trigger('click');
Expand All @@ -1147,11 +1143,10 @@ describe('FormAttachmentList', () => {
return { success: true };
})
.respondWithData(() => testData.extendedForms.last())
.respondFor('/projects/1/forms/f/submissions', {
form: false,
formDraft: false,
attachments: false
})
.respondWithData(() => testData.standardFormAttachments.sorted()) // publishedAttachments
.respondWithData(() => testData.formDatasetDiffs.sorted())
.respondWithData(() => testData.extendedProjects.last())
.respondForComponent('FormSubmissions')
.complete()
.request(app =>
app.get('#form-head-create-draft-button').trigger('click'))
Expand Down Expand Up @@ -1189,12 +1184,8 @@ describe('FormAttachmentList', () => {
return load('/projects/1/forms/f/draft/attachments')
.respondWithData(() => testData.extendedDatasets.sorted())
.complete()
.load('/projects/1/forms/f/draft', {
project: false,
form: false,
formDraft: false,
attachments: false
})
.route('/projects/1/forms/f/draft')
.respondWithData(() => testData.extendedFormVersions.published())
.complete()
.request(async (app) => {
await app.get('#form-draft-status-publish-button').trigger('click');
Expand All @@ -1207,11 +1198,10 @@ describe('FormAttachmentList', () => {
return { success: true };
})
.respondWithData(() => testData.extendedForms.last())
.respondFor('/projects/1/forms/f/submissions', {
form: false,
formDraft: false,
attachments: false
})
.respondWithData(() => testData.standardFormAttachments.sorted()) // publishedAttachments
.respondWithData(() => testData.formDatasetDiffs.sorted())
.respondWithData(() => testData.extendedProjects.last())
.respondForComponent('FormSubmissions')
.complete()
.request(app =>
app.get('#form-head-create-draft-button').trigger('click'))
Expand Down
9 changes: 2 additions & 7 deletions test/components/form-draft/abandon.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,12 +126,7 @@ describe('FormDraftAbandon', () => {
return app.get('#form-draft-abandon .btn-danger').trigger('click');
})
.respondWithSuccess()
.respondFor('/projects/1/forms/f/submissions', {
project: false,
form: false,
formDraft: false,
attachments: false
});
.respondForComponent('FormSubmissions');
};

it('shows a success alert', () =>
Expand Down Expand Up @@ -161,7 +156,7 @@ describe('FormDraftAbandon', () => {
})
.respondWithSuccess()
.respondWithData(() => []) // forms
.respondWithData(() => []); // deleted forms
.respondWithData(() => []); // deletedForms
};

it('shows a success alert', () =>
Expand Down
Loading