diff options
author | Phil Hughes <me@iamphill.com> | 2017-05-17 17:48:15 +0300 |
---|---|---|
committer | Phil Hughes <me@iamphill.com> | 2017-05-17 17:48:15 +0300 |
commit | 4f0849f2fd1427b21bd6a043223f49d0c77fa3a3 (patch) | |
tree | 0c5922905959b40f17f3825764e94b9c27436f8e | |
parent | 3301ca10552e7d95d7fb5108a180caa38ddfb9c5 (diff) | |
parent | 81c69c288b626a5bea2d5abddfe5dab1107e35e1 (diff) |
Merge branch 'issue-edit-inline' into issue-edit-inline-description-template
[ci skip]
9 files changed, 100 insertions, 4 deletions
diff --git a/app/assets/javascripts/issue_show/components/app.vue b/app/assets/javascripts/issue_show/components/app.vue index 37326d2ae5b..9cd454e9f73 100644 --- a/app/assets/javascripts/issue_show/components/app.vue +++ b/app/assets/javascripts/issue_show/components/app.vue @@ -46,6 +46,10 @@ export default { required: false, default: () => [], }, + isConfidential: { + type: Boolean, + required: true, + }, markdownPreviewUrl: { type: String, required: true, @@ -91,6 +95,7 @@ export default { this.showForm = true; this.store.formState = { title: this.state.titleText, + confidential: this.isConfidential, description: this.state.descriptionText, }; }, @@ -99,7 +104,13 @@ export default { }, updateIssuable() { this.service.updateIssuable(this.store.formState) - .then(() => { + .then((res) => { + const data = res.json(); + + if (data.confidential !== this.isConfidential) { + location.reload(); + } + eventHub.$emit('close.form'); }) .catch(() => { diff --git a/app/assets/javascripts/issue_show/components/edit_actions.vue b/app/assets/javascripts/issue_show/components/edit_actions.vue index 4cefb236d32..e57b867f93b 100644 --- a/app/assets/javascripts/issue_show/components/edit_actions.vue +++ b/app/assets/javascripts/issue_show/components/edit_actions.vue @@ -7,6 +7,10 @@ type: Boolean, required: true, }, + formState: { + type: Object, + required: true, + }, }, data() { return { @@ -14,6 +18,11 @@ updateLoading: false, }; }, + computed: { + isSubmitEnabled() { + return this.formState.title.trim() !== ''; + }, + }, methods: { updateIssuable() { this.updateLoading = true; @@ -38,9 +47,9 @@ <div class="prepend-top-default append-bottom-default clearfix"> <button class="btn btn-save pull-left" - :class="{ disabled: updateLoading }" + :class="{ disabled: updateLoading || !isSubmitEnabled }" type="submit" - :disabled="updateLoading" + :disabled="updateLoading || !isSubmitEnabled" @click="updateIssuable"> Save changes <i diff --git a/app/assets/javascripts/issue_show/components/fields/confidential_checkbox.vue b/app/assets/javascripts/issue_show/components/fields/confidential_checkbox.vue new file mode 100644 index 00000000000..a0ff08e9111 --- /dev/null +++ b/app/assets/javascripts/issue_show/components/fields/confidential_checkbox.vue @@ -0,0 +1,23 @@ +<script> + export default { + props: { + formState: { + type: Object, + required: true, + }, + }, + }; +</script> + +<template> + <fieldset class="checkbox"> + <label for="issue-confidential"> + <input + type="checkbox" + value="1" + id="issue-confidential" + v-model="formState.confidential" /> + This issue is confidential and should only be visible to team members with at least Reporter access. + </label> + </fieldset> +</template> diff --git a/app/assets/javascripts/issue_show/components/form.vue b/app/assets/javascripts/issue_show/components/form.vue index 429cb9fdf50..facdca4072d 100644 --- a/app/assets/javascripts/issue_show/components/form.vue +++ b/app/assets/javascripts/issue_show/components/form.vue @@ -3,6 +3,7 @@ import descriptionField from './fields/description.vue'; import editActions from './edit_actions.vue'; import descriptionTemplate from './fields/description_template.vue'; + import confidentialCheckbox from './fields/confidential_checkbox.vue'; export default { props: { @@ -41,6 +42,7 @@ descriptionField, descriptionTemplate, editActions, + confidentialCheckbox, }, computed: { hasIssuableTemplates() { @@ -76,7 +78,10 @@ :form-state="formState" :markdown-preview-url="markdownPreviewUrl" :markdown-docs="markdownDocs" /> + <confidential-checkbox + :form-state="formState" /> <edit-actions + :form-state="formState" :can-destroy="canDestroy" /> </form> </template> diff --git a/app/assets/javascripts/issue_show/index.js b/app/assets/javascripts/issue_show/index.js index fdfd9732a91..f368dd5902c 100644 --- a/app/assets/javascripts/issue_show/index.js +++ b/app/assets/javascripts/issue_show/index.js @@ -27,6 +27,7 @@ document.addEventListener('DOMContentLoaded', () => { canDestroy, endpoint, issuableRef, + isConfidential, markdownPreviewUrl, markdownDocs, } = issuableElement.dataset; @@ -39,7 +40,7 @@ document.addEventListener('DOMContentLoaded', () => { initialTitle: issuableTitleElement.innerHTML, initialDescriptionHtml: issuableDescriptionElement ? issuableDescriptionElement.innerHTML : '', initialDescriptionText: issuableDescriptionTextarea ? issuableDescriptionTextarea.textContent : '', - issuableTemplates: initialData.templates, + isConfidential: gl.utils.convertPermissionToBoolean(isConfidential), markdownPreviewUrl, markdownDocs, projectPath: initialData.project_path, @@ -57,6 +58,7 @@ document.addEventListener('DOMContentLoaded', () => { initialDescriptionHtml: this.initialDescriptionHtml, initialDescriptionText: this.initialDescriptionText, issuableTemplates: this.issuableTemplates, + isConfidential: this.isConfidential, markdownPreviewUrl: this.markdownPreviewUrl, markdownDocs: this.markdownDocs, projectPath: this.projectPath, diff --git a/app/assets/javascripts/issue_show/stores/index.js b/app/assets/javascripts/issue_show/stores/index.js index 3232875000d..d90716bef80 100644 --- a/app/assets/javascripts/issue_show/stores/index.js +++ b/app/assets/javascripts/issue_show/stores/index.js @@ -14,6 +14,7 @@ export default class Store { }; this.formState = { title: '', + confidential: false, description: '', }; } diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index 3518bf54666..3c55a517a31 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -56,6 +56,7 @@ "can-update" => can?(current_user, :update_issue, @issue).to_s, "can-destroy" => can?(current_user, :destroy_issue, @issue).to_s, "issuable-ref" => @issue.to_reference, + "is-confidential" => @issue.confidential.to_s, "markdown-preview-url" => preview_markdown_path(@project), "markdown-docs" => help_page_path('user/markdown'), } } diff --git a/spec/javascripts/issue_show/components/app_spec.js b/spec/javascripts/issue_show/components/app_spec.js index 22b0a0f7046..36cd174d341 100644 --- a/spec/javascripts/issue_show/components/app_spec.js +++ b/spec/javascripts/issue_show/components/app_spec.js @@ -35,6 +35,7 @@ describe('Issuable output', () => { initialDescriptionHtml: '', initialDescriptionText: '', showForm: false, + isConfidential: false, }, }).$mount(); }); @@ -108,6 +109,29 @@ describe('Issuable output', () => { }); }); + it('reloads the page if the confidential status has changed', (done) => { + spyOn(window.location, 'reload'); + spyOn(vm.service, 'updateIssuable').and.callFake(() => new Promise((resolve) => { + resolve({ + json() { + return { + confidential: true, + }; + }, + }); + })); + + vm.updateIssuable(); + + setTimeout(() => { + expect( + window.location.reload, + ).toHaveBeenCalled(); + + done(); + }); + }); + it('closes form on error', (done) => { spyOn(window, 'Flash').and.callThrough(); spyOn(vm.service, 'updateIssuable').and.callFake(() => new Promise((resolve, reject) => { diff --git a/spec/javascripts/issue_show/components/edit_actions_spec.js b/spec/javascripts/issue_show/components/edit_actions_spec.js index 8fbaf6cfb2b..f6625b748b6 100644 --- a/spec/javascripts/issue_show/components/edit_actions_spec.js +++ b/spec/javascripts/issue_show/components/edit_actions_spec.js @@ -1,18 +1,26 @@ import Vue from 'vue'; import editActions from '~/issue_show/components/edit_actions.vue'; import eventHub from '~/issue_show/event_hub'; +import Store from '~/issue_show/stores'; describe('Edit Actions components', () => { let vm; beforeEach((done) => { const Component = Vue.extend(editActions); + const store = new Store({ + titleHtml: '', + descriptionHtml: '', + issuableRef: '', + }); + store.formState.title = 'test'; spyOn(eventHub, '$emit'); vm = new Component({ propsData: { canDestroy: true, + formState: store.formState, }, }).$mount(); @@ -41,6 +49,18 @@ describe('Edit Actions components', () => { }); }); + it('disables submit button when title is blank', (done) => { + vm.formState.title = ''; + + Vue.nextTick(() => { + expect( + vm.$el.querySelector('.btn-save').getAttribute('disabled'), + ).toBe('disabled'); + + done(); + }); + }); + describe('updateIssuable', () => { it('sends update.issauble event when clicking save button', () => { vm.$el.querySelector('.btn-save').click(); |