Commit 41a3d9a2 authored by Phil Hughes's avatar Phil Hughes

Merge branch '2182-merge-vue-shared' into 'master'

Moves link to member component into vue shared folder

Closes #2182

See merge request !1660
parents c2ad90aa 5bc7c26d
import Vue from 'vue'; import Vue from 'vue';
import '../approvals_store';
require('../approvals_store'); import linkToMemberAvatar from '../../../vue_shared/components/link_to_member_avatar';
require('../../../vue_common_component/link_to_member_avatar');
Vue.component('approvals-footer', { Vue.component('approvals-footer', {
name: 'approvals-footer', name: 'approvals-footer',
...@@ -35,6 +34,9 @@ Vue.component('approvals-footer', { ...@@ -35,6 +34,9 @@ Vue.component('approvals-footer', {
required: true, required: true,
}, },
}, },
components: {
'link-to-member-avatar': linkToMemberAvatar,
},
data() { data() {
return { return {
unapproving: false, unapproving: false,
...@@ -57,32 +59,34 @@ Vue.component('approvals-footer', { ...@@ -57,32 +59,34 @@ Vue.component('approvals-footer', {
gl.ApprovalsStore.initStoreOnce(); gl.ApprovalsStore.initStoreOnce();
}, },
template: ` template: `
<div class='mr-widget-footer approved-by-users approvals-footer clearfix mr-approvals-footer'> <div class="mr-widget-footer approved-by-users approvals-footer clearfix mr-approvals-footer">
<span class='approvers-prefix'> Approved by </span> <span class="approvers-prefix"> Approved by </span>
<span v-for='approver in approvedBy'> <span v-for="approver in approvedBy">
<link-to-member-avatar <link-to-member-avatar
extra-link-class='approver-avatar' extra-link-class="approver-avatar"
:avatar-url='approver.user.avatar_url' :avatar-url="approver.user.avatar_url"
:display-name='approver.user.name' :display-name="approver.user.name"
:profile-url='approver.user.web_url' :profile-url="approver.user.web_url"
:avatar-html='checkmarkSvg' :avatar-html="checkmarkSvg"
:show-tooltip='true'> :show-tooltip="true" />
</link-to-member-avatar>
</span> </span>
<span v-for='n in approvalsLeft'> <span v-for="n in approvalsLeft">
<link-to-member-avatar <link-to-member-avatar
:clickable='false' :clickable="false"
:avatar-html='pendingAvatarSvg' :avatar-html="pendingAvatarSvg"
:show-tooltip='false' :show-tooltip="false"
extra-link-class='hide-asset'> extra-link-class="hide-asset" />
</link-to-member-avatar>
</span> </span>
<span class='unapprove-btn-wrap' v-if='showUnapproveButton'> <span
class="unapprove-btn-wrap"
v-if="showUnapproveButton">
<button <button
:disabled='unapproving' :disabled="unapproving"
@click='unapproveMergeRequest' @click="unapproveMergeRequest"
class='btn btn-link unapprove-btn'> class="btn btn-link unapprove-btn">
<i class='fa fa-close'></i> <i
class="fa fa-close"
aria-hidden="true"/>
Remove your approval Remove your approval
</button> </button>
</span> </span>
......
import Vue from 'vue';
// Analogue of link_to_member_avatar in app/helpers/projects_helper.rb
(() => {
Vue.component('link-to-member-avatar', {
props: {
avatarUrl: {
type: String,
required: false,
default: '/assets/no_avatar.png',
},
profileUrl: {
type: String,
required: false,
default: '',
},
displayName: {
type: String,
required: false,
},
extraAvatarClass: {
type: String,
default: '',
required: false,
},
extraLinkClass: {
type: String,
default: '',
required: false,
},
showTooltip: {
type: Boolean,
required: false,
default: true,
},
clickable: {
type: Boolean,
default: true,
required: false,
},
tooltipContainer: {
type: String,
required: false,
},
avatarHtml: {
type: String,
required: false,
},
avatarSize: {
type: Number,
required: false,
default: 32,
},
},
data() {
return {
avatarBaseClass: 'avatar avatar-inline',
};
},
computed: {
avatarSizeClass() {
return `s${this.avatarSize}`;
},
avatarHtmlClass() {
return `${this.avatarSizeClass} ${this.avatarBaseClass}`;
},
tooltipClass() {
return this.showTooltip ? 'has-tooltip' : '';
},
avatarClass() {
return `${this.avatarBaseClass} ${this.avatarSizeClass} ${this.extraAvatarClass}`;
},
disabledClass() {
return !this.clickable ? 'disabled' : '';
},
linkClass() {
return `author_link ${this.tooltipClass} ${this.extraLinkClass} ${this.disabledClass}`;
},
tooltipContainerAttr() {
return this.tooltipContainer || 'body';
},
},
template: `
<div class='link-to-member-avatar'>
<a :href='profileUrl' :class='linkClass' :data-original-title='displayName' :data-container='tooltipContainerAttr'>
<svg v-if='avatarHtml' v-html='avatarHtml' :class='avatarHtmlClass' :width='avatarSize' :height='avatarSize' :alt='displayName'></svg>
<img :class='avatarClass' :src='avatarUrl' :width='avatarSize' :height='avatarSize' :alt='displayName'/>
</a>
</div>
`,
});
})();
// Analogue of link_to_member_avatar in app/helpers/projects_helper.rb
export default {
props: {
avatarUrl: {
type: String,
required: false,
default: '/assets/no_avatar.png',
},
profileUrl: {
type: String,
required: false,
default: '',
},
displayName: {
type: String,
required: false,
},
extraAvatarClass: {
type: String,
default: '',
required: false,
},
extraLinkClass: {
type: String,
default: '',
required: false,
},
showTooltip: {
type: Boolean,
required: false,
default: true,
},
clickable: {
type: Boolean,
default: true,
required: false,
},
tooltipContainer: {
type: String,
required: false,
},
avatarHtml: {
type: String,
required: false,
},
avatarSize: {
type: Number,
required: false,
default: 32,
},
},
data() {
return {
avatarBaseClass: 'avatar avatar-inline',
};
},
computed: {
avatarSizeClass() {
return `s${this.avatarSize}`;
},
avatarHtmlClass() {
return `${this.avatarSizeClass} ${this.avatarBaseClass}`;
},
tooltipClass() {
return this.showTooltip ? 'has-tooltip' : '';
},
avatarClass() {
return `${this.avatarBaseClass} ${this.avatarSizeClass} ${this.extraAvatarClass}`;
},
disabledClass() {
return !this.clickable ? 'disabled' : '';
},
linkClass() {
return `author_link ${this.tooltipClass} ${this.extraLinkClass} ${this.disabledClass}`;
},
tooltipContainerAttr() {
return this.tooltipContainer || 'body';
},
},
template: `
<div class="link-to-member-avatar">
<a
:href="profileUrl"
:class="linkClass"
:title="displayName"
:data-container="tooltipContainerAttr">
<svg
v-if="avatarHtml"
v-html="avatarHtml"
:class="avatarHtmlClass"
:width="avatarSize"
:height="avatarSize"
:alt="displayName">
</svg>
<img
:class="avatarClass"
:src="avatarUrl"
:width="avatarSize"
:height="avatarSize"
:alt="displayName"/>
</a>
</div>
`,
};
/* eslint-disable guard-for-in, no-restricted-syntax */ /* eslint-disable no-restricted-syntax */
import Vue from 'vue'; import Vue from 'vue';
import linkToMemberAvatar from '~/vue_shared/components/link_to_member_avatar';
require('~/vue_common_component/link_to_member_avatar');
(() => { (() => {
function initComponent(propsData = {}) { function initComponent(propsData = {}) {
...@@ -12,7 +11,7 @@ require('~/vue_common_component/link_to_member_avatar'); ...@@ -12,7 +11,7 @@ require('~/vue_common_component/link_to_member_avatar');
</div> </div>
`); `);
const LinkToMembersComponent = Vue.component('link-to-member-avatar'); const LinkToMembersComponent = Vue.extend(linkToMemberAvatar);
this.component = new LinkToMembersComponent({ this.component = new LinkToMembersComponent({
el: '#mock-container', el: '#mock-container',
...@@ -63,9 +62,11 @@ require('~/vue_common_component/link_to_member_avatar'); ...@@ -63,9 +62,11 @@ require('~/vue_common_component/link_to_member_avatar');
Vue.nextTick(() => { Vue.nextTick(() => {
for (const computedKey in correctVals) { for (const computedKey in correctVals) {
const expectedVal = correctVals[computedKey]; if (Object.prototype.hasOwnProperty.call(correctVals, computedKey)) {
const actualComputed = this.component[computedKey]; const expectedVal = correctVals[computedKey];
expect(actualComputed).toBe(expectedVal); const actualComputed = this.component[computedKey];
expect(actualComputed).toBe(expectedVal);
}
} }
done(); done();
}); });
......
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