未验证 提交 62b82080 编写于 作者: F Fatih Acet

Implement discussions component.

上级 fc3d33ca
......@@ -54,7 +54,12 @@ export default {
<template>
<div id="app">
<h2 v-if="isLoading">Loading...</h2>
<p v-if="isLoading" class="loading">
Fetching issuable details and discussions. This may take a while.
<br />
If it doesn't work, please
<a href="https://gitlab.com/fatihacet/gitlab-vscode-extension/issues/new">create an issue.</a>
</p>
<template v-else>
<issuable-details :issuable="issuable" />
<issuable-discussions :discussions="discussions" />
......@@ -65,7 +70,11 @@ export default {
<style lang="scss">
body.vscode-light {
* {
border-color: #333;
border-color: #333 !important;
&::before {
border-color: #333 !important;
}
}
.idiff.deletion {
......@@ -75,6 +84,10 @@ body.vscode-light {
.idiff.addition {
background: #c7f0d2;
}
.issuable-details .state {
color: #fff;
}
}
.capitalize {
text-transform: capitalize;
......@@ -94,4 +107,10 @@ code {
.idiff.addition {
background: #7cba8d;
}
#app .loading {
text-align: center;
font-size: 14px;
line-height: 30px;
}
</style>
<script>
import Note from './Note';
export default {
name: 'Discussion',
props: {
noteable: {
type: Object,
required: true,
},
},
data() {
return {
isRepliesVisible: true,
};
},
components: {
Note,
},
computed: {
initialDiscussion() {
return this.noteable.notes[0];
},
replies() {
return this.noteable.notes.slice(1);
},
hasReplies() {
return this.replies.length > 0;
},
toggleRepliesText() {
return this.isRepliesVisible ? 'Collapse replies' : 'Expand replies';
},
toggleRepliesIcon() {
const chevronDown = '<svg aria-hidden="true" data-prefix="fas" data-icon="chevron-down" class="svg-inline--fa fa-chevron-down fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M207.029 381.476L12.686 187.132c-9.373-9.373-9.373-24.569 0-33.941l22.667-22.667c9.357-9.357 24.522-9.375 33.901-.04L224 284.505l154.745-154.021c9.379-9.335 24.544-9.317 33.901.04l22.667 22.667c9.373 9.373 9.373 24.569 0 33.941L240.971 381.476c-9.373 9.372-24.569 9.372-33.942 0z"></path></svg>';
const chevronRight = '<svg aria-hidden="true" data-prefix="fas" data-icon="chevron-right" class="svg-inline--fa fa-chevron-right fa-w-10" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path fill="currentColor" d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"></path></svg>';
return this.isRepliesVisible ? chevronDown : chevronRight;
},
},
methods: {
toggleReplies() {
this.isRepliesVisible = !this.isRepliesVisible;
},
},
};
</script>
<template>
<div
:class="{ collapsed: !isRepliesVisible }"
class="discussion"
>
<note :noteable="initialDiscussion" />
<div @click="toggleReplies" class="toggle-widget">
<span
class="chevron"
v-html="toggleRepliesIcon"></span> {{ toggleRepliesText }}
</div>
<template v-if="isRepliesVisible">
<note
v-for="note in replies"
:key="note.id"
:noteable="note"
/>
</template>
</div>
</template>
<style lang="scss">
.discussion {
border: 1px solid #919191;
border-radius: 4px;
background: var(--background-color);
&.collapsed {
.toggle-widget {
border-radius: 0 0 4px 4px;
}
}
> .note {
border: none;
margin: 0;
}
.toggle-widget {
background: var(--vscode-activityBar-dropBackground);
padding: 8px 16px;
cursor: pointer;
user-select: none;
}
.chevron svg {
width: 10px;
height: 10px;
}
}
</style>
......@@ -29,7 +29,6 @@ export default {
}
const description = this.issuable.description || '';
const path = `${this.issuable.web_url.split('/issues/')[0]}/uploads/`;
const normalized = description.replace(/\/uploads/gm, path);
......@@ -80,6 +79,7 @@ export default {
<style lang="scss">
.issuable-details {
border-bottom: 1px solid #919191;
line-height: 21px;
.header {
padding: 10px 0 6px;
......@@ -95,9 +95,17 @@ export default {
.state {
border-radius: 4px;
background-color: #2A9D3F;
padding: 2px 9px;
margin-right: 5px;
font-size: 12px;
&.opened {
background-color: #2A9D3F;
}
&.closed {
background-color: #1D64C9;
}
}
}
......
<script>
import Note from './Note';
import Discussion from './Discussion';
import SystemNote from './SystemNote';
export default {
......@@ -9,6 +10,11 @@ export default {
required: true,
},
},
components: {
Note,
Discussion,
SystemNote,
},
methods: {
getComponentName(discussion) {
if (discussion.individual_note) {
......@@ -18,6 +24,11 @@ export default {
return Note;
}
return Discussion;
},
getComponentData(discussion) {
return discussion.individual_note ? discussion.notes[0] : discussion;
},
},
};
......@@ -29,7 +40,7 @@ export default {
v-for="discussion in discussions"
:key="discussion.id"
:is="getComponentName(discussion)"
:noteable="discussion"
:noteable="getComponentData(discussion)"
/>
</div>
</template>
......
......@@ -17,14 +17,11 @@ export default {
NoteBody,
},
computed: {
note() {
return this.noteable.notes[0];
},
author() {
return this.note.author;
return this.noteable.author;
},
createdAgo() {
return moment(this.note.created_at).fromNow();
return moment(this.noteable.created_at).fromNow();
},
},
};
......@@ -35,7 +32,7 @@ export default {
<div class="note-header">
<user-avatar :user="author" :size="40" /> · {{ createdAgo }}
</div>
<note-body :note="note" />
<note-body :note="noteable" />
</div>
</template>
......
......@@ -34,6 +34,7 @@ export default {
<style lang="scss">
.note-body {
margin-left: 56px;
line-height: 21px;
.badge {
padding: 0 8px;
......
......@@ -16,14 +16,11 @@ export default {
UserAvatar,
},
computed: {
note() {
return this.noteable.notes[0];
},
author() {
return this.note.author;
return this.noteable.author;
},
createdAgo() {
return moment(this.note.created_at).fromNow();
return moment(this.noteable.created_at).fromNow();
},
},
};
......@@ -49,7 +46,7 @@ export default {
</span>
<div class="note-body-wrapper">
<user-avatar :user="author" :show-avatar="false"/>
<note-body :note="note"/>
<note-body :note="noteable"/>
· {{ createdAgo }}
</div>
</div>
......
import { expect } from 'chai'
import { shallowMount } from '@vue/test-utils'
import HelloWorld from '@/components/HelloWorld.vue'
describe('HelloWorld.vue', () => {
it('renders props.msg when passed', () => {
const msg = 'new message'
const wrapper = shallowMount(HelloWorld, {
propsData: { msg }
})
expect(wrapper.text()).to.include(msg)
})
})
......@@ -44,7 +44,8 @@ const getIndexPath = () => {
}
async function create(issuable) {
const panel = vscode.window.createWebviewPanel('glWorkflow', 'GL Workflow', vscode.ViewColumn.One, {
const title = `${issuable.title.slice(0, 20)}...`;
const panel = vscode.window.createWebviewPanel('glWorkflow', title, vscode.ViewColumn.One, {
enableScripts: true,
localResourceRoots: [
vscode.Uri.file(path.join(context.extensionPath, 'src'))
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册