diff --git a/app/assets/javascripts/issue_show/actions/tasks.js b/app/assets/javascripts/issue_show/actions/tasks.js deleted file mode 100644 index 0740a9f559c..00000000000 --- a/app/assets/javascripts/issue_show/actions/tasks.js +++ /dev/null @@ -1,27 +0,0 @@ -export default (newStateData, tasks) => { - const $tasks = $('#task_status'); - const $tasksShort = $('#task_status_short'); - const $issueableHeader = $('.issuable-header'); - const tasksStates = { newState: null, currentState: null }; - - if ($tasks.length === 0) { - if (!(newStateData.task_status.indexOf('0 of 0') === 0)) { - $issueableHeader.append(`${newStateData.task_status}`); - } else { - $issueableHeader.append(''); - } - } else { - tasksStates.newState = newStateData.task_status.indexOf('0 of 0') === 0; - tasksStates.currentState = tasks.indexOf('0 of 0') === 0; - } - - if ($tasks.length !== 0 && !tasksStates.newState) { - $tasks.text(newStateData.task_status); - $tasksShort.text(newStateData.task_status); - } else if (tasksStates.currentState) { - $issueableHeader.append(`${newStateData.task_status}`); - } else if (tasksStates.newState) { - $tasks.remove(); - $tasksShort.remove(); - } -}; diff --git a/app/assets/javascripts/issue_show/components/app.vue b/app/assets/javascripts/issue_show/components/app.vue new file mode 100644 index 00000000000..752d07f7ef0 --- /dev/null +++ b/app/assets/javascripts/issue_show/components/app.vue @@ -0,0 +1,95 @@ + + + diff --git a/app/assets/javascripts/issue_show/components/description.vue b/app/assets/javascripts/issue_show/components/description.vue new file mode 100644 index 00000000000..298f87b6d22 --- /dev/null +++ b/app/assets/javascripts/issue_show/components/description.vue @@ -0,0 +1,100 @@ + + + diff --git a/app/assets/javascripts/issue_show/components/title.vue b/app/assets/javascripts/issue_show/components/title.vue new file mode 100644 index 00000000000..a9dabd4cff1 --- /dev/null +++ b/app/assets/javascripts/issue_show/components/title.vue @@ -0,0 +1,53 @@ + + + diff --git a/app/assets/javascripts/issue_show/index.js b/app/assets/javascripts/issue_show/index.js index eb20a597bb5..af11ae4c533 100644 --- a/app/assets/javascripts/issue_show/index.js +++ b/app/assets/javascripts/issue_show/index.js @@ -1,20 +1,32 @@ import Vue from 'vue'; -import IssueTitle from './issue_title_description.vue'; +import issuableApp from './components/app.vue'; import '../vue_shared/vue_resource_interceptor'; -(() => { - const issueTitleData = document.querySelector('.issue-title-data').dataset; - const { canUpdateTasksClass, endpoint } = issueTitleData; +document.addEventListener('DOMContentLoaded', () => { + const issuableElement = document.getElementById('js-issuable-app'); + const issuableTitleElement = issuableElement.querySelector('.title'); + const issuableDescriptionElement = issuableElement.querySelector('.wiki'); + const issuableDescriptionTextarea = issuableElement.querySelector('.js-task-list-field'); + const { + canUpdate, + endpoint, + issuableRef, + } = issuableElement.dataset; - const vm = new Vue({ - el: '.issue-title-entrypoint', - render: createElement => createElement(IssueTitle, { + return new Vue({ + el: issuableElement, + components: { + issuableApp, + }, + render: createElement => createElement('issuable-app', { props: { - canUpdateTasksClass, + canUpdate: gl.utils.convertPermissionToBoolean(canUpdate), endpoint, + issuableRef, + initialTitle: issuableTitleElement.innerHTML, + initialDescriptionHtml: issuableDescriptionElement ? issuableDescriptionElement.innerHTML : '', + initialDescriptionText: issuableDescriptionTextarea ? issuableDescriptionTextarea.textContent : '', }, }), }); - - return vm; -})(); +}); diff --git a/app/assets/javascripts/issue_show/issue_title_description.vue b/app/assets/javascripts/issue_show/issue_title_description.vue deleted file mode 100644 index dc3ba2550c5..00000000000 --- a/app/assets/javascripts/issue_show/issue_title_description.vue +++ /dev/null @@ -1,180 +0,0 @@ - - - diff --git a/app/assets/javascripts/issue_show/mixins/animate.js b/app/assets/javascripts/issue_show/mixins/animate.js new file mode 100644 index 00000000000..eda6302aa8b --- /dev/null +++ b/app/assets/javascripts/issue_show/mixins/animate.js @@ -0,0 +1,13 @@ +export default { + methods: { + animateChange() { + this.preAnimation = true; + this.pulseAnimation = false; + + this.$nextTick(() => { + this.preAnimation = false; + this.pulseAnimation = true; + }); + }, + }, +}; diff --git a/app/assets/javascripts/issue_show/services/index.js b/app/assets/javascripts/issue_show/services/index.js index c4ab0b1e07a..348ad8d6813 100644 --- a/app/assets/javascripts/issue_show/services/index.js +++ b/app/assets/javascripts/issue_show/services/index.js @@ -1,10 +1,16 @@ +import Vue from 'vue'; +import VueResource from 'vue-resource'; + +Vue.use(VueResource); + export default class Service { - constructor(resource, endpoint) { - this.resource = resource; + constructor(endpoint) { this.endpoint = endpoint; + + this.resource = Vue.resource(this.endpoint); } - getTitle() { - return this.resource.get(this.endpoint); + getData() { + return this.resource.get(); } } diff --git a/app/assets/javascripts/issue_show/stores/index.js b/app/assets/javascripts/issue_show/stores/index.js new file mode 100644 index 00000000000..9c759dc53cb --- /dev/null +++ b/app/assets/javascripts/issue_show/stores/index.js @@ -0,0 +1,25 @@ +export default class Store { + constructor({ + title, + descriptionHtml, + descriptionText, + }) { + this.state = { + titleHtml: title, + titleText: '', + descriptionHtml, + descriptionText, + taskStatus: '', + updatedAt: '', + }; + } + + updateState(data) { + this.state.titleHtml = data.title; + this.state.titleText = data.title_text; + this.state.descriptionHtml = data.description; + this.state.descriptionText = data.description_text; + this.state.taskStatus = data.task_status; + this.state.updatedAt = data.updated_at; + } +} diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index 9084883eb3e..bd03593eb98 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -51,10 +51,15 @@ .issue-details.issuable-details .detail-page-description.content-block - .issue-title-data.hidden{ "data" => { "endpoint" => rendered_title_namespace_project_issue_path(@project.namespace, @project, @issue), - "can-update-tasks-class" => can?(current_user, :update_issue, @issue) ? 'js-task-list-container' : '', + #js-issuable-app{ "data" => { "endpoint" => rendered_title_namespace_project_issue_path(@project.namespace, @project, @issue), + "can-update" => can?(current_user, :update_issue, @issue).to_s, + "issuable-ref" => @issue.to_reference, } } - .issue-title-entrypoint + %h2.title= markdown_field(@issue, :title) + - if @issue.description.present? + .description{ class: can?(current_user, :update_issue, @issue) ? 'js-task-list-container' : '' } + .wiki= markdown_field(@issue, :description) + %textarea.hidden.js-task-list-field= @issue.description = edited_time_ago_with_tooltip(@issue, placement: 'bottom', html_class: 'issue_edited_ago')