Skip to content

Commit

Permalink
Merge pull request #313 from getodk/loading-after-create-draft
Browse files Browse the repository at this point in the history
Show loading message immediately after create draft button is clicked
  • Loading branch information
matthew-white authored Apr 22, 2020
2 parents 5bff9f1 + f653d34 commit e20603c
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 33 deletions.
26 changes: 3 additions & 23 deletions src/components/form/head.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ including this file, may be copied, modified, propagated, or distributed
except according to the terms contained in the LICENSE file.
-->
<template>
<div v-show="dataExists" id="form-head">
<div id="form-head">
<div id="form-head-project-nav" class="row">
<div class="col-xs-12">
<div v-if="project !=null">
Expand Down Expand Up @@ -67,10 +67,8 @@ except according to the terms contained in the LICENSE file.
class="col-xs-6" :class="{ 'draft-exists': formDraft.isDefined() }">
<button v-show="formDraft.isEmpty()"
id="form-head-create-draft-button" type="primary"
class="btn btn-primary" :disabled="awaitingResponse"
@click="createDraft">
class="btn btn-primary" @click="$emit('create-draft')">
<span class="icon-plus-circle"></span>Create a new Draft
<spinner :state="awaitingResponse"/>
</button>
<ul v-show="formDraft.isDefined()" class="nav nav-tabs">
<li v-if="canRoute(tabPath('draft'))" :class="tabClass('draft')"
Expand Down Expand Up @@ -105,25 +103,15 @@ except according to the terms contained in the LICENSE file.
<script>
import { mapGetters } from 'vuex';

import Spinner from '../spinner.vue';
import request from '../../mixins/request';
import routes from '../../mixins/routes';
import tab from '../../mixins/tab';
import { apiPaths } from '../../util/request';
import { noop } from '../../util/util';
import { requestData } from '../../store/modules/request';

const requestKeys = ['project', 'form', 'formDraft', 'attachments'];

export default {
name: 'FormHead',
components: { Spinner },
mixins: [request(), routes(), tab()],
data() {
return {
awaitingResponse: false
};
},
mixins: [routes(), tab()],
computed: {
// The component does not assume that this data will exist when the
// component is created.
Expand Down Expand Up @@ -154,14 +142,6 @@ export default {
if (this.form != null && this.form.publishedAt == null)
htmlClass.disabled = true;
return htmlClass;
},
createDraft() {
this.post(apiPaths.formDraft(this.form.projectId, this.form.xmlFormId))
.then(() => {
this.$emit('fetch-draft');
this.$router.push(this.formPath('draft'));
})
.catch(noop);
}
}
};
Expand Down
23 changes: 20 additions & 3 deletions src/components/form/show.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ except according to the terms contained in the LICENSE file.
-->
<template>
<div>
<form-head @fetch-draft="fetchDraft"/>
<form-head v-show="dataExists && !awaitingResponse"
@create-draft="createDraft"/>
<page-body>
<loading :state="initiallyLoading"/>
<div v-show="dataExists">
<loading :state="initiallyLoading || awaitingResponse"/>
<div v-show="dataExists && !awaitingResponse">
<!-- <router-view> is immediately created and can send its own requests
even before the server has responded to the requests from ProjectHome
and FormShow. -->
Expand All @@ -28,6 +29,8 @@ except according to the terms contained in the LICENSE file.
import FormHead from './head.vue';
import Loading from '../loading.vue';
import PageBody from '../page/body.vue';
import request from '../../mixins/request';
import routes from '../../mixins/routes';
import { apiPaths } from '../../util/request';
import { noop } from '../../util/util';

Expand All @@ -36,6 +39,7 @@ const REQUEST_KEYS = ['project', 'form', 'formDraft', 'attachments'];
export default {
name: 'FormShow',
components: { FormHead, Loading, PageBody },
mixins: [request(), routes()],
props: {
projectId: {
type: String,
Expand All @@ -46,6 +50,11 @@ export default {
required: true
}
},
data() {
return {
awaitingResponse: false
};
},
computed: {
initiallyLoading() {
return this.$store.getters.initiallyLoading(REQUEST_KEYS);
Expand Down Expand Up @@ -87,6 +96,14 @@ export default {
fetchData() {
this.fetchForm();
this.fetchDraft();
},
createDraft() {
this.post(apiPaths.formDraft(this.projectId, this.xmlFormId))
.then(() => {
this.fetchDraft();
this.$router.push(this.formPath('draft'));
})
.catch(noop);
}
}
};
Expand Down
46 changes: 39 additions & 7 deletions test/components/form/head.spec.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import FormDraftStatus from '../../../src/components/form-draft/status.vue';
import FormHead from '../../../src/components/form/head.vue';
import FormOverview from '../../../src/components/form/overview.vue';
import Loading from '../../../src/components/loading.vue';
import testData from '../../data';
import { load } from '../../util/http';
import { mockLogin } from '../../util/session';
Expand Down Expand Up @@ -204,12 +208,6 @@ describe('FormHead', () => {
app.first('#form-head-create-draft-button').should.be.visible();
}));

it('implements some standard button things', () =>
load('/projects/1/forms/f')
.complete()
.request(app => trigger.click(app, '#form-head-create-draft-button'))
.standardButton('#form-head-create-draft-button'));

it('posts to the correct endpoint', () =>
load('/projects/1/forms/f')
.complete()
Expand All @@ -220,7 +218,7 @@ describe('FormHead', () => {
})
.respondWithProblem());

it('redirects to .../draft', () =>
it('redirects to .../draft after a successful response', () =>
load('/projects/1/forms/f')
.complete()
.request(app => trigger.click(app, '#form-head-create-draft-button'))
Expand All @@ -234,6 +232,40 @@ describe('FormHead', () => {
.afterResponses(app => {
app.vm.$route.path.should.equal('/projects/1/forms/f/draft');
}));

it('shows a danger alert after a Problem response', () =>
load('/projects/1/forms/f')
.complete()
.request(app => trigger.click(app, '#form-head-create-draft-button'))
.beforeAnyResponse(app => {
app.should.not.alert();
})
.respondWithProblem()
.afterResponse(app => {
app.should.alert('danger');
}));

it('shows a loading message during the request', () =>
load('/projects/1/forms/f')
.complete()
.request(app => trigger.click(app, '#form-head-create-draft-button'))
.beforeAnyResponse(app => {
app.first(Loading).should.be.visible();
app.first(FormHead).should.be.hidden();
app.first(FormOverview).vm.$el.parentNode.should.be.hidden();
})
.respondWithSuccess()
.respondFor('/projects/1/forms/f/draft', {
project: false,
form: false,
formDraft: () =>
testData.extendedFormDrafts.createNew({ draft: true })
})
.afterResponses(app => {
app.first(Loading).should.be.hidden();
app.first(FormHead).should.be.visible();
app.first(FormDraftStatus).should.be.visible();
}));
});
});
});

0 comments on commit e20603c

Please sign in to comment.