Commit 76cdb8ee authored by Regis's avatar Regis

render description - tasks work - gfm is juicy

parent d3a788da
import Vue from 'vue'; import Vue from 'vue';
import IssueTitle from './issue_title.vue'; import IssueTitle from './issue_title_description.vue';
import '../vue_shared/vue_resource_interceptor'; import '../vue_shared/vue_resource_interceptor';
(() => { (() => {
const issueTitleData = document.querySelector('.issue-title-data').dataset; const issueTitleData = document.querySelector('.issue-title-data').dataset;
const { initialTitle, endpoint } = issueTitleData; const { candescription, endpoint } = issueTitleData;
const vm = new Vue({ const vm = new Vue({
el: '.issue-title-entrypoint', el: '.issue-title-entrypoint',
render: createElement => createElement(IssueTitle, { render: createElement => createElement(IssueTitle, {
props: { props: {
initialTitle, candescription,
endpoint, endpoint,
}, },
}), }),
......
...@@ -5,8 +5,8 @@ import Service from './services/index'; ...@@ -5,8 +5,8 @@ import Service from './services/index';
export default { export default {
props: { props: {
initialTitle: { required: true, type: String },
endpoint: { required: true, type: String }, endpoint: { required: true, type: String },
candescription: { required: true, type: String },
}, },
data() { data() {
const resource = new Service(this.$http, this.endpoint); const resource = new Service(this.$http, this.endpoint);
...@@ -30,7 +30,8 @@ export default { ...@@ -30,7 +30,8 @@ export default {
return { return {
poll, poll,
timeoutId: null, timeoutId: null,
title: this.initialTitle, title: null,
description: null,
}; };
}, },
methods: { methods: {
...@@ -39,26 +40,50 @@ export default { ...@@ -39,26 +40,50 @@ export default {
this.triggerAnimation(body); this.triggerAnimation(body);
}, },
triggerAnimation(body) { triggerAnimation(body) {
const { title } = body; const { title, description } = body;
this.descriptionText = body.description_text;
/** /**
* since opacity is changed, even if there is no diff for Vue to update * since opacity is changed, even if there is no diff for Vue to update
* we must check the title even on a 304 to ensure no visual change * we must check the title even on a 304 to ensure no visual change
*/ */
if (this.title === title) return; const noTitleChange = this.title === title;
const noDescriptionChange = this.description === description;
if (noTitleChange && noDescriptionChange) return;
const elementsToVisualize = [];
if (!noTitleChange) {
elementsToVisualize.push(this.$el.querySelector('.title'));
} else if (!noDescriptionChange) {
elementsToVisualize.push(this.$el.querySelector('.wiki'));
}
this.$el.style.opacity = 0; elementsToVisualize.forEach((element) => {
element.classList.remove('issue-realtime-trigger-pulse');
element.classList.add('issue-realtime-pre-pulse');
});
this.timeoutId = setTimeout(() => { this.timeoutId = setTimeout(() => {
this.title = title; this.title = title;
this.description = description;
this.$el.style.transition = 'opacity 0.2s ease'; elementsToVisualize.forEach((element) => {
this.$el.style.opacity = 1; element.classList.remove('issue-realtime-pre-pulse');
element.classList.add('issue-realtime-trigger-pulse');
});
clearTimeout(this.timeoutId); clearTimeout(this.timeoutId);
}, 100); }, 100);
}, },
}, },
computed: {
descriptionClass() {
return `description ${this.candescription} is-task-list-enabled`;
},
},
created() { created() {
if (!Visibility.hidden()) { if (!Visibility.hidden()) {
this.poll.makeRequest(); this.poll.makeRequest();
...@@ -72,9 +97,32 @@ export default { ...@@ -72,9 +97,32 @@ export default {
} }
}); });
}, },
updated() {
new gl.TaskList({
dataType: 'issue',
fieldName: 'description',
selector: '.detail-page-description',
}).init();
$(this.$refs['issue-content-container-gfm-entry']).renderGFM();
},
}; };
</script> </script>
<template> <template>
<h2 class="title" v-html="title"></h2> <div>
<h2 class="title issue-realtime-trigger-pulse" v-html="title"></h2>
<div
:class="descriptionClass"
v-if="description"
>
<div
class="wiki issue-realtime-trigger-pulse"
v-html="description"
ref="issue-content-container-gfm-entry"
>
</div>
<textarea class="hidden js-task-list-field" v-if="descriptionText">{{descriptionText}}</textarea>
</div>
</div>
</template> </template>
...@@ -18,6 +18,15 @@ ...@@ -18,6 +18,15 @@
} }
} }
.issue-realtime-pre-pulse {
opacity: 0;
}
.issue-realtime-trigger-pulse {
transition: opacity 0.2s ease;
opacity: 1;
}
.check-all-holder { .check-all-holder {
line-height: 36px; line-height: 36px;
float: left; float: left;
......
...@@ -198,7 +198,11 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -198,7 +198,11 @@ class Projects::IssuesController < Projects::ApplicationController
def rendered_title def rendered_title
Gitlab::PollingInterval.set_header(response, interval: 3_000) Gitlab::PollingInterval.set_header(response, interval: 3_000)
render json: { title: view_context.markdown_field(@issue, :title) } render json: {
title: view_context.markdown_field(@issue, :title),
description: view_context.markdown_field(@issue, :description),
description_text: @issue.description,
}
end end
protected protected
......
...@@ -51,17 +51,11 @@ ...@@ -51,17 +51,11 @@
.issue-details.issuable-details .issue-details.issuable-details
.detail-page-description.content-block{ class: ('hide-bottom-border' unless @issue.description.present? ) } .detail-page-description.content-block{ class: ('hide-bottom-border' unless @issue.description.present? ) }
.issue-title-data.hidden{ "data" => { "initial-title" => markdown_field(@issue, :title), .issue-title-data.hidden{ "data" => { "endpoint" => rendered_title_namespace_project_issue_path(@project.namespace, @project, @issue),
"endpoint" => rendered_title_namespace_project_issue_path(@project.namespace, @project, @issue), "canDescription" => can?(current_user, :update_issue, @issue) ? 'js-task-list-container' : '',
} } } }
.issue-title-entrypoint .issue-title-entrypoint
- if @issue.description.present?
.description{ class: can?(current_user, :update_issue, @issue) ? 'js-task-list-container' : '' }
.wiki
= preserve do
= 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') = edited_time_ago_with_tooltip(@issue, placement: 'bottom', html_class: 'issue_edited_ago')
#merge-requests{ data: { url: referenced_merge_requests_namespace_project_issue_url(@project.namespace, @project, @issue) } } #merge-requests{ data: { url: referenced_merge_requests_namespace_project_issue_url(@project.namespace, @project, @issue) } }
......
import Vue from 'vue'; import Vue from 'vue';
import issueTitle from '~/issue_show/issue_title.vue'; import issueTitle from '~/issue_show/issue_title_description.vue';
describe('Issue Title', () => { describe('Issue Title', () => {
let IssueTitleComponent; let IssueTitleComponent;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment