Commit bce029a2 authored by Simon Knox's avatar Simon Knox

clean up merge request widget UI

parent 4b3011e1
import tooltip from '../../vue_shared/directives/tooltip';
export default {
name: 'MRWidgetAuthor',
props: {
......@@ -5,11 +7,14 @@ export default {
showAuthorName: { type: Boolean, required: false, default: true },
showAuthorTooltip: { type: Boolean, required: false, default: false },
},
directives: {
tooltip,
},
template: `
<a
:href="author.webUrl || author.web_url"
class="author-link"
:class="{ 'has-tooltip': showAuthorTooltip }"
class="author-link inline"
:v-tooltip="showAuthorTooltip"
:title="author.name">
<img
:src="author.avatarUrl || author.avatar_url"
......
/* global Flash */
import '~/lib/utils/datetime_utility';
import { statusIconEntityMap } from '../../vue_shared/ci_status_icons';
import MemoryUsage from './mr_widget_memory_usage';
import StatusIcon from './mr_widget_status_icon';
import MRWidgetService from '../services/mr_widget_service';
export default {
......@@ -13,11 +13,7 @@ export default {
},
components: {
'mr-widget-memory-usage': MemoryUsage,
},
computed: {
svg() {
return statusIconEntityMap.icon_status_success;
},
'status-icon': StatusIcon,
},
methods: {
formatDate(date) {
......@@ -51,51 +47,51 @@ export default {
},
},
template: `
<div class="mr-widget-heading">
<div class="mr-widget-heading deploy-heading">
<div v-for="deployment in mr.deployments">
<div class="ci-widget">
<div class="ci-widget media">
<div class="ci-status-icon ci-status-icon-success">
<span class="js-icon-link icon-link">
<span class="ci-status-icon"
v-html="svg"
aria-hidden="true"></span>
<status-icon status="success" />
</span>
</div>
<span>
<span
v-if="hasDeploymentMeta(deployment)">
Deployed to
</span>
<a
v-if="hasDeploymentMeta(deployment)"
:href="deployment.url"
target="_blank"
rel="noopener noreferrer nofollow"
class="js-deploy-meta">
{{deployment.name}}
</a>
<span
v-if="hasExternalUrls(deployment)">
on
</span>
<a
v-if="hasExternalUrls(deployment)"
:href="deployment.external_url"
target="_blank"
rel="noopener noreferrer nofollow"
class="js-deploy-url">
<i
class="fa fa-external-link"
aria-hidden="true" />
{{deployment.external_url_formatted}}
</a>
<span
v-if="hasDeploymentTime(deployment)"
:data-title="deployment.deployed_at_formatted"
class="js-deploy-time"
data-toggle="tooltip"
data-placement="top">
{{formatDate(deployment.deployed_at)}}
<div class="media-body space-children">
<span>
<span
v-if="hasDeploymentMeta(deployment)">
Deployed to
</span>
<a
v-if="hasDeploymentMeta(deployment)"
:href="deployment.url"
target="_blank"
rel="noopener noreferrer nofollow"
class="js-deploy-meta inline">
{{deployment.name}}
</a>
<span
v-if="hasExternalUrls(deployment)">
on
</span>
<a
v-if="hasExternalUrls(deployment)"
:href="deployment.external_url"
target="_blank"
rel="noopener noreferrer nofollow"
class="js-deploy-url inline">
<i
class="fa fa-external-link"
aria-hidden="true" />
{{deployment.external_url_formatted}}
</a>
<span
v-if="hasDeploymentTime(deployment)"
:data-title="deployment.deployed_at_formatted"
class="js-deploy-time"
data-toggle="tooltip"
data-placement="top">
{{formatDate(deployment.deployed_at)}}
</span>
</span>
<button
type="button"
......@@ -104,13 +100,13 @@ export default {
class="btn btn-default btn-xs">
Stop environment
</button>
</span>
<mr-widget-memory-usage
v-if="deployment.metrics_url"
:metrics-url="deployment.metrics_url"
:metrics-monitoring-url="deployment.metrics_monitoring_url"
/>
</div>
</div>
<mr-widget-memory-usage
v-if="deployment.metrics_url"
:metrics-url="deployment.metrics_url"
:metrics-monitoring-url="deployment.metrics_monitoring_url"
/>
</div>
</div>
`,
......
import tooltip from '../../vue_shared/directives/tooltip';
import '../../lib/utils/text_utility';
export default {
......@@ -5,6 +6,9 @@ export default {
props: {
mr: { type: Object, required: true },
},
directives: {
tooltip,
},
computed: {
shouldShowCommitsBehindText() {
return this.mr.divergedCommitsCount > 0;
......@@ -29,18 +33,51 @@ export default {
},
template: `
<div class="mr-source-target">
<div
v-if="mr.isOpen"
class="pull-right">
<div class="normal">
<strong>
Request to merge
<span
class="label-branch"
:class="{'label-truncated': isBranchTitleLong(mr.sourceBranch)}"
:title="isBranchTitleLong(mr.sourceBranch) ? mr.sourceBranch : ''"
data-placement="bottom"
:v-tooltip="isBranchTitleLong(mr.sourceBranch)"
v-html="mr.sourceBranchLink"></span>
<button
v-tooltip
class="btn btn-transparent btn-clipboard"
data-title="Copy branch name to clipboard"
:data-clipboard-text="branchNameClipboardData">
<i
aria-hidden="true"
class="fa fa-clipboard"></i>
</button>
into
<span
class="label-branch"
:v-tooltip="isBranchTitleLong(mr.sourceBranch)"
:class="{'label-truncatedtooltip': isBranchTitleLong(mr.targetBranch)}"
:title="isBranchTitleLong(mr.targetBranch) ? mr.targetBranch : ''"
data-placement="bottom">
<a :href="mr.targetBranchTreePath">{{mr.targetBranch}}</a>
</span>
</strong>
<span
v-if="shouldShowCommitsBehindText"
class="diverged-commits-count">
(<a :href="mr.targetBranchPath">{{mr.divergedCommitsCount}} {{commitsText}} behind</a>)
</span>
</div>
<div v-if="mr.isOpen">
<a
href="#modal_merge_info"
data-toggle="modal"
class="btn inline btn-grouped btn-sm">
class="btn btn-small inline">
Check out branch
</a>
<span class="dropdown inline prepend-left-5">
<span class="dropdown inline prepend-left-10">
<a
class="btn btn-sm dropdown-toggle"
class="btn btn-xs dropdown-toggle"
data-toggle="dropdown"
aria-label="Download as"
role="button">
......@@ -69,38 +106,6 @@ export default {
</ul>
</span>
</div>
<div class="normal">
<strong>
Request to merge
<span
class="label-branch"
:class="{'label-truncated has-tooltip': isBranchTitleLong(mr.sourceBranch)}"
:title="isBranchTitleLong(mr.sourceBranch) ? mr.sourceBranch : ''"
data-placement="bottom"
v-html="mr.sourceBranchLink"></span>
<button
class="btn btn-transparent btn-clipboard has-tooltip"
data-title="Copy branch name to clipboard"
:data-clipboard-text="branchNameClipboardData">
<i
aria-hidden="true"
class="fa fa-clipboard"></i>
</button>
into
<span
class="label-branch"
:class="{'label-truncated has-tooltip': isBranchTitleLong(mr.targetBranch)}"
:title="isBranchTitleLong(mr.targetBranch) ? mr.targetBranch : ''"
data-placement="bottom">
<a :href="mr.targetBranchTreePath">{{mr.targetBranch}}</a>
</span>
</strong>
<span
v-if="shouldShowCommitsBehindText"
class="diverged-commits-count">
(<a :href="mr.targetBranchPath">{{mr.divergedCommitsCount}} {{commitsText}} behind</a>)
</span>
</div>
</div>
`,
};
......@@ -120,13 +120,12 @@ export default {
},
template: `
<div class="mr-info-list clearfix mr-memory-usage js-mr-memory-usage">
<div class="legend"></div>
<p
v-if="shouldShowLoading"
class="usage-info js-usage-info usage-info-loading">
<i
class="fa fa-spinner fa-spin usage-info-load-spinner"
aria-hidden="true" />Loading deployment statistics.
aria-hidden="true" />Loading deployment statistics
</p>
<p
v-if="shouldShowMemoryGraph"
......@@ -136,12 +135,12 @@ export default {
<p
v-if="shouldShowLoadFailure"
class="usage-info js-usage-info usage-info-failed">
Failed to load deployment statistics.
Failed to load deployment statistics
</p>
<p
v-if="shouldShowMetricsUnavailable"
class="usage-info js-usage-info usage-info-unavailable">
Deployment statistics are not available currently.
Deployment statistics are not available currently
</p>
<mr-memory-graph
v-if="shouldShowMemoryGraph"
......
......@@ -16,7 +16,7 @@ export default {
<a
data-toggle="modal"
href="#modal_merge_info">
command line.
command line
</a>
</section>
`,
......
......@@ -29,58 +29,55 @@ export default {
},
template: `
<div class="mr-widget-heading">
<div class="ci-widget">
<div class="ci-widget media">
<template v-if="hasCIError">
<div class="ci-status-icon ci-status-icon-failed ci-error js-ci-error">
<span class="js-icon-link icon-link">
<span
v-html="svg"
aria-hidden="true"></span>
</span>
<div class="ci-status-icon ci-status-icon-failed ci-error js-ci-error append-right-10">
<span
v-html="svg"
aria-hidden="true"></span>
</div>
<div class="media-body">
Could not connect to the CI server. Please check your settings and try again
</div>
<span>Could not connect to the CI server. Please check your settings and try again.</span>
</template>
<template v-else>
<div>
<div class="ci-status-icon append-right-10">
<a
class="icon-link"
:href="this.status.details_path">
<ci-icon :status="status" />
</a>
</div>
<span>
Pipeline
<a
:href="mr.pipeline.path"
class="pipeline-id">#{{mr.pipeline.id}}</a>
{{mr.pipeline.details.status.label}}
</span>
<span
v-if="mr.pipeline.details.stages.length > 0">
with {{stageText}}
</span>
<div class="mr-widget-pipeline-graph">
<div class="stage-cell">
<div
v-if="mr.pipeline.details.stages.length > 0"
v-for="stage in mr.pipeline.details.stages"
class="stage-container dropdown js-mini-pipeline-graph">
<pipeline-stage :stage="stage" />
</div>
</div>
<div class="media-body">
<span>
Pipeline
<a
:href="mr.pipeline.path"
class="pipeline-id">#{{mr.pipeline.id}}</a>
</span>
<span class="mr-widget-pipeline-graph">
<span class="stage-cell">
<div
v-if="mr.pipeline.details.stages.length > 0"
v-for="stage in mr.pipeline.details.stages"
class="stage-container dropdown js-mini-pipeline-graph">
<pipeline-stage :stage="stage" />
</div>
</span>
</span>
<span>
{{mr.pipeline.details.status.label}} for
<a
:href="mr.pipeline.commit.commit_path"
class="commit-sha js-commit-link">
{{mr.pipeline.commit.short_id}}</a>.
</span>
<span
v-if="mr.pipeline.coverage"
class="js-mr-coverage">
Coverage {{mr.pipeline.coverage}}%
</span>
</div>
<span>
for
<a
:href="mr.pipeline.commit.commit_path"
class="commit-sha js-commit-link">
{{mr.pipeline.commit.short_id}}</a>.
</span>
<span
v-if="mr.pipeline.coverage"
class="js-mr-coverage">
Coverage {{mr.pipeline.coverage}}%.
</span>
</template>
</div>
</div>
......
......@@ -2,37 +2,32 @@ export default {
name: 'MRWidgetRelatedLinks',
props: {
relatedLinks: { type: Object, required: true },
state: { type: String, required: false },
},
computed: {
hasLinks() {
const { closing, mentioned, assignToMe } = this.relatedLinks;
return closing || mentioned || assignToMe;
},
},
methods: {
hasMultipleIssues(text) {
return !text ? false : text.match(/<\/a> and <a/);
},
issueLabel(field) {
return this.hasMultipleIssues(this.relatedLinks[field]) ? 'issues' : 'issue';
},
verbLabel(field) {
return this.hasMultipleIssues(this.relatedLinks[field]) ? 'are' : 'is';
closesText() {
if (this.state === 'merged') {
return 'Closed';
}
if (this.state === 'closed') {
return 'Did not close';
}
return 'Closes';
},
},
template: `
<section
v-if="hasLinks"
class="mr-info-list mr-links">
<div class="legend"></div>
<p v-if="relatedLinks.closing">
Closes {{issueLabel('closing')}}
<span v-html="relatedLinks.closing"></span>.
{{closesText}} <span v-html="relatedLinks.closing"></span>
</p>
<p v-if="relatedLinks.mentioned">
<span class="capitalize">{{issueLabel('mentioned')}}</span>
<span v-html="relatedLinks.mentioned"></span>
{{verbLabel('mentioned')}} mentioned but will not be closed.
Mentions <span v-html="relatedLinks.mentioned"></span>
</p>
<p v-if="relatedLinks.assignToMe">
<span v-html="relatedLinks.assignToMe"></span>
......
import ciIcon from '../../vue_shared/components/ci_icon.vue';
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
export default {
props: {
status: { type: String, required: true },
showDisabledButton: { type: Boolean, required: false },
},
components: {
ciIcon,
loadingIcon,
},
computed: {
statusObj() {
return {
group: this.status,
icon: `icon_status_${this.status}`,
};
},
},
template: `
<div class="space-children flex-container-block append-right-10">
<div v-if="status === 'loading'" class="mr-widget-icon">
<loading-icon />
</div>
<ci-icon v-else :status="statusObj" />
<button
v-if="showDisabledButton"
type="button"
class="btn btn-success btn-small"
disabled="true">
Merge
</button>
</div>
`,
};
import statusIcon from '../mr_widget_status_icon';
export default {
name: 'MRWidgetArchived',
components: {
statusIcon,
},
template: `
<div class="mr-widget-body">
<button
type="button"
class="btn btn-success btn-small"
disabled="true">
Merge
</button>
<span class="bold">
This project is archived, write access has been disabled.
</span>
<div class="mr-widget-body media">
<div class="space-children">
<status-icon status="failed" />
<button
type="button"
class="btn btn-success btn-small"
disabled="true">
Merge
</button>
</div>
<div class="media-body">
<span class="bold">
This project is archived, write access has been disabled
</span>
</div>
</div>
`,
};
import eventHub from '../../event_hub';
import statusIcon from '../mr_widget_status_icon';
export default {
name: 'MRWidgetAutoMergeFailed',
......@@ -10,6 +11,9 @@ export default {
isRefreshing: false,
};
},
components: {
statusIcon,
},
methods: {
refreshWidget() {
this.isRefreshing = true;
......@@ -19,18 +23,16 @@ export default {
},
},
template: `
<div class="mr-widget-body">
<button
class="btn btn-success btn-small"
disabled="true"
type="button">
Merge
</button>
<span class="bold danger">
This merge request failed to be merged automatically.
<div class="mr-widget-body media">
<status-icon status="failed" />
<div class="media-body space-children">
<span class="bold">
<template v-if="mr.mergeError">{{mr.mergeError}}.</template>
This merge request failed to be merged automatically
</span>
<button
@click="refreshWidget"
:class="{ disabled: isRefreshing }"
:disabled="isRefreshing"
type="button"
class="btn btn-xs btn-default">
<i
......@@ -39,9 +41,6 @@ export default {
aria-hidden="true" />
Refresh
</button>
</span>
<div class="merge-error-text danger bold">
{{mr.mergeError}}
</div>
</div>
`,
......
import statusIcon from '../mr_widget_status_icon';
export default {
name: 'MRWidgetChecking',
components: {
statusIcon,
},
template: `
<div class="mr-widget-body">
<button
type="button"
class="btn btn-success btn-small"
disabled="true">
Merge
</button>
<span class="bold">
Checking ability to merge automatically.
<i
class="fa fa-spinner fa-spin"
aria-hidden="true" />
</span>
<div class="mr-widget-body media">
<status-icon status="loading" showDisabledButton />
<div class="media-body space-children">
<span class="bold">
Checking ability to merge automatically
</span>
</div>
</div>
`,
};
import mrWidgetAuthorTime from '../../components/mr_widget_author_time';
import statusIcon from '../mr_widget_status_icon';
export default {
name: 'MRWidgetClosed',
......@@ -7,24 +8,28 @@ export default {
},
components: {
'mr-widget-author-and-time': mrWidgetAuthorTime,
statusIcon,
},
template: `
<div class="mr-widget-body">
<mr-widget-author-and-time
actionText="Closed by"
:author="mr.closedBy"
:dateTitle="mr.updatedAt"
:dateReadable="mr.closedAt"
/>
<section>
<p>
The changes were not merged into
<a
:href="mr.targetBranchPath"
class="label-branch">
{{mr.targetBranch}}</a>.
</p>
</section>
<div class="mr-widget-body media">
<status-icon status="failed" />
<div class="media-body">
<mr-widget-author-and-time
actionText="Closed by"
:author="mr.closedBy"
:dateTitle="mr.updatedAt"
:dateReadable="mr.closedAt"
/>
<section class="mr-info-list">
<p>
The changes were not merged into
<a
:href="mr.targetBranchPath"
class="label-branch">
{{mr.targetBranch}}</a>
</p>
</section>
</div>
</div>
`,
};
import statusIcon from '../mr_widget_status_icon';
export default {
name: 'MRWidgetConflicts',
props: {
mr: { type: Object, required: true },
},
components: {
statusIcon,
},
template: `
<div class="mr-widget-body">
<button
type="button"
class="btn btn-success btn-small"
disabled="true">