Commit 34d2f392 authored by Andrew Fontaine's avatar Andrew Fontaine

Merge branch 'selhorn-notes-button' into 'master'

WIP Button redo for OKR

See merge request gitlab-org/gitlab!42626
parents 0ce91537 bf39ae0a
<script>
import { mapGetters } from 'vuex';
import { GlLoadingIcon, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import { GlTooltipDirective, GlIcon, GlButton, GlDropdownItem } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
import resolvedStatusMixin from '~/batch_comments/mixins/resolved_status';
import ReplyButton from './note_actions/reply_button.vue';
......@@ -14,7 +14,8 @@ export default {
components: {
GlIcon,
ReplyButton,
GlLoadingIcon,
GlButton,
GlDropdownItem,
},
directives: {
GlTooltip: GlTooltipDirective,
......@@ -170,6 +171,15 @@ export default {
name: this.projectName,
});
},
resolveIcon() {
if (!this.isResolving) {
return this.isResolved ? 'check-circle-filled' : 'check-circle';
}
return null;
},
resolveVariant() {
return this.isResolved ? 'success' : 'default';
},
},
methods: {
onEdit() {
......@@ -233,24 +243,23 @@ export default {
:title="displayContributorBadgeText"
>{{ __('Contributor') }}</span
>
<div v-if="canResolve" class="note-actions-item">
<button
<div v-if="canResolve" class="gl-ml-2">
<gl-button
ref="resolveButton"
v-gl-tooltip
size="small"
category="tertiary"
:variant="resolveVariant"
:class="{ 'is-disabled': !resolvable, 'is-active': isResolved }"
:title="resolveButtonTitle"
:aria-label="resolveButtonTitle"
type="button"
:icon="resolveIcon"
:loading="isResolving"
class="line-resolve-btn note-action-button"
@click="onResolve"
>
<template v-if="!isResolving">
<gl-icon :name="isResolved ? 'check-circle-filled' : 'check-circle'" />
</template>
<gl-loading-icon v-else inline />
</button>
/>
</div>
<div v-if="canAwardEmoji" class="note-actions-item">
<div v-if="canAwardEmoji" class="gl-ml-3 gl-mr-2">
<a
v-gl-tooltip
:class="{ 'js-user-authored': isAuthoredByCurrentUser }"
......@@ -261,7 +270,7 @@ export default {
>
<gl-icon class="link-highlight award-control-icon-neutral" name="slight-smile" />
<gl-icon class="link-highlight award-control-icon-positive" name="smiley" />
<gl-icon class="link-highlight award-control-icon-super-positive" name="smiley" />
<gl-icon class="link-highlight award-control-icon-super-positive" name="smile" />
</a>
</div>
<reply-button
......@@ -270,72 +279,57 @@ export default {
class="js-reply-button"
@startReplying="$emit('startReplying')"
/>
<div v-if="canEdit" class="note-actions-item">
<button
<div v-if="canEdit" class="gl-ml-2">
<gl-button
v-gl-tooltip
type="button"
title="Edit comment"
icon="pencil"
size="small"
category="tertiary"
class="note-action-button js-note-edit btn btn-transparent"
data-qa-selector="note_edit_button"
@click="onEdit"
>
<gl-icon name="pencil" class="link-highlight" />
</button>
/>
</div>
<div v-if="showDeleteAction" class="note-actions-item">
<button
<div v-if="showDeleteAction" class="gl-ml-2">
<gl-button
v-gl-tooltip
type="button"
title="Delete comment"
size="small"
icon="remove"
category="tertiary"
class="note-action-button js-note-delete btn btn-transparent"
@click="onDelete"
>
<gl-icon name="remove" class="link-highlight" />
</button>
/>
</div>
<div v-else-if="shouldShowActionsDropdown" class="dropdown more-actions note-actions-item">
<button
<div v-else-if="shouldShowActionsDropdown" class="dropdown more-actions gl-ml-2">
<gl-button
v-gl-tooltip
type="button"
title="More actions"
icon="ellipsis_v"
size="small"
category="tertiary"
class="note-action-button more-actions-toggle btn btn-transparent"
data-toggle="dropdown"
@click="closeTooltip"
>
<gl-icon class="icon" name="ellipsis_v" />
</button>
/>
<ul class="dropdown-menu more-actions-dropdown dropdown-open-left">
<li v-if="canReportAsAbuse">
<a :href="reportAbusePath">{{ __('Report abuse to admin') }}</a>
</li>
<li v-if="noteUrl">
<button
:data-clipboard-text="noteUrl"
type="button"
class="btn-default btn-transparent js-btn-copy-note-link"
>
{{ __('Copy link') }}
</button>
</li>
<li v-if="canAssign">
<button
class="btn-default btn-transparent"
data-testid="assign-user"
type="button"
@click="assignUser"
>
{{ displayAssignUserText }}
</button>
</li>
<li v-if="canEdit">
<button
class="btn btn-transparent js-note-delete js-note-delete"
type="button"
@click.prevent="onDelete"
>
<span class="text-danger">{{ __('Delete comment') }}</span>
</button>
</li>
<gl-dropdown-item v-if="canReportAsAbuse" :href="reportAbusePath">
{{ __('Report abuse to admin') }}
</gl-dropdown-item>
<gl-dropdown-item
v-if="noteUrl"
class="js-btn-copy-note-link"
:data-clipboard-text="noteUrl"
>
{{ __('Copy link') }}
</gl-dropdown-item>
<gl-dropdown-item v-if="canAssign" data-testid="assign-user" @click="assignUser">
{{ displayAssignUserText }}
</gl-dropdown-item>
<gl-dropdown-item v-if="canEdit" class="js-note-delete" @click.prevent="onDelete">
<span class="text-danger">{{ __('Delete comment') }}</span>
</gl-dropdown-item>
</ul>
</div>
</div>
......
......@@ -13,7 +13,7 @@ export default {
</script>
<template>
<div class="note-actions-item">
<div class="gl-ml-2">
<gl-button
ref="button"
v-gl-tooltip
......
......@@ -337,11 +337,11 @@ table.pipeline-project-metrics tr td {
}
.user-access-role {
@include gl-px-3;
display: inline-block;
color: $gl-text-color-secondary;
font-size: 12px;
line-height: 20px;
padding: 0 $label-padding;
border: 1px solid $border-color;
border-radius: $label-border-radius;
font-weight: $gl-font-weight-normal;
......
......@@ -801,7 +801,7 @@ $note-form-margin-left: 72px;
}
.note-role {
margin: 0 3px;
margin: 0 8px;
}
/**
......@@ -892,6 +892,15 @@ $note-form-margin-left: 72px;
outline: 0;
transition: color $general-hover-transition-duration $general-hover-transition-curve;
&[disabled] {
padding: 0 8px !important;
box-shadow: none !important;
.gl-button-loading-indicator {
margin-right: 0 !important;
}
}
&.is-disabled {
cursor: default;
}
......@@ -899,16 +908,22 @@ $note-form-margin-left: 72px;
&:not(.is-disabled) {
&:hover,
&:focus {
color: $green-600;
svg {
color: $green-600;
}
}
}
&.is-active {
color: $green-600;
svg {
@include gl-text-green-500;
}
&:hover,
&:focus {
color: $green-700;
svg {
color: $green-700;
}
}
}
......
import Vue from 'vue';
import { shallowMount, createLocalVue, createWrapper } from '@vue/test-utils';
import { mount, createLocalVue, createWrapper } from '@vue/test-utils';
import { TEST_HOST } from 'spec/test_constants';
import AxiosMockAdapter from 'axios-mock-adapter';
import createStore from '~/notes/stores';
......@@ -14,9 +14,9 @@ describe('noteActions', () => {
let actions;
let axiosMock;
const shallowMountNoteActions = (propsData, computed) => {
const mountNoteActions = (propsData, computed) => {
const localVue = createLocalVue();
return shallowMount(localVue.extend(noteActions), {
return mount(localVue.extend(noteActions), {
store,
propsData,
localVue,
......@@ -61,7 +61,7 @@ describe('noteActions', () => {
beforeEach(() => {
store.dispatch('setUserData', userDataMock);
wrapper = shallowMountNoteActions(props);
wrapper = mountNoteActions(props);
});
it('should render noteable author badge', () => {
......@@ -178,7 +178,7 @@ describe('noteActions', () => {
};
beforeEach(() => {
wrapper = shallowMountNoteActions(props, {
wrapper = mountNoteActions(props, {
targetType: () => 'issue',
});
store.state.noteableData = {
......@@ -205,7 +205,7 @@ describe('noteActions', () => {
};
beforeEach(() => {
wrapper = shallowMountNoteActions(props, {
wrapper = mountNoteActions(props, {
targetType: () => 'issue',
});
});
......@@ -221,7 +221,7 @@ describe('noteActions', () => {
describe('user is not logged in', () => {
beforeEach(() => {
store.dispatch('setUserData', {});
wrapper = shallowMountNoteActions({
wrapper = mountNoteActions({
...props,
canDelete: false,
canEdit: false,
......@@ -241,7 +241,7 @@ describe('noteActions', () => {
describe('for showReply = true', () => {
beforeEach(() => {
wrapper = shallowMountNoteActions({
wrapper = mountNoteActions({
...props,
showReply: true,
});
......@@ -256,7 +256,7 @@ describe('noteActions', () => {
describe('for showReply = false', () => {
beforeEach(() => {
wrapper = shallowMountNoteActions({
wrapper = mountNoteActions({
...props,
showReply: false,
});
......@@ -273,7 +273,7 @@ describe('noteActions', () => {
beforeEach(() => {
store.dispatch('setUserData', userDataMock);
wrapper = shallowMountNoteActions({ ...props, canResolve: true, isDraft: true });
wrapper = mountNoteActions({ ...props, canResolve: true, isDraft: true });
});
it('should render the right resolve button title', () => {
......
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