diff options
author | Phil Hughes <me@iamphill.com> | 2017-05-22 08:59:37 +0100 |
---|---|---|
committer | Phil Hughes <me@iamphill.com> | 2017-05-22 08:59:37 +0100 |
commit | 7a21e26f4b1243a48e6e31f2b9af6e525ae8ca30 (patch) | |
tree | 15f730d427826f884aa5f84827da6810255cd080 /app/assets | |
parent | 4f0849f2fd1427b21bd6a043223f49d0c77fa3a3 (diff) | |
parent | 3c3b17a5a4b4f85f3f81f918a7e0c3a57f469eb7 (diff) | |
download | gitlab-ce-7a21e26f4b1243a48e6e31f2b9af6e525ae8ca30.tar.gz |
Merge branch 'issue-edit-inline' into issue-edit-inline-description-template
[ci skip]
Diffstat (limited to 'app/assets')
7 files changed, 140 insertions, 14 deletions
diff --git a/app/assets/javascripts/issue_show/components/app.vue b/app/assets/javascripts/issue_show/components/app.vue index 9cd454e9f73..d9bfc29130f 100644 --- a/app/assets/javascripts/issue_show/components/app.vue +++ b/app/assets/javascripts/issue_show/components/app.vue @@ -8,6 +8,7 @@ import Store from '../stores'; import titleComponent from './title.vue'; import descriptionComponent from './description.vue'; import formComponent from './form.vue'; +import '../../lib/utils/url_utility'; export default { props: { @@ -15,6 +16,10 @@ export default { required: true, type: String, }, + canMove: { + required: true, + type: Boolean, + }, canUpdate: { required: true, type: Boolean, @@ -66,6 +71,10 @@ export default { type: String, required: true, }, + projectsAutocompleteUrl: { + type: String, + required: true, + }, }, data() { const store = new Store({ @@ -92,23 +101,27 @@ export default { }, methods: { openForm() { - this.showForm = true; - this.store.formState = { - title: this.state.titleText, - confidential: this.isConfidential, - description: this.state.descriptionText, - }; + if (!this.showForm) { + this.showForm = true; + this.store.formState = { + title: this.state.titleText, + confidential: this.isConfidential, + description: this.state.descriptionText, + move_to_project_id: 0, + }; + } }, closeForm() { this.showForm = false; }, updateIssuable() { this.service.updateIssuable(this.store.formState) - .then((res) => { - const data = res.json(); - - if (data.confidential !== this.isConfidential) { - location.reload(); + .then(res => res.json()) + .then((data) => { + if (location.pathname !== data.path) { + gl.utils.visitUrl(data.path); + } else if (data.confidential !== this.isConfidential) { + gl.utils.visitUrl(location.pathname); } eventHub.$emit('close.form'); @@ -177,12 +190,15 @@ export default { <form-component v-if="canUpdate && showForm" :form-state="formState" + :can-move="canMove" :can-destroy="canDestroy" :issuable-templates="issuableTemplates" :markdown-docs="markdownDocs" :markdown-preview-url="markdownPreviewUrl" :project-path="projectPath" - :project-namespace="projectNamespace" /> + :project-namespace="projectNamespace" + :projects-autocomplete-url="projectsAutocompleteUrl" + /> <div v-else> <title-component :issuable-ref="issuableRef" diff --git a/app/assets/javascripts/issue_show/components/fields/description.vue b/app/assets/javascripts/issue_show/components/fields/description.vue index b4c31811a0b..35b1ea6ff2b 100644 --- a/app/assets/javascripts/issue_show/components/fields/description.vue +++ b/app/assets/javascripts/issue_show/components/fields/description.vue @@ -20,6 +20,9 @@ components: { markdownField, }, + mounted() { + this.$refs.textarea.focus(); + }, }; </script> @@ -39,7 +42,7 @@ data-supports-slash-commands="false" aria-label="Description" v-model="formState.description" - ref="textatea" + ref="textarea" slot="textarea"> </textarea> </markdown-field> diff --git a/app/assets/javascripts/issue_show/components/fields/project_move.vue b/app/assets/javascripts/issue_show/components/fields/project_move.vue new file mode 100644 index 00000000000..f811fb0de24 --- /dev/null +++ b/app/assets/javascripts/issue_show/components/fields/project_move.vue @@ -0,0 +1,83 @@ +<script> + import tooltipMixin from '../../../vue_shared/mixins/tooltip'; + + export default { + mixins: [ + tooltipMixin, + ], + props: { + formState: { + type: Object, + required: true, + }, + projectsAutocompleteUrl: { + type: String, + required: true, + }, + }, + mounted() { + const $moveDropdown = $(this.$refs['move-dropdown']); + + $moveDropdown.select2({ + ajax: { + url: this.projectsAutocompleteUrl, + quietMillis: 125, + data(term, page, context) { + return { + search: term, + offset_id: context, + }; + }, + results(data) { + const more = data.length >= 50; + const context = data[data.length - 1] ? data[data.length - 1].id : null; + + return { + results: data, + more, + context, + }; + }, + }, + formatResult(project) { + return project.name_with_namespace; + }, + formatSelection(project) { + return project.name_with_namespace; + }, + }) + .on('change', (e) => { + this.formState.move_to_project_id = parseInt(e.target.value, 10); + }); + }, + beforeDestroy() { + $(this.$refs['move-dropdown']).select2('destroy'); + }, + }; +</script> + +<template> + <fieldset> + <label + for="issuable-move" + class="sr-only"> + Move + </label> + <div class="issuable-form-select-holder append-right-5"> + <input + ref="move-dropdown" + type="hidden" + id="issuable-move" + data-placeholder="Move to a different project" /> + </div> + <span + data-placement="auto top" + title="Moving an issue will copy the discussion to a different project and close it here. All participants will be notified of the new location." + ref="tooltip"> + <i + class="fa fa-question-circle" + aria-hidden="true"> + </i> + </span> + </fieldset> +</template> diff --git a/app/assets/javascripts/issue_show/components/form.vue b/app/assets/javascripts/issue_show/components/form.vue index facdca4072d..0c8c972ff31 100644 --- a/app/assets/javascripts/issue_show/components/form.vue +++ b/app/assets/javascripts/issue_show/components/form.vue @@ -2,11 +2,19 @@ import titleField from './fields/title.vue'; import descriptionField from './fields/description.vue'; import editActions from './edit_actions.vue'; +<<<<<<< HEAD import descriptionTemplate from './fields/description_template.vue'; +======= + import projectMove from './fields/project_move.vue'; +>>>>>>> issue-edit-inline import confidentialCheckbox from './fields/confidential_checkbox.vue'; export default { props: { + canMove: { + type: Boolean, + required: true, + }, canDestroy: { type: Boolean, required: true, @@ -36,12 +44,17 @@ type: String, required: true, }, + projectsAutocompleteUrl: { + type: String, + required: true, + }, }, components: { titleField, descriptionField, descriptionTemplate, editActions, + projectMove, confidentialCheckbox, }, computed: { @@ -80,6 +93,10 @@ :markdown-docs="markdownDocs" /> <confidential-checkbox :form-state="formState" /> + <project-move + v-if="canMove" + :form-state="formState" + :projects-autocomplete-url="projectsAutocompleteUrl" /> <edit-actions :form-state="formState" :can-destroy="canDestroy" /> diff --git a/app/assets/javascripts/issue_show/index.js b/app/assets/javascripts/issue_show/index.js index f368dd5902c..3b4e5c5488c 100644 --- a/app/assets/javascripts/issue_show/index.js +++ b/app/assets/javascripts/issue_show/index.js @@ -25,16 +25,19 @@ document.addEventListener('DOMContentLoaded', () => { const { canUpdate, canDestroy, + canMove, endpoint, issuableRef, isConfidential, markdownPreviewUrl, markdownDocs, + projectsAutocompleteUrl, } = issuableElement.dataset; return { canUpdate: gl.utils.convertPermissionToBoolean(canUpdate), canDestroy: gl.utils.convertPermissionToBoolean(canDestroy), + canMove: gl.utils.convertPermissionToBoolean(canMove), endpoint, issuableRef, initialTitle: issuableTitleElement.innerHTML, @@ -45,6 +48,7 @@ document.addEventListener('DOMContentLoaded', () => { markdownDocs, projectPath: initialData.project_path, projectNamespace: initialData.namespace_path, + projectsAutocompleteUrl, }; }, render(createElement) { @@ -52,6 +56,7 @@ document.addEventListener('DOMContentLoaded', () => { props: { canUpdate: this.canUpdate, canDestroy: this.canDestroy, + canMove: this.canMove, endpoint: this.endpoint, issuableRef: this.issuableRef, initialTitle: this.initialTitle, @@ -63,6 +68,7 @@ document.addEventListener('DOMContentLoaded', () => { markdownDocs: this.markdownDocs, projectPath: this.projectPath, projectNamespace: this.projectNamespace, + projectsAutocompleteUrl: this.projectsAutocompleteUrl, }, }); }, diff --git a/app/assets/javascripts/issue_show/services/index.js b/app/assets/javascripts/issue_show/services/index.js index 0ceff34cf8b..6f0fd0b1768 100644 --- a/app/assets/javascripts/issue_show/services/index.js +++ b/app/assets/javascripts/issue_show/services/index.js @@ -7,7 +7,7 @@ export default class Service { constructor(endpoint) { this.endpoint = endpoint; - this.resource = Vue.resource(this.endpoint, {}, { + this.resource = Vue.resource(`${this.endpoint}.json`, {}, { realtimeChanges: { method: 'GET', url: `${this.endpoint}/realtime_changes`, diff --git a/app/assets/javascripts/issue_show/stores/index.js b/app/assets/javascripts/issue_show/stores/index.js index d90716bef80..1135bc0bfb5 100644 --- a/app/assets/javascripts/issue_show/stores/index.js +++ b/app/assets/javascripts/issue_show/stores/index.js @@ -16,6 +16,7 @@ export default class Store { title: '', confidential: false, description: '', + move_to_project_id: 0, }; } |