Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorDouwe Maan <douwe@gitlab.com>2017-08-07 12:13:10 +0300
committerDouwe Maan <douwe@gitlab.com>2017-08-07 12:13:10 +0300
commit727b6d16e5e11933c0879cfa9ed5eb3bb9280cf1 (patch)
tree16649f5e4d23fb0a0d5f0b28cb25890d7999f493 /app
parent4b34720c0ca8b5459cc56a4e52e11e213ab6ae9a (diff)
parent440dc934dec31b4ef3ee78e5ae366f832719b173 (diff)
Merge branch 'master' into 'bvl-nfs-circuitbreaker'
# Conflicts: # app/models/repository.rb # spec/models/repository_spec.rb
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/boards/components/modal/index.js4
-rw-r--r--app/assets/javascripts/dispatcher.js2
-rw-r--r--app/assets/javascripts/pdf/index.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/graph/graph_component.vue4
-rw-r--r--app/assets/javascripts/users/activity_calendar.js12
-rw-r--r--app/assets/javascripts/users/user_tabs.js8
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.js9
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_deployment.js100
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.js81
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_memory_usage.js7
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_merge_help.js2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.js79
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.js27
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.js36
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.js30
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.js25
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.js25
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.js37
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.js30
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.js64
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_locked.js35
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.js95
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.js154
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.js39
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_not_allowed.js24
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_nothing_to_merge.js16
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.js22
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_failed.js22
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_ready_to_merge.js178
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_sha_mismatch.js22
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_unresolved_discussions.js36
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_wip.js36
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/dependencies.js2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js31
-rw-r--r--app/assets/stylesheets/framework.scss1
-rw-r--r--app/assets/stylesheets/framework/calendar.scss1
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss4
-rw-r--r--app/assets/stylesheets/framework/header.scss4
-rw-r--r--app/assets/stylesheets/framework/media_object.scss8
-rw-r--r--app/assets/stylesheets/framework/variables.scss7
-rw-r--r--app/assets/stylesheets/new_nav.scss4
-rw-r--r--app/assets/stylesheets/pages/issuable.scss8
-rw-r--r--app/assets/stylesheets/pages/merge_requests.scss317
-rw-r--r--app/assets/stylesheets/pages/pipelines.scss6
-rw-r--r--app/assets/stylesheets/pages/projects.scss1
-rw-r--r--app/assets/stylesheets/pages/settings.scss20
-rw-r--r--app/models/project.rb2
-rw-r--r--app/models/repository.rb34
-rw-r--r--app/services/merge_requests/create_service.rb7
-rw-r--r--app/views/ci/lints/show.html.haml2
-rw-r--r--app/views/layouts/_head.html.haml3
-rw-r--r--app/views/layouts/header/_default.html.haml2
-rw-r--r--app/views/layouts/header/_new.html.haml2
-rw-r--r--app/views/layouts/nav/_group.html.haml2
-rw-r--r--app/views/layouts/nav/_new_admin_sidebar.html.haml2
-rw-r--r--app/views/layouts/nav/_new_group_sidebar.html.haml4
-rw-r--r--app/views/layouts/nav/_new_project_sidebar.html.haml10
-rw-r--r--app/views/projects/_merge_request_settings.html.haml7
-rw-r--r--app/views/projects/edit.html.haml431
-rw-r--r--app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml2
-rw-r--r--app/views/projects/runners/edit.html.haml2
-rw-r--r--app/views/shared/icons/_container_registry.svg1
-rw-r--r--app/views/shared/icons/_spam_logs.svg1
-rw-r--r--app/views/shared/milestones/_sidebar.html.haml2
-rw-r--r--app/views/users/calendar_activities.html.haml6
-rw-r--r--app/views/users/show.html.haml2
66 files changed, 1162 insertions, 1041 deletions
diff --git a/app/assets/javascripts/boards/components/modal/index.js b/app/assets/javascripts/boards/components/modal/index.js
index 1d36519c75c..96af69e7a36 100644
--- a/app/assets/javascripts/boards/components/modal/index.js
+++ b/app/assets/javascripts/boards/components/modal/index.js
@@ -1,8 +1,8 @@
/* global ListIssue */
import Vue from 'vue';
-import queryData from '../../utils/query_data';
-import loadingIcon from '../../../vue_shared/components/loading_icon.vue';
+import queryData from '~/boards/utils/query_data';
+import loadingIcon from '~/vue_shared/components/loading_icon.vue';
import './header';
import './list';
import './footer';
diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js
index ad5ff19ec58..5630940f5bb 100644
--- a/app/assets/javascripts/dispatcher.js
+++ b/app/assets/javascripts/dispatcher.js
@@ -348,6 +348,8 @@ import GpgBadges from './gpg_badges';
break;
case 'projects:edit':
setupProjectEdit();
+ // Initialize expandable settings panels
+ initSettingsPanels();
break;
case 'projects:imports:show':
new ProjectImport();
diff --git a/app/assets/javascripts/pdf/index.vue b/app/assets/javascripts/pdf/index.vue
index 4603859d7b0..b874e484d45 100644
--- a/app/assets/javascripts/pdf/index.vue
+++ b/app/assets/javascripts/pdf/index.vue
@@ -9,8 +9,8 @@
</template>
<script>
- import pdfjsLib from 'pdfjs-dist';
- import workerSrc from 'vendor/pdf.worker';
+ import pdfjsLib from 'vendor/pdf';
+ import workerSrc from 'vendor/pdf.worker.min';
import page from './page/index.vue';
diff --git a/app/assets/javascripts/pipelines/components/graph/graph_component.vue b/app/assets/javascripts/pipelines/components/graph/graph_component.vue
index 77cbaeb43ef..66bc1d1979c 100644
--- a/app/assets/javascripts/pipelines/components/graph/graph_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/graph_component.vue
@@ -1,7 +1,7 @@
<script>
+ import loadingIcon from '~/vue_shared/components/loading_icon.vue';
+ import '~/flash';
import stageColumnComponent from './stage_column_component.vue';
- import loadingIcon from '../../../vue_shared/components/loading_icon.vue';
- import '../../../flash';
export default {
props: {
diff --git a/app/assets/javascripts/users/activity_calendar.js b/app/assets/javascripts/users/activity_calendar.js
index 3dac31c2121..5e947769f8a 100644
--- a/app/assets/javascripts/users/activity_calendar.js
+++ b/app/assets/javascripts/users/activity_calendar.js
@@ -7,6 +7,14 @@ const LOADING_HTML = `
</div>
`;
+function getSystemDate(systemUtcOffsetSeconds) {
+ const date = new Date();
+ const localUtcOffsetMinutes = 0 - date.getTimezoneOffset();
+ const systemUtcOffsetMinutes = systemUtcOffsetSeconds / 60;
+ date.setMinutes((date.getMinutes() - localUtcOffsetMinutes) + systemUtcOffsetMinutes);
+ return date;
+}
+
function formatTooltipText({ date, count }) {
const dateObject = new Date(date);
const dateDayName = gl.utils.getDayName(dateObject);
@@ -22,7 +30,7 @@ function formatTooltipText({ date, count }) {
const initColorKey = () => d3.scale.linear().range(['#acd5f2', '#254e77']).domain([0, 3]);
export default class ActivityCalendar {
- constructor(container, timestamps, calendarActivitiesPath) {
+ constructor(container, timestamps, calendarActivitiesPath, utcOffset = 0) {
this.calendarActivitiesPath = calendarActivitiesPath;
this.clickDay = this.clickDay.bind(this);
this.currentSelectedDate = '';
@@ -37,7 +45,7 @@ export default class ActivityCalendar {
this.timestampsTmp = [];
let group = 0;
- const today = new Date();
+ const today = getSystemDate(utcOffset);
today.setHours(0, 0, 0, 0, 0);
const oneYearAgo = new Date(today);
diff --git a/app/assets/javascripts/users/user_tabs.js b/app/assets/javascripts/users/user_tabs.js
index 5fe6603ce7b..1215b265e28 100644
--- a/app/assets/javascripts/users/user_tabs.js
+++ b/app/assets/javascripts/users/user_tabs.js
@@ -150,15 +150,21 @@ export default class UserTabs {
const $calendarWrap = this.$parentEl.find('.user-calendar');
const calendarPath = $calendarWrap.data('calendarPath');
const calendarActivitiesPath = $calendarWrap.data('calendarActivitiesPath');
+ const utcOffset = $calendarWrap.data('utcOffset');
+ let utcFormatted = 'UTC';
+ if (utcOffset !== 0) {
+ utcFormatted = `UTC${utcOffset > 0 ? '+' : ''}${(utcOffset / 3600)}`;
+ }
$.ajax({
dataType: 'json',
url: calendarPath,
success: (activityData) => {
$calendarWrap.html(CALENDAR_TEMPLATE);
+ $calendarWrap.find('.calendar-hint').append(`(Timezone: ${utcFormatted})`);
// eslint-disable-next-line no-new
- new ActivityCalendar('.js-contrib-calendar', activityData, calendarActivitiesPath);
+ new ActivityCalendar('.js-contrib-calendar', activityData, calendarActivitiesPath, utcOffset);
},
});
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.js b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.js
index a01cb8cc202..982b5e8e373 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.js
@@ -1,3 +1,5 @@
+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"
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_deployment.js b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_deployment.js
index 744a1cd24fa..e98d147733c 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_deployment.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_deployment.js
@@ -1,8 +1,8 @@
/* 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>
`,
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.js b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.js
index 8430548903c..c05a76a3b4a 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.js
@@ -1,3 +1,4 @@
+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>
`,
};
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_memory_usage.js b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_memory_usage.js
index 534e2a88eff..a4e34116c33 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_memory_usage.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_memory_usage.js
@@ -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"
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_merge_help.js b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_merge_help.js
index 2fecebce7a0..1d9f9863dd9 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_merge_help.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_merge_help.js
@@ -16,7 +16,7 @@ export default {
<a
data-toggle="modal"
href="#modal_merge_info">
- command line.
+ command line
</a>
</section>
`,
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.js b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.js
index c02e10128e2..6c2e9ba1d30 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.js
@@ -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>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.js b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.js
index 205804670fa..563267ad044 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.js
@@ -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>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.js b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.js
new file mode 100644
index 00000000000..b01c923311b
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.js
@@ -0,0 +1,36 @@
+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>
+ `,
+};
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.js
index c7f25a1697c..2b16a2d6817 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.js
@@ -1,16 +1,26 @@
+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>
`,
};
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.js
index 4063859d5d0..5648208f7b1 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.js
@@ -1,4 +1,5 @@
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>
`,
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.js
index 8515b54e62d..aaf9d3304a4 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.js
@@ -1,19 +1,18 @@
+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>
`,
};
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.js
index fc2e42c6821..4078aad7f83 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.js
@@ -1,4 +1,5 @@
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>
`,
};
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.js
index 36596c6f37e..f9cb79a0bc1 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.js
@@ -1,27 +1,25 @@
+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">
- Merge
- </button>
- <span class="bold">
- There are merge conflicts.
- <span v-if="!mr.canMerge">
- Resolve these conflicts or ask someone with write access to this repository to merge it locally.
+ <div class="mr-widget-body media">
+ <status-icon status="failed" showDisabledButton />
+ <div class="media-body space-children">
+ <span class="bold">
+ There are merge conflicts<span v-if="!mr.canMerge">.</span>
+ <span v-if="!mr.canMerge">
+ Resolve these conflicts or ask someone with write access to this repository to merge it locally
+ </span>
</span>
- </span>
- <div
- v-if="mr.canMerge"
- class="btn-group">
<a
- v-if="mr.conflictResolutionPath"
+ v-if="mr.canMerge && mr.conflictResolutionPath"
:href="mr.conflictResolutionPath"
class="btn btn-default btn-xs js-resolve-conflicts-button">
Resolve conflicts
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.js
index 600b4d42e3d..1cb24549d53 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.js
@@ -1,3 +1,4 @@
+import statusIcon from '../mr_widget_status_icon';
import eventHub from '../../event_hub';
export default {
@@ -38,39 +39,40 @@ export default {
}
},
},
+ components: {
+ statusIcon,
+ },
template: `
- <div class="mr-widget-body">
- <button
- class="btn btn-success btn-small"
- disabled="true"
- type="button">
- Merge
- </button>
- <span
- v-if="!isRefreshing"
- class="bold danger">
- <span
- class="has-error-message"
- v-if="mr.mergeError">
- {{mr.mergeError}}
- </span>
- <span v-else>Merge failed.</span>
- <span
- :class="{ 'has-custom-error': mr.mergeError }">
- Refreshing in {{timerText}} to show the updated status...
+ <div class="mr-widget-body media">
+ <template v-if="isRefreshing">
+ <status-icon status="loading" />
+ <span class="media-body bold js-refresh-label">
+ Refreshing now
</span>
- <button
- @click="refresh"
- class="btn btn-default btn-xs js-refresh-button"
- type="button">
- Refresh now
- </button>
- </span>
- <span
- v-if="isRefreshing"
- class="bold js-refresh-label">
- Refreshing now...
- </span>
+ </template>
+ <template v-else>
+ <status-icon status="failed" showDisabledButton />
+ <div class="media-body space-children">
+ <span class="bold">
+ <span
+ class="has-error-message"
+ v-if="mr.mergeError">
+ {{mr.mergeError}}.
+ </span>
+ <span v-else>Merge failed.</span>
+ <span
+ :class="{ 'has-custom-error': mr.mergeError }">
+ Refreshing in {{timerText}} to show the updated status...
+ </span>
+ </span>
+ <button
+ @click="refresh"
+ class="btn btn-default btn-xs js-refresh-button"
+ type="button">
+ Refresh now
+ </button>
+ </div>
+ </template>
</div>
`,
};
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_locked.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_locked.js
index 0bd31731a0b..a12f418e1af 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_locked.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_locked.js
@@ -1,24 +1,29 @@
+import statusIcon from '../mr_widget_status_icon';
+
export default {
name: 'MRWidgetLocked',
props: {
mr: { type: Object, required: true },
},
+ components: {
+ statusIcon,
+ },
template: `
- <div class="mr-widget-body mr-state-locked">
- <span class="state-label">Locked</span>
- This merge request is in the process of being merged, during which time it is locked and cannot be closed.
- <i
- class="fa fa-spinner fa-spin"
- aria-hidden="true" />
- <section class="mr-info-list mr-links">
- <div class="legend"></div>
- <p>
- The changes will be merged into
- <span class="label-branch">
- <a :href="mr.targetBranchPath">{{mr.targetBranch}}</a>
- </span>.
- </p>
- </section>
+ <div class="mr-widget-body mr-state-locked media">
+ <status-icon status="loading" />
+ <div class="media-body">
+ <h4>
+ This merge request is in the process of being merged, during which time it is locked and cannot be closed
+ </h4>
+ <section class="mr-info-list">
+ <p>
+ The changes will be merged into
+ <span class="label-branch">
+ <a :href="mr.targetBranchPath">{{mr.targetBranch}}</a>
+ </span>
+ </p>
+ </section>
+ </div>
</div>
`,
};
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.js
index 419d174f3ff..bdfd4d9667c 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.js
@@ -1,5 +1,5 @@
/* global Flash */
-
+import statusIcon from '../mr_widget_status_icon';
import MRWidgetAuthor from '../../components/mr_widget_author';
import eventHub from '../../event_hub';
@@ -11,6 +11,7 @@ export default {
},
components: {
'mr-widget-author': MRWidgetAuthor,
+ statusIcon,
},
data() {
return {
@@ -61,56 +62,56 @@ export default {
},
},
template: `
- <div class="mr-widget-body">
- <h4>
- Set by
- <mr-widget-author :author="mr.setToMWPSBy" />
- to be merged automatically when the pipeline succeeds.
- <a
- v-if="mr.canCancelAutomaticMerge"
- @click.prevent="cancelAutomaticMerge"
- :disabled="isCancellingAutoMerge"
- role="button"
- href="#"
- class="btn btn-xs btn-default js-cancel-auto-merge">
- <i
- v-if="isCancellingAutoMerge"
- class="fa fa-spinner fa-spin"
- aria-hidden="true" />
- Cancel automatic merge
- </a>
- </h4>
- <section class="mr-info-list">
- <div class="legend"></div>
- <p>The changes will be merged into
- <a
- :href="mr.targetBranchPath"
- class="label-branch">
- {{mr.targetBranch}}
- </a>.
- </p>
- <p v-if="mr.shouldRemoveSourceBranch">
- The source branch will be removed.
- </p>
- <p
- v-else
- class="with-button">
- The source branch will not be removed.
+ <div class="mr-widget-body media">
+ <status-icon status="success" />
+ <div class="media-body">
+ <h4>
+ Set by
+ <mr-widget-author :author="mr.setToMWPSBy" />
+ to be merged automatically when the pipeline succeeds
<a
- v-if="canRemoveSourceBranch"
- :disabled="isRemovingSourceBranch"
- @click.prevent="removeSourceBranch"
+ v-if="mr.canCancelAutomaticMerge"
+ @click.prevent="cancelAutomaticMerge"
+ :disabled="isCancellingAutoMerge"
role="button"
- class="btn btn-xs btn-default js-remove-source-branch"
- href="#">
+ href="#"
+ class="btn btn-xs btn-default js-cancel-auto-merge">
<i
- v-if="isRemovingSourceBranch"
- class="fa fa-spinner fa-spin"
- aria-hidden="true" />
- Remove source branch
+ v-if="isCancellingAutoMerge"
+ class="fa fa-spinner fa-spin"
+ aria-hidden="true" />
+ Cancel automatic merge
</a>
- </p>
- </section>
+ </h4>
+ <section class="mr-info-list">
+ <p>The changes will be merged into
+ <a
+ :href="mr.targetBranchPath"
+ class="label-branch">
+ {{mr.targetBranch}}
+ </a>
+ </p>
+ <p v-if="mr.shouldRemoveSourceBranch">
+ The source branch will be removed
+ </p>
+ <p v-else>
+ The source branch will not be removed
+ <a
+ v-if="canRemoveSourceBranch"
+ :disabled="isRemovingSourceBranch"
+ @click.prevent="removeSourceBranch"
+ role="button"
+ class="btn btn-xs btn-default js-remove-source-branch"
+ href="#">
+ <i
+ v-if="isRemovingSourceBranch"
+ class="fa fa-spinner fa-spin"
+ aria-hidden="true" />
+ Remove source branch
+ </a>
+ </p>
+ </section>
+ </div>
</div>
`,
};
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.js
index c7d32d18141..e452260a4d0 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.js
@@ -1,6 +1,9 @@
/* global Flash */
import mrWidgetAuthorTime from '../../components/mr_widget_author_time';
+import tooltip from '../../../vue_shared/directives/tooltip';
+import loadingIcon from '../../../vue_shared/components/loading_icon.vue';
+import statusIcon from '../mr_widget_status_icon';
import eventHub from '../../event_hub';
export default {
@@ -9,14 +12,19 @@ export default {
mr: { type: Object, required: true },
service: { type: Object, required: true },
},
- components: {
- 'mr-widget-author-and-time': mrWidgetAuthorTime,
- },
data() {
return {
isMakingRequest: false,
};
},
+ directives: {
+ tooltip,
+ },
+ components: {
+ 'mr-widget-author-and-time': mrWidgetAuthorTime,
+ loadingIcon,
+ statusIcon,
+ },
computed: {
shouldShowRemoveSourceBranch() {
const { sourceBranchRemoved, isRemovingSourceBranch, canRemoveSourceBranch } = this.mr;
@@ -55,75 +63,77 @@ export default {
},
},
template: `
- <div class="mr-widget-body">
- <mr-widget-author-and-time
- actionText="Merged by"
- :author="mr.mergedBy"
- :dateTitle="mr.updatedAt"
- :dateReadable="mr.mergedAt" />
- <section class="mr-info-list">
- <div class="legend"></div>
- <p>
- The changes were merged into
- <span class="label-branch">
- <a :href="mr.targetBranchPath">{{mr.targetBranch}}</a>
- </span>
- </p>
- <p v-if="mr.sourceBranchRemoved">The source branch has been removed.</p>
- <p v-if="shouldShowRemoveSourceBranch">
- You can remove source branch now.
- <button
- @click="removeSourceBranch"
- :class="{ disabled: isMakingRequest }"
- type="button"
- class="btn btn-xs btn-default js-remove-branch-button">
- Remove Source Branch
- </button>
- </p>
- <p v-if="shouldShowSourceBranchRemoving">
- <i
- class="fa fa-spinner fa-spin"
- aria-hidden="true" />
- The source branch is being removed.
- </p>
- </section>
- <div
- v-if="shouldShowMergedButtons"
- class="merged-buttons clearfix">
- <a
- v-if="mr.canRevertInCurrentMR"
- class="btn btn-close btn-sm has-tooltip"
- href="#modal-revert-commit"
- data-toggle="modal"
- data-container="body"
- title="Revert this merge request in a new merge request">
- Revert
- </a>
- <a
- v-else-if="mr.revertInForkPath"
- class="btn btn-close btn-sm has-tooltip"
- data-method="post"
- :href="mr.revertInForkPath"
- title="Revert this merge request in a new merge request">
- Revert
- </a>
- <a
- v-if="mr.canCherryPickInCurrentMR"
- class="btn btn-default btn-sm has-tooltip"
- href="#modal-cherry-pick-commit"
- data-toggle="modal"
- data-container="body"
- title="Cherry-pick this merge request in a new merge request">
- Cherry-pick
- </a>
- <a
- v-else-if="mr.cherryPickInForkPath"
- class="btn btn-default btn-sm has-tooltip"
- data-method="post"
- :href="mr.cherryPickInForkPath"
- title="Cherry-pick this merge request in a new merge request">
- Cherry-pick
- </a>
+ <div class="mr-widget-body media">
+ <status-icon status="success" />
+ <div class="media-body">
+ <div class="space-children">
+ <mr-widget-author-and-time
+ actionText="Merged by"
+ :author="mr.mergedBy"
+ :dateTitle="mr.updatedAt"
+ :dateReadable="mr.mergedAt" />
+ <a
+ v-if="mr.canRevertInCurrentMR"
+ v-tooltip
+ class="btn btn-close btn-xs"
+ href="#modal-revert-commit"
+ data-toggle="modal"
+ data-container="body"
+ title="Revert this merge request in a new merge request">
+ Revert
+ </a>
+ <a
+ v-else-if="mr.revertInForkPath"
+ v-tooltip
+ class="btn btn-close btn-xs"
+ data-method="post"
+ :href="mr.revertInForkPath"
+ title="Revert this merge request in a new merge request">
+ Revert
+ </a>
+ <a
+ v-if="mr.canCherryPickInCurrentMR"
+ v-tooltip
+ class="btn btn-default btn-xs"
+ href="#modal-cherry-pick-commit"
+ data-toggle="modal"
+ data-container="body"
+ title="Cherry-pick this merge request in a new merge request">
+ Cherry-pick
+ </a>
+ <a
+ v-else-if="mr.cherryPickInForkPath"
+ v-tooltip
+ class="btn btn-default btn-xs"
+ data-method="post"
+ :href="mr.cherryPickInForkPath"
+ title="Cherry-pick this merge request in a new merge request">
+ Cherry-pick
+ </a>
+ </div>
+ <section class="mr-info-list">
+ <p>
+ The changes were merged into
+ <span class="label-branch">
+ <a :href="mr.targetBranchPath">{{mr.targetBranch}}</a>
+ </span>
+ </p>
+ <p v-if="mr.sourceBranchRemoved">The source branch has been removed</p>
+ <p v-if="shouldShowRemoveSourceBranch" class="space-children">
+ <span>You can remove source branch now</span>
+ <button
+ @click="removeSourceBranch"
+ :disabled="isMakingRequest"
+ type="button"
+ class="btn btn-xs btn-default js-remove-branch-button">
+ Remove Source Branch
+ </button>
+ </p>
+ <p v-if="shouldShowSourceBranchRemoving">
+ <loading-icon inline />
+ <span>The source branch is being removed</span>
+ </p>
+ </section>
</div>
</div>
`,
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.js
index 328382485f6..9f0a359d01a 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.js
@@ -1,3 +1,5 @@
+import statusIcon from '../mr_widget_status_icon';
+import tooltip from '../../../vue_shared/directives/tooltip';
import mrWidgetMergeHelp from '../../components/mr_widget_merge_help';
export default {
@@ -5,30 +7,37 @@ export default {
props: {
mr: { type: Object, required: true },
},
+ directives: {
+ tooltip,
+ },
components: {
'mr-widget-merge-help': mrWidgetMergeHelp,
+ statusIcon,
},
computed: {
missingBranchName() {
return this.mr.sourceBranchRemoved ? 'source' : 'target';
},
+ message() {
+ return `If the ${this.missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line`;
+ },
},
template: `
- <div class="mr-widget-body">
- <button
- type="button"
- class="btn btn-success btn-small"
- disabled="true">
- Merge
- </button>
- <span class="bold js-branch-text">
- <span class="capitalize">
- {{missingBranchName}}
- </span> branch does not exist.
- Please restore the {{missingBranchName}} branch or use a different {{missingBranchName}} branch.
- </span>
- <mr-widget-merge-help
- :missing-branch="missingBranchName" />
+ <div class="mr-widget-body media">
+ <status-icon status="failed" showDisabledButton />
+ <div class="media-body space-children">
+ <span class="bold js-branch-text">
+ <span class="capitalize">
+ {{missingBranchName}}
+ </span> branch does not exist.
+ Please restore it or use a different {{missingBranchName}} branch
+ <i
+ v-tooltip
+ class="fa fa-question-circle"
+ :title="message"
+ :aria-label="message"></i>
+ </span>
+ </div>
</div>
`,
};
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_not_allowed.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_not_allowed.js
index 07169b349be..797511d4e3a 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_not_allowed.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_not_allowed.js
@@ -1,17 +1,19 @@
+import statusIcon from '../mr_widget_status_icon';
+
export default {
name: 'MRWidgetNotAllowed',
+ components: {
+ statusIcon,
+ },
template: `
- <div class="mr-widget-body">
- <button
- type="button"
- class="btn btn-success btn-small"
- disabled="true">
- Merge
- </button>
- <span class="bold">
- Ready to be merged automatically.
- Ask someone with write access to this repository to merge this request.
- </span>
+ <div class="mr-widget-body media">
+ <status-icon status="success" showDisabledButton />
+ <div class="media-body space-children">
+ <span class="bold">
+ Ready to be merged automatically.
+ Ask someone with write access to this repository to merge this request
+ </span>
+ </div>
</div>
`,
};
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_nothing_to_merge.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_nothing_to_merge.js
index 375a382615a..ebfd6765934 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_nothing_to_merge.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_nothing_to_merge.js
@@ -12,7 +12,7 @@ export default {
return { emptyStateSVG };
},
template: `
- <div class="mr-widget-body empty-state">
+ <div class="mr-widget-body mr-widget-empty-state">
<div class="row">
<div class="artwork col-sm-5 col-sm-push-7 col-xs-12 text-center">
<span v-html="emptyStateSVG"></span>
@@ -29,12 +29,14 @@ export default {
Currently there are no changes in this merge request's source branch.
Please push new commits or use a different branch.
</p>
- <a
- v-if="mr.newBlobPath"
- :href="mr.newBlobPath"
- class="btn btn-inverted btn-save">
- Create file
- </a>
+ <div>
+ <a
+ v-if="mr.newBlobPath"
+ :href="mr.newBlobPath"
+ class="btn btn-inverted btn-save">
+ Create file
+ </a>
+ </div>
</div>
</div>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.js
index 31c53b679ed..167a0d4613a 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.js
@@ -1,16 +1,18 @@
+import statusIcon from '../mr_widget_status_icon';
+
export default {
name: 'MRWidgetPipelineBlocked',
+ components: {
+ statusIcon,
+ },
template: `
- <div class="mr-widget-body">
- <button
- type="button"
- class="btn btn-success btn-small"
- disabled="true">
- Merge
- </button>
- <span class="bold">
- Pipeline blocked. The pipeline for this merge request requires a manual action to proceed.
- </span>
+ <div class="mr-widget-body media">
+ <status-icon status="failed" showDisabledButton />
+ <div class="media-body space-children">
+ <span class="bold">
+ Pipeline blocked. The pipeline for this merge request requires a manual action to proceed
+ </span>
+ </div>
</div>
`,
};
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_failed.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_failed.js
index 002820123ca..c5be9a0530a 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_failed.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_failed.js
@@ -1,16 +1,18 @@
+import statusIcon from '../mr_widget_status_icon';
+
export default {
name: 'MRWidgetPipelineBlocked',
+ components: {
+ statusIcon,
+ },
template: `
- <div class="mr-widget-body">
- <button
- class="btn btn-success btn-small"
- disabled="true"
- type="button">
- Merge
- </button>
- <span class="bold">
- The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure.
- </span>
+ <div class="mr-widget-body media">
+ <status-icon status="failed" showDisabledButton />
+ <div class="media-body space-children">
+ <span class="bold">
+ The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure
+ </span>
+ </div>
</div>
`,
};
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_ready_to_merge.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_ready_to_merge.js
index fcd4fdaf09f..65187754009 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_ready_to_merge.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_ready_to_merge.js
@@ -1,8 +1,8 @@
/* global Flash */
-
import successSvg from 'icons/_icon_status_success.svg';
import warningSvg from 'icons/_icon_status_warning.svg';
import simplePoll from '~/lib/utils/simple_poll';
+import statusIcon from '../mr_widget_status_icon';
import eventHub from '../../event_hub';
export default {
@@ -25,6 +25,9 @@ export default {
warningSvg,
};
},
+ components: {
+ statusIcon,
+ },
computed: {
commitMessageLinkTitle() {
const withDesc = 'Include description in commit message';
@@ -196,84 +199,98 @@ export default {
},
},
template: `
- <div class="mr-widget-body">
- <span class="btn-group">
- <button
- @click="handleMergeButtonClick()"
- :disabled="isMergeButtonDisabled"
- :class="mergeButtonClass"
- type="button">
- <i
- v-if="isMakingRequest"
- class="fa fa-spinner fa-spin"
- aria-hidden="true" />
- {{mergeButtonText}}
- </button>
- <button
- v-if="shouldShowMergeOptionsDropdown"
- :disabled="isMergeButtonDisabled"
- type="button"
- class="btn btn-small btn-info dropdown-toggle"
- data-toggle="dropdown">
- <i
- class="fa fa-caret-down"
- aria-hidden="true" />
- <span class="sr-only">
- Select merge moment
+ <div class="mr-widget-body media">
+ <status-icon status="success" />
+ <div class="media-body">
+ <div class="media space-children">
+ <span class="btn-group">
+ <button
+ @click="handleMergeButtonClick()"
+ :disabled="isMergeButtonDisabled"
+ :class="mergeButtonClass"
+ type="button">
+ <i
+ v-if="isMakingRequest"
+ class="fa fa-spinner fa-spin"
+ aria-hidden="true" />
+ {{mergeButtonText}}
+ </button>
+ <button
+ v-if="shouldShowMergeOptionsDropdown"
+ :disabled="isMergeButtonDisabled"
+ type="button"
+ class="btn btn-small btn-info dropdown-toggle js-merge-moment"
+ data-toggle="dropdown"
+ aria-label="Select merge moment">
+ <i
+ class="fa fa-chevron-down"
+ aria-hidden="true" />
+ </button>
+ <ul
+ v-if="shouldShowMergeOptionsDropdown"
+ class="dropdown-menu dropdown-menu-right"
+ role="menu">
+ <li>
+ <a
+ @click.prevent="handleMergeButtonClick(true)"
+ class="merge_when_pipeline_succeeds"
+ href="#">
+ <span class="media">
+ <span
+ v-html="successSvg"
+ class="merge-opt-icon"
+ aria-hidden="true"></span>
+ <span class="media-body merge-opt-title">Merge when pipeline succeeds</span>
+ </span>
+ </a>
+ </li>
+ <li>
+ <a
+ @click.prevent="handleMergeButtonClick(false, true)"
+ class="accept-merge-request"
+ href="#">
+ <span class="media">
+ <span
+ v-html="warningSvg"
+ class="merge-opt-icon"
+ aria-hidden="true"></span>
+ <span class="media-body merge-opt-title">Merge immediately</span>
+ </span>
+ </a>
+ </li>
+ </ul>
</span>
- </button>
- <ul
- v-if="shouldShowMergeOptionsDropdown"
- class="dropdown-menu dropdown-menu-right"
- role="menu">
- <li>
- <a
- @click.prevent="handleMergeButtonClick(true)"
- class="merge_when_pipeline_succeeds"
- href="#">
- <span
- v-html="successSvg"
- class="merge-opt-icon"
- aria-hidden="true"></span>
- <span class="merge-opt-title">Merge when pipeline succeeds</span>
- </a>
- </li>
- <li>
- <a
- @click.prevent="handleMergeButtonClick(false, true)"
- class="accept-merge-request"
- href="#">
- <span
- v-html="warningSvg"
- class="merge-opt-icon"
- aria-hidden="true"></span>
- <span class="merge-opt-title">Merge immediately</span>
- </a>
- </li>
- </ul>
- </span>
- <template v-if="isMergeAllowed()">
- <label class="spacing">
- <input
- id="remove-source-branch-input"
- v-model="removeSourceBranch"
- :disabled="isRemoveSourceBranchButtonDisabled"
- type="checkbox"/> Remove source branch
- </label>
+ <div class="media-body space-children">
+ <template v-if="isMergeAllowed()">
+ <label>
+ <input
+ id="remove-source-branch-input"
+ v-model="removeSourceBranch"
+ :disabled="isRemoveSourceBranchButtonDisabled"
+ type="checkbox"/> Remove source branch
+ </label>
- <!-- Placeholder for EE extension of this component -->
- <squash-before-merge
- v-if="shouldShowSquashBeforeMerge"
- :mr="mr"
- :is-merge-button-disabled="isMergeButtonDisabled" />
+ <!-- Placeholder for EE extension of this component -->
+ <squash-before-merge
+ v-if="shouldShowSquashBeforeMerge"
+ :mr="mr"
+ :is-merge-button-disabled="isMergeButtonDisabled" />
- <button
- @click="toggleCommitMessageEditor"
- :disabled="isMergeButtonDisabled"
- class="btn btn-default btn-xs"
- type="button">
- Modify commit message
- </button>
+ <button
+ @click="toggleCommitMessageEditor"
+ :disabled="isMergeButtonDisabled"
+ class="btn btn-default btn-xs"
+ type="button">
+ Modify commit message
+ </button>
+ </template>
+ <template v-else>
+ <span class="bold">
+ The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure
+ </span>
+ </template>
+ </div>
+ </div>
<div
v-if="showCommitMessageEditor"
class="prepend-top-default commit-message-editor">
@@ -293,7 +310,7 @@ export default {
rows="14"
name="Commit message"></textarea>
</div>
- <p class="hint">Try to keep the first line under 52 characters and the others under 72.</p>
+ <p class="hint">Try to keep the first line under 52 characters and the others under 72</p>
<div class="hint">
<a
@click.prevent="updateCommitMessage"
@@ -302,12 +319,7 @@ export default {
</div>
</div>
</div>
- </template>
- <template v-else>
- <span class="bold">
- The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure.
- </span>
- </template>
+ </div>
</div>
`,
};
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_sha_mismatch.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_sha_mismatch.js
index 79f8ef408e6..89f38e5bd2a 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_sha_mismatch.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_sha_mismatch.js
@@ -1,16 +1,18 @@
+import statusIcon from '../mr_widget_status_icon';
+
export default {
name: 'MRWidgetSHAMismatch',
+ components: {
+ statusIcon,
+ },
template: `
- <div class="mr-widget-body">
- <button
- type="button"
- class="btn btn-success btn-small"
- disabled="true">
- Merge
- </button>
- <span class="bold">
- The source branch HEAD has recently changed. Please reload the page and review the changes before merging.
- </span>
+ <div class="mr-widget-body media">
+ <status-icon status="failed" showDisabledButton />
+ <div class="media-body space-children">
+ <span class="bold">
+ The source branch HEAD has recently changed. Please reload the page and review the changes before merging
+ </span>
+ </div>
</div>
`,
};
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_unresolved_discussions.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_unresolved_discussions.js
index f4ab2d9fa58..d762ca6e640 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_unresolved_discussions.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_unresolved_discussions.js
@@ -1,27 +1,27 @@
+import statusIcon from '../mr_widget_status_icon';
+
export default {
name: 'MRWidgetUnresolvedDiscussions',
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">
- Merge
- </button>
- <span class="bold">
- There are unresolved discussions. Please resolve these discussions
- <span v-if="mr.canCreateIssue">or</span>
- <span v-else>.</span>
- </span>
- <a
- v-if="mr.createIssueToResolveDiscussionsPath"
- :href="mr.createIssueToResolveDiscussionsPath"
- class="btn btn-default btn-xs js-create-issue">
- Create an issue to resolve them later
- </a>
+ <div class="mr-widget-body media">
+ <status-icon status="failed" showDisabledButton />
+ <div class="media-body space-children">
+ <span class="bold">
+ There are unresolved discussions. Please resolve these discussions
+ </span>
+ <a
+ v-if="mr.createIssueToResolveDiscussionsPath"
+ :href="mr.createIssueToResolveDiscussionsPath"
+ class="btn btn-default btn-xs js-create-issue">
+ Create an issue to resolve them later
+ </a>
+ </div>
</div>
`,
};
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_wip.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_wip.js
index cb02ffe93bd..b11a06899cf 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_wip.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_wip.js
@@ -1,4 +1,6 @@
/* global Flash */
+import statusIcon from '../mr_widget_status_icon';
+import tooltip from '../../../vue_shared/directives/tooltip';
import eventHub from '../../event_hub';
export default {
@@ -7,11 +9,17 @@ export default {
mr: { type: Object, required: true },
service: { type: Object, required: true },
},
+ directives: {
+ tooltip,
+ },
data() {
return {
isMakingRequest: false,
};
},
+ components: {
+ statusIcon,
+ },
methods: {
removeWIP() {
this.isMakingRequest = true;
@@ -29,20 +37,20 @@ export default {
},
},
template: `
- <div class="mr-widget-body">
- <button
- type="button"
- class="btn btn-success btn-small"
- disabled="true">
- Merge</button>
- <span class="bold">
- This merge request is currently Work In Progress and therefore unable to merge
- </span>
- <template v-if="mr.removeWIPPath">
- <i
- class="fa fa-question-circle has-tooltip"
- title="When this merge request is ready, remove the WIP: prefix from the title to allow it to be merged." />
+ <div class="mr-widget-body media">
+ <status-icon status="failed" :showDisabledButton="Boolean(mr.removeWIPPath)" />
+ <div class="media-body space-children">
+ <span class="bold">
+ This is a Work in Progress
+ <i
+ v-tooltip
+ class="fa fa-question-circle"
+ title="When this merge request is ready, remove the WIP: prefix from the title to allow it to be merged"
+ aria-label="When this merge request is ready, remove the WIP: prefix from the title to allow it to be merged">
+ </i>
+ </span>
<button
+ v-if="mr.removeWIPPath"
@click="removeWIP"
:disabled="isMakingRequest"
type="button"
@@ -53,7 +61,7 @@ export default {
aria-hidden="true" />
Resolve WIP status
</button>
- </template>
+ </div>
</div>
`,
};
diff --git a/app/assets/javascripts/vue_merge_request_widget/dependencies.js b/app/assets/javascripts/vue_merge_request_widget/dependencies.js
index fe5e1bbb55c..546a3f625c7 100644
--- a/app/assets/javascripts/vue_merge_request_widget/dependencies.js
+++ b/app/assets/javascripts/vue_merge_request_widget/dependencies.js
@@ -1,7 +1,7 @@
/**
* This file is the centerpiece of an attempt to reduce potential conflicts
* between the CE and EE versions of the MR widget. EE additions to the MR widget should
- * be contained in the ./vue_merge_request_widget/ee directory, and should **extend**
+ * be contained in the ee/vue_merge_request_widget directory, and should **extend**
* rather than mutate CE MR Widget code.
*
* This file should be the only source of conflicts between EE and CE. EE-only components should
diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js
index 2339a00ddd0..577d77f09a6 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js
+++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js
@@ -35,8 +35,14 @@ import {
export default {
el: '#js-vue-mr-widget',
name: 'MRWidget',
+ props: {
+ mrData: {
+ type: Object,
+ required: false,
+ },
+ },
data() {
- const store = new MRWidgetStore(gl.mrWidgetData);
+ const store = new MRWidgetStore(this.mrData || window.gl.mrWidgetData);
const service = this.createService(store);
return {
mr: store,
@@ -234,14 +240,21 @@ export default {
v-if="shouldRenderDeployments"
:mr="mr"
:service="service" />
- <component
- :is="componentName"
- :mr="mr"
- :service="service" />
- <mr-widget-related-links
- v-if="shouldRenderRelatedLinks"
- :related-links="mr.relatedLinks" />
- <mr-widget-merge-help v-if="shouldRenderMergeHelp" />
+ <div class="mr-widget-section">
+ <component
+ :is="componentName"
+ :mr="mr"
+ :service="service" />
+ <mr-widget-related-links
+ v-if="shouldRenderRelatedLinks"
+ :state="mr.state"
+ :related-links="mr.relatedLinks" />
+ </div>
+ <div
+ class="mr-widget-footer"
+ v-if="shouldRenderMergeHelp">
+ <mr-widget-merge-help />
+ </div>
</div>
`,
};
diff --git a/app/assets/stylesheets/framework.scss b/app/assets/stylesheets/framework.scss
index 6ce331a9129..b2b3297e880 100644
--- a/app/assets/stylesheets/framework.scss
+++ b/app/assets/stylesheets/framework.scss
@@ -26,6 +26,7 @@
@import "framework/lists";
@import "framework/logo";
@import "framework/markdown_area";
+@import "framework/media_object";
@import "framework/mobile";
@import "framework/modal";
@import "framework/nav";
diff --git a/app/assets/stylesheets/framework/calendar.scss b/app/assets/stylesheets/framework/calendar.scss
index 0ac095f7d8f..0ded4a3b423 100644
--- a/app/assets/stylesheets/framework/calendar.scss
+++ b/app/assets/stylesheets/framework/calendar.scss
@@ -45,6 +45,7 @@
margin-top: -23px;
float: right;
font-size: 12px;
+ direction: ltr;
}
.pika-single.gitlab-theme {
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index bd4bd541c3a..02e0ba74158 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -728,6 +728,10 @@
@mixin new-style-dropdown {
.dropdown-menu,
.dropdown-menu-nav {
+ .divider {
+ margin: 6px 0;
+ }
+
li {
padding: 0 1px;
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index 555e444a062..4a69c14fa7e 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -325,9 +325,9 @@ header {
li {
.badge {
position: inherit;
- top: -3px;
+ top: -8px;
font-weight: normal;
- margin-left: -12px;
+ margin-left: -11px;
font-size: 11px;
color: $white-light;
padding: 1px 5px 2px;
diff --git a/app/assets/stylesheets/framework/media_object.scss b/app/assets/stylesheets/framework/media_object.scss
new file mode 100644
index 00000000000..b573052c14a
--- /dev/null
+++ b/app/assets/stylesheets/framework/media_object.scss
@@ -0,0 +1,8 @@
+.media {
+ display: flex;
+ align-items: flex-start;
+}
+
+.media-body {
+ flex: 1;
+}
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index 0df6f24bfe6..1d0f10d6a32 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -206,7 +206,6 @@ $general-hover-transition-curve: linear;
$highlight-changes-color: rgb(235, 255, 232);
$performance-bar-height: 35px;
-
/*
* Common component specific colors
*/
@@ -316,6 +315,12 @@ $badge-bg: rgba(0, 0, 0, 0.07);
$badge-color: $gl-text-color-secondary;
/*
+ * Status icons
+ */
+$status-icon-size: 22px;
+$status-icon-margin: $gl-btn-padding;
+
+/*
* Award emoji
*/
$award-emoji-menu-shadow: rgba(0, 0, 0, .175);
diff --git a/app/assets/stylesheets/new_nav.scss b/app/assets/stylesheets/new_nav.scss
index 1c4a84de7ec..795ee91af8b 100644
--- a/app/assets/stylesheets/new_nav.scss
+++ b/app/assets/stylesheets/new_nav.scss
@@ -312,6 +312,10 @@ header.navbar-gitlab-new {
// TODO: fallback to global style
.dropdown-menu {
+ .divider {
+ margin: 6px 0;
+ }
+
li {
padding: 0 1px;
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index 6da14320914..88343bd0113 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -328,9 +328,17 @@
margin-bottom: 10px;
color: $issuable-sidebar-color;
+ svg {
+ fill: $issuable-sidebar-color;
+ }
+
&:hover,
&:hover .todo-undone {
color: $gl-text-color;
+
+ svg {
+ fill: $gl-text-color;
+ }
}
span {
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index a4e19094508..6bb013cca85 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -2,10 +2,35 @@
* MR -> show: Automerge widget
*
*/
+
+.space-children {
+ @include clearfix;
+
+ > * {
+ float: left;
+ }
+
+ > *:not(:last-child) {
+ margin-right: 10px;
+ }
+}
+
.mr-state-widget {
color: $gl-text-color;
border: 1px solid $border-color;
border-radius: 2px;
+ line-height: 28px;
+
+ .mr-widget-heading,
+ .mr-widget-section,
+ .mr-widget-footer {
+ padding: $gl-padding;
+ border-top: solid 1px $border-color;
+ }
+
+ .mr-widget-footer {
+ padding: 0;
+ }
form {
margin-bottom: 0;
@@ -15,15 +40,35 @@
}
}
+ label {
+ margin-bottom: 0;
+ }
+
+ .btn {
+ font-size: $gl-font-size;
+
+ &[disabled] {
+ opacity: 0.3;
+ }
+
+ &.btn-xs {
+ line-height: 1;
+ padding: 5px 10px;
+ margin-top: 1px;
+ }
+
+ &.dropdown-toggle {
+ .fa {
+ color: inherit;
+ }
+ }
+ }
+
.accept-merge-holder {
.accept-action {
display: inline-block;
float: left;
- .btn-success.dropdown-toggle .fa {
- color: inherit;
- }
-
.accept-merge-request {
&.ci-pending,
&.ci-running {
@@ -84,77 +129,64 @@
.ci-widget {
color: $gl-text-color;
- display: -webkit-flex;
display: flex;
- -webkit-align-items: center;
- align-items: center;
- padding: $gl-padding-top $gl-padding 0;
-
- svg {
- position: relative;
- top: 1px;
- overflow: visible;
- }
-
- > span {
- padding-right: 4px;
- }
@media (max-width: $screen-xs-max) {
flex-wrap: wrap;
}
+ }
- .icon-link > .ci-status-icon > svg {
- width: 22px;
- height: 22px;
- margin-right: 8px;
- }
+ .mr-widget-icon {
+ font-size: 22px;
+ margin-right: $status-icon-margin;
+ }
- .ci-error {
- margin-right: $btn-side-margin;
- }
+ .ci-status-icon svg {
+ width: $status-icon-size;
+ height: $status-icon-size;
+ margin: 3px 0;
+ position: relative;
+ overflow: visible;
+ display: block;
}
- .mr-widget-body,
- .mr-widget-footer {
- margin: 16px;
+ .mr-widget-body {
+ @include clearfix;
+
+ &.media > *:first-child {
+ margin-right: 10px;
+ }
}
.mr-widget-pipeline-graph {
- flex-shrink: 0;
+ padding: 0 4px;
.dropdown-menu {
- margin-top: 11px;
z-index: 300;
}
.ci-action-icon-wrapper {
line-height: 16px;
}
+ }
- @media (max-width: $screen-xs-max) {
- order: 1;
- margin-top: $gl-padding-top;
- border-radius: 3px;
- background-color: $white-light;
- border: 1px solid $gray-darker;
- width: 100%;
- text-align: center;
+ .mini-pipeline-graph-dropdown-toggle {
+ vertical-align: top;
+ }
- .dropdown-menu {
- margin-left: -97.5px;
- }
+ .mini-pipeline-graph-dropdown-menu .mini-pipeline-graph-dropdown-item {
+ display: flex;
+ align-items: center;
- .arrow-up::before,
- .arrow-up::after, {
- margin-left: 97.5px;
- }
+ .ci-status-text,
+ .ci-status-icon {
+ top: 0;
+ margin-right: 10px;
}
}
.normal {
- color: $gl-text-color;
- font-size: 15px;
+ line-height: 28px;
}
.capitalize {
@@ -165,9 +197,8 @@
@extend .ref-name;
color: $gl-text-color;
- font-weight: bold;
+ font-weight: 600;
overflow: hidden;
- margin: 0 3px;
word-break: break-all;
&.label-truncated {
@@ -189,52 +220,19 @@
}
}
- .js-deployment-link {
- display: inline-block;
- }
-
.mr-widget-help {
- margin: $gl-padding;
- color: $ci-skipped-color;
- }
-
- .mr-info-list {
-
- &.mr-links {
- margin-left: 28px;
- }
-
- &.mr-memory-usage {
- margin: 5px 0 10px 25px;
- }
- }
-
- .mr-widget-heading {
- .btn-default.btn-xs {
- margin-left: 5px;
- }
- }
-
- .mr-widget-body {
- .btn {
- font-size: 15px;
- }
-
- .btn-group .btn {
- padding: 5px 10px;
-
- &.dropdown-toggle {
- padding: 5px 7px;
- }
- }
+ padding: 10px 16px 10px 48px;
+ font-style: italic;
}
.mr-widget-body {
h4 {
- font-weight: bold;
- font-size: 15px;
- margin: 5px 0;
- color: $gl-text-color;
+ float: left;
+ font-weight: 600;
+ font-size: 14px;
+ line-height: inherit;
+ margin-top: 0;
+ margin-bottom: 0;
&.has-conflicts .fa-exclamation-triangle {
color: $gl-warning;
@@ -255,18 +253,16 @@
}
.spacing {
- margin: 0 $gl-padding;
+ margin: 0 0 0 10px;
}
.bold {
- font-weight: bold;
- font-size: 15px;
+ font-weight: 600;
color: $gl-gray-light;
}
.state-label {
- font-size: 16px;
- font-weight: bold;
+ font-weight: 600;
padding-right: 10px;
}
@@ -274,16 +270,6 @@
color: $gl-danger;
}
- .mr-widget-help {
- margin: $gl-padding 0;
- }
-
- .with-button {
- position: relative;
- top: 6px;
- margin-bottom: 24px;
- }
-
.spacing,
.bold {
vertical-align: middle;
@@ -294,15 +280,8 @@
padding: 5px;
}
- .merge-opt-icon,
- .merge-opt-title {
- display: inline-block;
- float: left;
- }
-
- .merge-opt-icon svg {
- height: 15px;
- width: 15px;
+ .merge-opt-icon {
+ line-height: 1.5;
}
.merge-opt-title {
@@ -316,34 +295,15 @@
}
}
- .has-error-message + .has-custom-error {
- margin-left: 0;
- }
-
.has-custom-error {
display: inline-block;
- margin-left: 70px;
- }
-
- .merge-error-text {
- margin-left: 70px;
}
@media (max-width: $screen-xs-max) {
- h4 {
- font-size: 14px;
- }
-
p {
font-size: 13px;
}
- .btn,
- .btn-group,
- .accept-action {
- margin-bottom: 4px;
- }
-
.btn-grouped {
float: none;
margin-right: 0;
@@ -367,19 +327,16 @@
}
}
- &.mr-state-locked .mr-info-list {
- margin-top: 10px;
- margin-left: 12px;
- }
+ &.mr-widget-empty-state {
+ line-height: 20px;
- &.empty-state {
.artwork {
margin-bottom: $gl-padding;
}
.text {
span {
- font-weight: bold;
+ font-weight: 600;
}
p {
@@ -389,10 +346,6 @@
}
}
- .mr-widget-footer {
- border-top: 1px solid $gray-darker;
- }
-
.ci-coverage {
float: right;
}
@@ -497,8 +450,6 @@
}
.btn-clipboard {
- @extend .pull-right;
-
margin-right: 20px;
margin-top: 5px;
position: absolute;
@@ -506,56 +457,29 @@
}
}
+.mr-links {
+ padding-left: $status-icon-size + $status-icon-margin;
+}
+
.mr-info-list {
+ clear: left;
position: relative;
- margin: 10px 0 $gl-padding 12px;
+ padding-top: 4px;
p {
- margin: 6px 0;
+ margin: 0;
position: relative;
- padding-left: 15px;
-
- &::before {
- content: '';
- position: absolute;
- border-top: 2px solid $border-color;
- height: 1px;
- top: 9px;
- width: 8px;
- left: 0;
- }
+ padding: 4px 0;
&:last-child {
- margin-bottom: 0;
+ padding-bottom: 0;
}
}
-
- .legend {
- height: 100%;
- width: 2px;
- background: $border-color;
- position: absolute;
- top: -9px;
- }
}
.mr-info-list.mr-memory-usage {
- .legend {
- height: 65%;
- top: 0;
-
- @media (max-width: $screen-xs-max) {
- height: 20px;
- }
- }
-
p {
float: left;
- padding-left: 21px;
-
- &::before {
- top: 13px;
- }
}
.memory-graph-container {
@@ -565,12 +489,13 @@
}
.mr-source-target {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: space-between;
+ align-items: center;
background-color: $gray-light;
- border-radius: 3px 3px 0 0;
- border-bottom: 1px solid $border-color;
- padding: 0 $gl-padding;
- margin-bottom: 6px;
- line-height: 44px;
+ border-radius: $border-radius-default $border-radius-default 0 0;
+ padding: $gl-padding / 2 $gl-padding;
.dropdown-toggle .fa {
color: $gl-text-color;
@@ -679,14 +604,8 @@
}
.merged-buttons {
- margin-top: 20px;
-
.btn {
float: left;
-
- &:not(:last-child) {
- margin-right: 10px;
- }
}
}
@@ -803,20 +722,8 @@
}
.mr-memory-usage {
- p.usage-info-loading,
- p.usage-info-unavailable,
- p.usage-info-failed {
- margin-bottom: 5px;
- }
-
p.usage-info-loading .usage-info-load-spinner {
margin-right: 10px;
font-size: 16px;
}
-
- @media (max-width: $screen-md-min) {
- .mr-info-list.mr-memory-usage .legend {
- height: 80%;
- }
- }
}
diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss
index d3862df20d3..6185342b495 100644
--- a/app/assets/stylesheets/pages/pipelines.scss
+++ b/app/assets/stylesheets/pages/pipelines.scss
@@ -220,7 +220,11 @@
position: relative;
vertical-align: middle;
height: 22px;
- margin: 3px 6px 3px 0;
+ margin: 3px 0;
+
+ + .stage-container {
+ margin-left: 6px;
+ }
// Hack to show a button tooltip inline
button.has-tooltip + .tooltip {
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index d29421aa1b3..73603f20ef6 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -36,7 +36,6 @@
}
select {
- background: transparent;
transition: background 2s ease-out;
&.highlight-changes {
diff --git a/app/assets/stylesheets/pages/settings.scss b/app/assets/stylesheets/pages/settings.scss
index d69a8e0995c..15df51e9c69 100644
--- a/app/assets/stylesheets/pages/settings.scss
+++ b/app/assets/stylesheets/pages/settings.scss
@@ -54,8 +54,7 @@
.settings-content {
max-height: 1px;
overflow-y: scroll;
- margin-right: -20px;
- padding-right: 130px;
+ padding-right: 110px;
animation: collapseMaxHeight 300ms ease-out;
&.expanded {
@@ -87,6 +86,23 @@
overflow: hidden;
margin-top: 20px;
}
+
+ .sub-section {
+ margin-bottom: 32px;
+ padding: 16px;
+ border: 1px solid $border-color;
+ background-color: $gray-light;
+ }
+
+ .bs-callout,
+ .checkbox:first-child,
+ .help-block {
+ margin-top: 0;
+ }
+
+ .label-light {
+ margin-bottom: 0;
+ }
}
.settings-list-icon {
diff --git a/app/models/project.rb b/app/models/project.rb
index d85782782aa..09b1305739c 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -941,7 +941,7 @@ class Project < ActiveRecord::Base
end
def repo
- repository.raw
+ repository.rugged
end
def url_to_repo
diff --git a/app/models/repository.rb b/app/models/repository.rb
index b04d434926f..f86a0869b01 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -614,17 +614,26 @@ class Repository
end
def last_commit_for_path(sha, path)
- sha = last_commit_id_for_path(sha, path)
- commit(sha)
+ raw_repository.gitaly_migrate(:last_commit_for_path) do |is_enabled|
+ if is_enabled
+ last_commit_for_path_by_gitaly(sha, path)
+ else
+ last_commit_for_path_by_rugged(sha, path)
+ end
+ end
end
- # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/383
def last_commit_id_for_path(sha, path)
key = path.blank? ? "last_commit_id_for_path:#{sha}" : "last_commit_id_for_path:#{sha}:#{Digest::SHA1.hexdigest(path)}"
cache.fetch(key) do
- args = %W(rev-list --max-count=1 #{sha} -- #{path})
- run_git(args).first.strip
+ raw_repository.gitaly_migrate(:last_commit_for_path) do |is_enabled|
+ if is_enabled
+ last_commit_for_path_by_gitaly(sha, path).id
+ else
+ last_commit_id_for_path_by_shelling_out(sha, path)
+ end
+ end
end
end
@@ -1149,6 +1158,21 @@ class Repository
Rugged::Commit.create(rugged, params)
end
+ def last_commit_for_path_by_gitaly(sha, path)
+ c = raw_repository.gitaly_commit_client.last_commit_for_path(sha, path)
+ commit(c)
+ end
+
+ def last_commit_for_path_by_rugged(sha, path)
+ sha = last_commit_id_for_path_by_shelling_out(sha, path)
+ commit(sha)
+ end
+
+ def last_commit_id_for_path_by_shelling_out(sha, path)
+ args = %W(rev-list --max-count=1 #{sha} -- #{path})
+ run_git(args).first.strip
+ end
+
def repository_storage_path
@project.repository_storage_path
end
diff --git a/app/services/merge_requests/create_service.rb b/app/services/merge_requests/create_service.rb
index 19189e64acf..5414fa79def 100644
--- a/app/services/merge_requests/create_service.rb
+++ b/app/services/merge_requests/create_service.rb
@@ -12,7 +12,6 @@ module MergeRequests
merge_request.source_project = source_project
merge_request.source_branch = params[:source_branch]
merge_request.merge_params['force_remove_source_branch'] = params.delete(:force_remove_source_branch)
- merge_request.head_pipeline = head_pipeline_for(merge_request)
create(merge_request)
end
@@ -22,10 +21,16 @@ module MergeRequests
notification_service.new_merge_request(issuable, current_user)
todo_service.new_merge_request(issuable, current_user)
issuable.cache_merge_request_closes_issues!(current_user)
+ update_merge_requests_head_pipeline(issuable)
end
private
+ def update_merge_requests_head_pipeline(merge_request)
+ pipeline = head_pipeline_for(merge_request)
+ merge_request.update(head_pipeline_id: pipeline.id) if pipeline
+ end
+
def head_pipeline_for(merge_request)
return unless merge_request.source_project
diff --git a/app/views/ci/lints/show.html.haml b/app/views/ci/lints/show.html.haml
index dfbc7772698..e6408f35201 100644
--- a/app/views/ci/lints/show.html.haml
+++ b/app/views/ci/lints/show.html.haml
@@ -1,6 +1,6 @@
- page_title "CI Lint"
- page_description "Validate your GitLab CI configuration file"
-- content_for :page_specific_javascripts do
+- content_for :library_javascripts do
= page_specific_javascript_tag('lib/ace.js')
%h2 Check your .gitlab-ci.yml
diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml
index 6ad22958df3..3babdae3968 100644
--- a/app/views/layouts/_head.html.haml
+++ b/app/views/layouts/_head.html.haml
@@ -38,6 +38,9 @@
= Gon::Base.render_data
+ - if content_for?(:library_javascripts)
+ = yield :library_javascripts
+
= webpack_bundle_tag "webpack_runtime"
= webpack_bundle_tag "common"
= webpack_bundle_tag "locale"
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index bc3293fd100..b32cfe158bb 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -44,7 +44,7 @@
= icon('tachometer fw')
%li
= link_to assigned_issues_dashboard_path, title: 'Issues', aria: { label: "Issues" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
- = icon('hashtag fw')
+ = custom_icon('issues')
- issues_count = assigned_issuables_count(:issues)
%span.badge.issues-count{ class: ('hidden' if issues_count.zero?) }
= number_with_delimiter(issues_count)
diff --git a/app/views/layouts/header/_new.html.haml b/app/views/layouts/header/_new.html.haml
index 60940dba475..2c1c23d6ea9 100644
--- a/app/views/layouts/header/_new.html.haml
+++ b/app/views/layouts/header/_new.html.haml
@@ -38,7 +38,7 @@
= icon('tachometer fw')
%li
= link_to assigned_issues_dashboard_path, title: 'Issues', aria: { label: "Issues" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
- = icon('hashtag fw')
+ = custom_icon('issues')
- issues_count = assigned_issuables_count(:issues)
%span.badge.issues-count{ class: ('hidden' if issues_count.zero?) }
= number_with_delimiter(issues_count)
diff --git a/app/views/layouts/nav/_group.html.haml b/app/views/layouts/nav/_group.html.haml
index 8605380848d..261445ecd2b 100644
--- a/app/views/layouts/nav/_group.html.haml
+++ b/app/views/layouts/nav/_group.html.haml
@@ -25,7 +25,7 @@
%span
Members
- if current_user && can?(current_user, :admin_group, @group)
- = nav_link(path: %w[groups#projects groups#edit]) do
+ = nav_link(path: %w[groups#projects groups#edit ci_cd#show]) do
= link_to edit_group_path(@group), title: 'Settings' do
%span
Settings
diff --git a/app/views/layouts/nav/_new_admin_sidebar.html.haml b/app/views/layouts/nav/_new_admin_sidebar.html.haml
index e2f6e9c1aa2..54ea39a2d36 100644
--- a/app/views/layouts/nav/_new_admin_sidebar.html.haml
+++ b/app/views/layouts/nav/_new_admin_sidebar.html.haml
@@ -110,7 +110,7 @@
= nav_link(controller: :spam_logs) do
= link_to admin_spam_logs_path, title: "Spam Logs" do
.nav-icon-container
- = custom_icon('mr_bold')
+ = custom_icon('spam_logs')
%span.nav-item-name
Spam Logs
diff --git a/app/views/layouts/nav/_new_group_sidebar.html.haml b/app/views/layouts/nav/_new_group_sidebar.html.haml
index fdfd7e60732..33a83866cbf 100644
--- a/app/views/layouts/nav/_new_group_sidebar.html.haml
+++ b/app/views/layouts/nav/_new_group_sidebar.html.haml
@@ -85,6 +85,6 @@
Projects
= nav_link(controller: :ci_cd) do
- = link_to group_settings_ci_cd_path(@group), title: 'Pipelines' do
+ = link_to group_settings_ci_cd_path(@group), title: 'CI / CD' do
%span
- Pipelines
+ CI / CD
diff --git a/app/views/layouts/nav/_new_project_sidebar.html.haml b/app/views/layouts/nav/_new_project_sidebar.html.haml
index 9f1cb248c4e..673febbc798 100644
--- a/app/views/layouts/nav/_new_project_sidebar.html.haml
+++ b/app/views/layouts/nav/_new_project_sidebar.html.haml
@@ -76,7 +76,7 @@
= nav_link(controller: %w[projects/registry/repositories]) do
= link_to project_container_registry_index_path(@project), title: 'Container Registry', class: 'shortcuts-container-registry' do
.nav-icon-container
- = custom_icon('mr_bold')
+ = custom_icon('container_registry')
%span.nav-item-name
Registry
@@ -122,11 +122,11 @@
- if project_nav_tab? :pipelines
= nav_link(controller: [:pipelines, :builds, :jobs, :pipeline_schedules, :environments, :artifacts]) do
- = link_to project_pipelines_path(@project), title: 'Pipelines', class: 'shortcuts-pipelines' do
+ = link_to project_pipelines_path(@project), title: 'CI / CD', class: 'shortcuts-pipelines' do
.nav-icon-container
= custom_icon('pipeline')
%span.nav-item-name
- Pipelines
+ CI / CD
%ul.sidebar-sub-level-items
- if project_nav_tab? :pipelines
@@ -205,9 +205,9 @@
Repository
- if @project.feature_available?(:builds, current_user)
= nav_link(controller: :ci_cd) do
- = link_to project_settings_ci_cd_path(@project), title: 'Pipelines' do
+ = link_to project_settings_ci_cd_path(@project), title: 'CI / CD' do
%span
- Pipelines
+ CI / CD
- if Gitlab.config.pages.enabled
= nav_link(controller: :pages) do
= link_to project_pages_path(@project), title: 'Pages' do
diff --git a/app/views/projects/_merge_request_settings.html.haml b/app/views/projects/_merge_request_settings.html.haml
index 818010bc7d3..cc5afa943cf 100644
--- a/app/views/projects/_merge_request_settings.html.haml
+++ b/app/views/projects/_merge_request_settings.html.haml
@@ -1,8 +1,3 @@
- form = local_assigns.fetch(:form)
-%fieldset.features.merge-requests-feature.append-bottom-default
- %hr
- %h5.prepend-top-0
- Merge Requests
-
- = render 'projects/merge_request_merge_settings', form: form
+= render 'projects/merge_request_merge_settings', form: form
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index 087cb804449..20fceda26dc 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -1,12 +1,19 @@
+- page_title "General"
- @content_class = "limit-container-width" unless fluid_layout
+- expanded = Rails.env.test?
= render "projects/settings/head"
+
.project-edit-container
- .row.prepend-top-default
- .col-lg-4.profile-settings-sidebar
- %h4.prepend-top-0
- Project settings
- .col-lg-8
+ %section.settings.general-settings
+ .settings-header
+ %h4
+ General project settings
+ %button.btn.js-settings-toggle
+ = expanded ? 'Collapse' : 'Expand'
+ %p
+ Update your project name, description, avatar, and other general settings.
+ .settings-content.no-animate{ class: ('expanded' if expanded) }
.project-edit-errors
= form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "edit-project" }, authenticity_token: true do |f|
%fieldset
@@ -35,89 +42,7 @@
= f.label :tag_list, "Tags", class: 'label-light'
= f.text_field :tag_list, value: @project.tag_list.sort.join(', '), maxlength: 2000, class: "form-control"
%p.help-block Separate tags with commas.
- %hr
- %fieldset
- %h5.prepend-top-0
- Sharing &amp; Permissions
- .form_group.prepend-top-20.sharing-and-permissions
- .row.js-visibility-select
- .col-md-8
- .label-light
- = label_tag :project_visibility, 'Project Visibility', class: 'label-light', for: :project_visibility_level
- = link_to icon('question-circle'), help_page_path("public_access/public_access")
- %span.help-block
- .col-md-4.visibility-select-container
- = render('projects/visibility_select', model_method: :visibility_level, form: f, selected_level: @project.visibility_level)
- = f.fields_for :project_feature do |feature_fields|
- %fieldset.features
- .row
- .col-md-8.project-feature
- = feature_fields.label :repository_access_level, "Repository", class: 'label-light'
- %span.help-block View and edit files in this project
- .col-md-4.js-repo-access-level
- = project_feature_access_select(:repository_access_level)
-
- .row
- .col-md-8.project-feature.nested
- = feature_fields.label :merge_requests_access_level, "Merge requests", class: 'label-light'
- %span.help-block Submit changes to be merged upstream
- .col-md-4
- = project_feature_access_select(:merge_requests_access_level)
-
- .row
- .col-md-8.project-feature.nested
- = feature_fields.label :builds_access_level, "Pipelines", class: 'label-light'
- %span.help-block Build, test, and deploy your changes
- .col-md-4
- = project_feature_access_select(:builds_access_level)
-
- .row
- .col-md-8.project-feature
- = feature_fields.label :snippets_access_level, "Snippets", class: 'label-light'
- %span.help-block Share code pastes with others out of Git repository
- .col-md-4
- = project_feature_access_select(:snippets_access_level)
-
- .row
- .col-md-8.project-feature
- = feature_fields.label :issues_access_level, "Issues", class: 'label-light'
- %span.help-block Lightweight issue tracking system for this project
- .col-md-4
- = project_feature_access_select(:issues_access_level)
-
- .row
- .col-md-8.project-feature
- = feature_fields.label :wiki_access_level, "Wiki", class: 'label-light'
- %span.help-block Pages for project documentation
- .col-md-4
- = project_feature_access_select(:wiki_access_level)
- .form-group
- = render 'shared/allow_request_access', form: f
- - if Gitlab.config.lfs.enabled && current_user.admin?
- .row.js-lfs-enabled
- .col-md-8
- = f.label :lfs_enabled, 'LFS', class: 'label-light'
- %span.help-block
- Git Large File Storage
- = link_to icon('question-circle'), help_page_path('workflow/lfs/manage_large_binaries_with_git_lfs')
- .col-md-4
- .select-wrapper
- = f.select :lfs_enabled, [%w(Enabled true), %w(Disabled false)], {}, selected: @project.lfs_enabled?, class: 'pull-right form-control project-repo-select select-control', data: { field: 'lfs_enabled' }
- = icon('chevron-down')
- - if Gitlab.config.registry.enabled
- .form-group.js-container-registry{ style: ("display: none;" if @project.project_feature.send(:repository_access_level) == 0) }
- .checkbox
- = f.label :container_registry_enabled do
- = f.check_box :container_registry_enabled
- %strong Container Registry
- %br
- %span.descr Enable Container Registry for this project
- = link_to icon('question-circle'), help_page_path('user/project/container_registry'), target: '_blank'
-
- = render 'merge_request_settings', form: f
-
- %hr
- %fieldset.features.append-bottom-default
+ %fieldset.features
%h5.prepend-top-0
Project avatar
.form-group
@@ -137,41 +62,114 @@
= link_to 'Remove avatar', project_avatar_path(@project), data: { confirm: "Project avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-sm remove-avatar"
= f.submit 'Save changes', class: "btn btn-save"
- .row.prepend-top-default
- %hr
- .row.prepend-top-default
- .col-lg-4
- %h4.prepend-top-0
- Housekeeping
- %p.append-bottom-0
- %p
- Runs a number of housekeeping tasks within the current repository,
- such as compressing file revisions and removing unreachable objects.
- .col-lg-8
- = link_to 'Housekeeping', housekeeping_project_path(@project),
- method: :post, class: "btn btn-default"
- %hr
- .row.prepend-top-default
- .col-lg-4
- %h4.prepend-top-0
- Export project
- %p.append-bottom-0
- %p
- Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the "New Project" page.
- %p
- Once the exported file is ready, you will receive a notification email with a download link.
+ %section.settings.sharing-permissions
+ .settings-header
+ %h4
+ Sharing and permissions
+ %button.btn.js-settings-toggle
+ = expanded ? 'Collapse' : 'Expand'
+ %p
+ Enable or disable certain project features and choose access levels.
+ .settings-content.no-animate{ class: ('expanded' if expanded) }
+ = form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "sharing-permissions-form" }, authenticity_token: true do |f|
+ .form_group.sharing-and-permissions
+ .row.js-visibility-select
+ .col-md-8
+ .label-light
+ = label_tag :project_visibility, 'Project Visibility', class: 'label-light', for: :project_visibility_level
+ = link_to icon('question-circle'), help_page_path("public_access/public_access")
+ %span.help-block
+ .col-md-4.visibility-select-container
+ = render('projects/visibility_select', model_method: :visibility_level, form: f, selected_level: @project.visibility_level)
+ = f.fields_for :project_feature do |feature_fields|
+ %fieldset.features
+ .row
+ .col-md-8.project-feature
+ = feature_fields.label :repository_access_level, "Repository", class: 'label-light'
+ %span.help-block View and edit files in this project
+ .col-md-4.js-repo-access-level
+ = project_feature_access_select(:repository_access_level)
- .col-lg-8
+ .row
+ .col-md-8.project-feature.nested
+ = feature_fields.label :merge_requests_access_level, "Merge requests", class: 'label-light'
+ %span.help-block Submit changes to be merged upstream
+ .col-md-4
+ = project_feature_access_select(:merge_requests_access_level)
- - if @project.export_project_path
- = link_to 'Download export', download_export_project_path(@project),
- rel: 'nofollow', download: '', method: :get, class: "btn btn-default"
- = link_to 'Generate new export', generate_new_export_project_path(@project),
- method: :post, class: "btn btn-default"
- - else
- = link_to 'Export project', export_project_path(@project),
- method: :post, class: "btn btn-default"
+ .row
+ .col-md-8.project-feature.nested
+ = feature_fields.label :builds_access_level, "Pipelines", class: 'label-light'
+ %span.help-block Build, test, and deploy your changes
+ .col-md-4
+ = project_feature_access_select(:builds_access_level)
+
+ .row
+ .col-md-8.project-feature
+ = feature_fields.label :snippets_access_level, "Snippets", class: 'label-light'
+ %span.help-block Share code pastes with others out of Git repository
+ .col-md-4
+ = project_feature_access_select(:snippets_access_level)
+
+ .row
+ .col-md-8.project-feature
+ = feature_fields.label :issues_access_level, "Issues", class: 'label-light'
+ %span.help-block Lightweight issue tracking system for this project
+ .col-md-4
+ = project_feature_access_select(:issues_access_level)
+
+ .row
+ .col-md-8.project-feature
+ = feature_fields.label :wiki_access_level, "Wiki", class: 'label-light'
+ %span.help-block Pages for project documentation
+ .col-md-4
+ = project_feature_access_select(:wiki_access_level)
+ .form-group
+ = render 'shared/allow_request_access', form: f
+ - if Gitlab.config.lfs.enabled && current_user.admin?
+ .row.js-lfs-enabled.form-group.sharing-and-permissions
+ .col-md-8
+ = f.label :lfs_enabled, 'Git Large File Storage', class: 'label-light'
+ = link_to icon('question-circle'), help_page_path('workflow/lfs/manage_large_binaries_with_git_lfs')
+ %span.help-block Manages large files such as audio, video and graphics files.
+ .col-md-4
+ .select-wrapper
+ = f.select :lfs_enabled, [%w(Enabled true), %w(Disabled false)], {}, selected: @project.lfs_enabled?, class: 'pull-right form-control project-repo-select select-control', data: { field: 'lfs_enabled' }
+ = icon('chevron-down')
+ - if Gitlab.config.registry.enabled
+ .form-group.js-container-registry{ style: ("display: none;" if @project.project_feature.send(:repository_access_level) == 0) }
+ .checkbox
+ = f.label :container_registry_enabled do
+ = f.check_box :container_registry_enabled
+ %strong Container Registry
+ %br
+ %span.descr Enable Container Registry for this project
+ = link_to icon('question-circle'), help_page_path('user/project/container_registry'), target: '_blank'
+ = f.submit 'Save changes', class: "btn btn-save"
+
+
+ %section.settings.merge-requests-feature{ style: ("display: none;" if @project.project_feature.send(:merge_requests_access_level) == 0) }
+ .settings-header
+ %h4
+ Merge request settings
+ %button.btn.js-settings-toggle
+ = expanded ? 'Collapse' : 'Expand'
+ %p
+ Customize your merge request restrictions.
+ .settings-content.no-animate{ class: ('expanded' if expanded) }
+ = form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "merge-request-settings-form" }, authenticity_token: true do |f|
+ = render 'merge_request_settings', form: f
+ = f.submit 'Save changes', class: "btn btn-save"
+ %section.settings
+ .settings-header
+ %h4
+ Export project
+ %button.btn.js-settings-toggle
+ = expanded ? 'Collapse' : 'Expand'
+ %p
+ Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the "New Project" page.
+ .settings-content.no-animate{ class: ('expanded' if expanded) }
.bs-callout.bs-callout-info
%p.append-bottom-0
%p
@@ -189,110 +187,117 @@
%li Container registry images
%li CI variables
%li Any encrypted tokens
- - if can? current_user, :archive_project, @project
- %hr
- .row.prepend-top-default
- .col-lg-4
- %h4.warning-title.prepend-top-0
- - if @project.archived?
- Unarchive project
- - else
- Archive project
- %p.append-bottom-0
+ %p
+ Once the exported file is ready, you will receive a notification email with a download link.
+ - if @project.export_project_path
+ = link_to 'Download export', download_export_project_path(@project),
+ rel: 'nofollow', download: '', method: :get, class: "btn btn-default"
+ = link_to 'Generate new export', generate_new_export_project_path(@project),
+ method: :post, class: "btn btn-default"
+ - else
+ = link_to 'Export project', export_project_path(@project),
+ method: :post, class: "btn btn-default"
+
+ %section.settings.advanced-settings
+ .settings-header
+ %h4
+ Advanced settings
+ %button.btn.js-settings-toggle
+ = expanded ? 'Collapse' : 'Expand'
+ %p
+ Perform advanced options such as housekeeping, exporting, archiveing, renameing, transfering, or removeing your project.
+ .settings-content.no-animate{ class: ('expanded' if expanded) }
+ .sub-section
+ %h4 Housekeeping
+ %p
+ Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects.
+ = link_to 'Run housekeeping', housekeeping_project_path(@project),
+ method: :post, class: "btn btn-default"
+ - if can? current_user, :archive_project, @project
+ .sub-section
+ %h4.warning-title
+ - if @project.archived?
+ Unarchive project
+ - else
+ Archive project
- if @project.archived?
- Unarchiving the project will mark its repository as active. The project can be committed to.
+ %p
+ Unarchiving the project will mark its repository as active. The project can be committed to.
+ %strong Once active this project shows up in the search and on the dashboard.
+ = link_to 'Unarchive project', unarchive_project_path(@project),
+ data: { confirm: "Are you sure that you want to unarchive this project?\nWhen this project is unarchived it is active and can be committed to again." },
+ method: :post, class: "btn btn-success"
- else
- Archiving the project will mark its repository as read-only. It is hidden from the dashboard and doesn't show up in searches.
- .col-lg-8
- - if @project.archived?
- %p
- %strong Once active this project shows up in the search and on the dashboard.
- = link_to 'Unarchive project', unarchive_project_path(@project),
- data: { confirm: "Are you sure that you want to unarchive this project?\nWhen this project is unarchived it is active and can be committed to again." },
- method: :post, class: "btn btn-success"
- - else
- %p
- %strong Archived projects cannot be committed to!
- = link_to 'Archive project', archive_project_path(@project),
- data: { confirm: "Are you sure that you want to archive this project?\nAn archived project cannot be committed to." },
- method: :post, class: "btn btn-warning"
- %hr
- .row.prepend-top-default
- .col-lg-4
- %h4.prepend-top-0.warning-title
- Rename repository
- .col-lg-8
- = render 'projects/errors'
- = form_for([@project.namespace.becomes(Namespace), @project]) do |f|
- .form-group.project_name_holder
- = f.label :name, class: 'label-light' do
- Project name
- .form-group
- = f.text_field :name, class: "form-control"
- .form-group
- = f.label :path, class: 'label-light' do
- %span Path
- .form-group
- .input-group
- .input-group-addon
- #{URI.join(root_url, @project.namespace.full_path)}/
- = f.text_field :path, class: 'form-control'
- %ul
- %li Be careful. Renaming a project's repository can have unintended side effects.
- %li You will need to update your local repositories to point to the new location.
- - if @project.deployment_services.any?
- %li Your deployment services will be broken, you will need to manually fix the services after renaming.
- = f.submit 'Rename project', class: "btn btn-warning"
- - if can?(current_user, :change_namespace, @project)
- %hr
- .row.prepend-top-default
- .col-lg-4
- %h4.prepend-top-0.danger-title
- Transfer project to new group
- %p.append-bottom-0
- Please select the group you want to transfer this project to in the dropdown to the right.
- .col-lg-8
- = form_for([@project.namespace.becomes(Namespace), @project], url: transfer_project_path(@project), method: :put, remote: true, html: { class: 'js-project-transfer-form' } ) do |f|
+ %p
+ Archiving the project will mark its repository as read-only. It is hidden from the dashboard and doesn't show up in searches.
+ %strong Archived projects cannot be committed to!
+ = link_to 'Archive project', archive_project_path(@project),
+ data: { confirm: "Are you sure that you want to archive this project?\nAn archived project cannot be committed to." },
+ method: :post, class: "btn btn-warning"
+ .sub-section.rename-respository
+ %h4.warning-title
+ Rename repository
+ %p
+ Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the "New Project" page.
+ = render 'projects/errors'
+ = form_for([@project.namespace.becomes(Namespace), @project]) do |f|
+ .form-group.project_name_holder
+ = f.label :name, class: 'label-light' do
+ Project name
+ .form-group
+ = f.text_field :name, class: "form-control"
.form-group
- = label_tag :new_namespace_id, nil, class: 'label-light' do
- %span Select a new namespace
+ = f.label :path, class: 'label-light' do
+ %span Path
.form-group
- = select_tag :new_namespace_id, namespaces_options(nil), include_blank: true, class: 'select2'
+ .input-group
+ .input-group-addon
+ #{URI.join(root_url, @project.namespace.full_path)}/
+ = f.text_field :path, class: 'form-control'
%ul
- %li Be careful. Changing the project's namespace can have unintended side effects.
- %li You can only transfer the project to namespaces you manage.
+ %li Be careful. Renaming a project's repository can have unintended side effects.
%li You will need to update your local repositories to point to the new location.
- %li Project visibility level will be changed to match namespace rules when transfering to a group.
- = f.submit 'Transfer project', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => transfer_project_message(@project) }
- - if @project.forked? && can?(current_user, :remove_fork_project, @project)
- %hr
- .row.prepend-top-default.append-bottom-default
- .col-lg-4
- %h4.prepend-top-0.danger-title
- Remove fork relationship
- %p.append-bottom-0
+ - if @project.deployment_services.any?
+ %li Your deployment services will be broken, you will need to manually fix the services after renaming.
+ = f.submit 'Rename project', class: "btn btn-warning"
+ - if can?(current_user, :change_namespace, @project)
+ .sub-section
+ %h4.danger-title
+ Transfer project
+ = form_for([@project.namespace.becomes(Namespace), @project], url: transfer_project_path(@project), method: :put, remote: true, html: { class: 'js-project-transfer-form' } ) do |f|
+ .form-group
+ = label_tag :new_namespace_id, nil, class: 'label-light' do
+ %span Select a new namespace
+ .form-group
+ = select_tag :new_namespace_id, namespaces_options(nil), include_blank: true, class: 'select2'
+ %ul
+ %li Be careful. Changing the project's namespace can have unintended side effects.
+ %li You can only transfer the project to namespaces you manage.
+ %li You will need to update your local repositories to point to the new location.
+ %li Project visibility level will be changed to match namespace rules when transfering to a group.
+ = f.submit 'Transfer project', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => transfer_project_message(@project) }
+ - if @project.forked? && can?(current_user, :remove_fork_project, @project)
+ .sub-section
+ %h4.danger-title
+ Remove fork relationship
%p
This will remove the fork relationship to source project
= succeed "." do
= link_to @project.forked_from_project.name_with_namespace, project_path(@project.forked_from_project)
- .col-lg-8
- = form_for([@project.namespace.becomes(Namespace), @project], url: remove_fork_project_path(@project), method: :delete, remote: true, html: { class: 'transfer-project' }) do |f|
- %p
- %strong Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source.
- = button_to 'Remove fork relationship', '#', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => remove_fork_project_message(@project) }
- - if can?(current_user, :remove_project, @project)
- %hr
- .row.prepend-top-default.append-bottom-default
- .col-lg-4
- %h4.prepend-top-0.danger-title
- Remove project
- %p.append-bottom-0
- Removing the project will delete its repository and all related resources including issues, merge requests etc.
- .col-lg-8
- = form_tag(project_path(@project), method: :delete) do
+ = form_for([@project.namespace.becomes(Namespace), @project], url: remove_fork_project_path(@project), method: :delete, remote: true, html: { class: 'transfer-project' }) do |f|
+ %p
+ %strong Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source.
+ = button_to 'Remove fork relationship', '#', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => remove_fork_project_message(@project) }
+ - if can?(current_user, :remove_project, @project)
+ .sub-section
+ %h4.danger-title
+ Remove project
%p
- %strong Removed projects cannot be restored!
- = button_to 'Remove project', '#', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => remove_project_message(@project) }
+ Removing the project will delete its repository and all related resources including issues, merge requests etc.
+ = form_tag(project_path(@project), method: :delete) do
+ %p
+ %strong Removed projects cannot be restored!
+ = button_to 'Remove project', '#', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => remove_project_message(@project) }
.save-project-loader.hide
.center
diff --git a/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml b/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml
index 7343d6e039c..bd8c38292d6 100644
--- a/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml
+++ b/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml
@@ -15,7 +15,7 @@
- else
= s_("PipelineSchedules|None")
%td.next-run-cell
- - if pipeline_schedule.active?
+ - if pipeline_schedule.active? && pipeline_schedule.next_run_at
= time_ago_with_tooltip(pipeline_schedule.real_next_run)
- else
= s_("PipelineSchedules|Inactive")
diff --git a/app/views/projects/runners/edit.html.haml b/app/views/projects/runners/edit.html.haml
index 95706888655..78dc4817ed7 100644
--- a/app/views/projects/runners/edit.html.haml
+++ b/app/views/projects/runners/edit.html.haml
@@ -3,4 +3,4 @@
%h4 Runner ##{@runner.id}
%hr
- = render 'form', runner: @runner, runner_form_url: runner_path(@runner)
+ = render 'form', runner: @runner, runner_form_url: runner_path(@runner)
diff --git a/app/views/shared/icons/_container_registry.svg b/app/views/shared/icons/_container_registry.svg
new file mode 100644
index 00000000000..56d62aab670
--- /dev/null
+++ b/app/views/shared/icons/_container_registry.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="m16 11.764v-8.764c0-1.657-1.343-3-3-3h-10c-1.657 0-3 1.343-3 3v8.764c.531-.475 1.232-.764 2-.764v-8c0-.552.448-1 1-1h10c.552 0 1 .448 1 1v8c.768 0 1.469.289 2 .764m-14 .236h12c1.105 0 2 .895 2 2 0 1.105-.895 2-2 2h-12c-1.105 0-2-.895-2-2 0-1.105.895-2 2-2m10 1c-.552 0-1 .448-1 1 0 .552.448 1 1 1 .552 0 1-.448 1-1 0-.552-.448-1-1-1"/></svg>
diff --git a/app/views/shared/icons/_spam_logs.svg b/app/views/shared/icons/_spam_logs.svg
new file mode 100644
index 00000000000..80ee0eb3856
--- /dev/null
+++ b/app/views/shared/icons/_spam_logs.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M8.75.433l5.428 3.134a1.5 1.5 0 0 1 .75 1.299v6.268a1.5 1.5 0 0 1-.75 1.299L8.75 15.567a1.5 1.5 0 0 1-1.5 0l-5.428-3.134a1.5 1.5 0 0 1-.75-1.299V4.866a1.5 1.5 0 0 1 .75-1.299L7.25.433a1.5 1.5 0 0 1 1.5 0zM3.072 5.155v5.69L8 13.691l4.928-2.846v-5.69L8 2.309 3.072 5.155zM8 4a1 1 0 0 1 1 1v3a1 1 0 1 1-2 0V5a1 1 0 0 1 1-1zm0 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></svg>
diff --git a/app/views/shared/milestones/_sidebar.html.haml b/app/views/shared/milestones/_sidebar.html.haml
index 895fb8247b5..66ac8196f2f 100644
--- a/app/views/shared/milestones/_sidebar.html.haml
+++ b/app/views/shared/milestones/_sidebar.html.haml
@@ -67,7 +67,7 @@
.block.issues
.sidebar-collapsed-icon
%strong
- = icon('hashtag', 'aria-hidden': 'true')
+ = custom_icon('issues')
%span= milestone.issues_visible_to_user(current_user).count
.title.hide-collapsed
Issues
diff --git a/app/views/users/calendar_activities.html.haml b/app/views/users/calendar_activities.html.haml
index 805a346a85e..6b1d75c6e72 100644
--- a/app/views/users/calendar_activities.html.haml
+++ b/app/views/users/calendar_activities.html.haml
@@ -1,6 +1,6 @@
%h4.prepend-top-20
Contributions for
- %strong= @calendar_date.to_s(:short)
+ %strong= @calendar_date.to_s(:medium)
- if @events.any?
%ul.bordered-list
@@ -8,7 +8,7 @@
%li
%span.light
%i.fa.fa-clock-o
- = event.created_at.to_s(:time)
+ = event.created_at.strftime('%-I:%M%P')
- if event.push?
#{event.action_name} #{event.ref_type}
%strong
@@ -30,4 +30,4 @@
= event.project_name
- else
%p
- No contributions found for #{@calendar_date.to_s(:short)}
+ No contributions found for #{@calendar_date.to_s(:medium)}
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index a449706c567..879e0f99b14 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -104,7 +104,7 @@
.tab-content
#activity.tab-pane
.row-content-block.calender-block.white.second-block.hidden-xs
- .user-calendar{ data: { calendar_path: user_calendar_path(@user, :json), calendar_activities_path: user_calendar_activities_path } }
+ .user-calendar{ data: { calendar_path: user_calendar_path(@user, :json), calendar_activities_path: user_calendar_activities_path, utc_offset: Time.zone.utc_offset } }
%h4.center.light
%i.fa.fa-spinner.fa-spin
.user-calendar-activities