summaryrefslogtreecommitdiff
path: root/app/assets
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets')
-rw-r--r--app/assets/javascripts/activities.js.es63
-rw-r--r--app/assets/javascripts/boards/components/board_card.js.es63
-rw-r--r--app/assets/javascripts/boards/components/board_list.js.es69
-rw-r--r--app/assets/javascripts/boards/models/list.js.es68
-rw-r--r--app/assets/javascripts/boards/stores/boards_store.js.es64
-rw-r--r--app/assets/javascripts/build.js2
-rw-r--r--app/assets/javascripts/commits.js6
-rw-r--r--app/assets/javascripts/cycle_analytics/components/stage_code_component.js.es62
-rw-r--r--app/assets/javascripts/cycle_analytics/components/stage_issue_component.js.es62
-rw-r--r--app/assets/javascripts/cycle_analytics/components/stage_plan_component.js.es62
-rw-r--r--app/assets/javascripts/cycle_analytics/components/stage_production_component.js.es62
-rw-r--r--app/assets/javascripts/cycle_analytics/components/stage_review_component.js.es62
-rw-r--r--app/assets/javascripts/cycle_analytics/components/stage_staging_component.js.es62
-rw-r--r--app/assets/javascripts/cycle_analytics/components/stage_test_component.js.es62
-rw-r--r--app/assets/javascripts/cycle_analytics/components/total_time_component.js.es615
-rw-r--r--app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js.es64
-rw-r--r--app/assets/javascripts/cycle_analytics/cycle_analytics_store.js.es68
-rw-r--r--app/assets/javascripts/diff_notes/models/discussion.js.es69
-rw-r--r--app/assets/javascripts/dispatcher.js.es63
-rw-r--r--app/assets/javascripts/due_date_select.js.es622
-rw-r--r--app/assets/javascripts/environments/components/environment.js.es623
-rw-r--r--app/assets/javascripts/environments/components/environment_item.js.es67
-rw-r--r--app/assets/javascripts/extensions/array.js8
-rw-r--r--app/assets/javascripts/extensions/array.js.es624
-rw-r--r--app/assets/javascripts/extensions/element.js.es62
-rw-r--r--app/assets/javascripts/gfm_auto_complete.js.es634
-rw-r--r--app/assets/javascripts/labels_select.js2
-rw-r--r--app/assets/javascripts/lib/utils/custom_event_polyfill.js.es612
-rw-r--r--app/assets/javascripts/lib/utils/datetime_utility.js8
-rw-r--r--app/assets/javascripts/lib/utils/pretty_time.js.es667
-rw-r--r--app/assets/javascripts/lib/utils/timeago.js239
-rw-r--r--app/assets/javascripts/logo.js2
-rw-r--r--app/assets/javascripts/merge_request_widget.js.es66
-rw-r--r--app/assets/javascripts/notes.js5
-rw-r--r--app/assets/javascripts/profile/profile.js.es61
-rw-r--r--app/assets/javascripts/project_variables.js.es643
-rw-r--r--app/assets/javascripts/smart_interval.js.es6130
-rw-r--r--app/assets/javascripts/subbable_resource.js.es654
-rw-r--r--app/assets/javascripts/tree.js1
-rw-r--r--app/assets/javascripts/users/calendar.js1
-rw-r--r--app/assets/stylesheets/framework/avatar.scss1
-rw-r--r--app/assets/stylesheets/framework/blocks.scss29
-rw-r--r--app/assets/stylesheets/framework/buttons.scss26
-rw-r--r--app/assets/stylesheets/framework/common.scss4
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss85
-rw-r--r--app/assets/stylesheets/framework/forms.scss41
-rw-r--r--app/assets/stylesheets/framework/issue_box.scss4
-rw-r--r--app/assets/stylesheets/framework/nav.scss51
-rw-r--r--app/assets/stylesheets/framework/variables.scss84
-rw-r--r--app/assets/stylesheets/mailers/highlighted_diff_email.scss (renamed from app/assets/stylesheets/mailers/repository_push_email.scss)0
-rw-r--r--app/assets/stylesheets/pages/boards.scss2
-rw-r--r--app/assets/stylesheets/pages/environments.scss25
-rw-r--r--app/assets/stylesheets/pages/icons.scss53
-rw-r--r--app/assets/stylesheets/pages/issuable.scss16
-rw-r--r--app/assets/stylesheets/pages/merge_requests.scss39
-rw-r--r--app/assets/stylesheets/pages/notes.scss43
-rw-r--r--app/assets/stylesheets/pages/pipelines.scss17
-rw-r--r--app/assets/stylesheets/pages/projects.scss8
-rw-r--r--app/assets/stylesheets/pages/settings.scss4
-rw-r--r--app/assets/stylesheets/pages/status.scss98
60 files changed, 879 insertions, 530 deletions
diff --git a/app/assets/javascripts/activities.js.es6 b/app/assets/javascripts/activities.js.es6
index 19bcfef89fb..648cb4d5d85 100644
--- a/app/assets/javascripts/activities.js.es6
+++ b/app/assets/javascripts/activities.js.es6
@@ -1,5 +1,6 @@
/* eslint-disable no-param-reassign, class-methods-use-this */
-/* global Pager, Cookies */
+/* global Pager */
+/* global Cookies */
((global) => {
class Activities {
diff --git a/app/assets/javascripts/boards/components/board_card.js.es6 b/app/assets/javascripts/boards/components/board_card.js.es6
index b1afbe7d97e..2299dafd217 100644
--- a/app/assets/javascripts/boards/components/board_card.js.es6
+++ b/app/assets/javascripts/boards/components/board_card.js.es6
@@ -54,6 +54,9 @@
mouseDown () {
this.showDetail = true;
},
+ mouseMove() {
+ this.showDetail = false;
+ },
showIssue (e) {
const targetTagName = e.target.tagName.toLowerCase();
diff --git a/app/assets/javascripts/boards/components/board_list.js.es6 b/app/assets/javascripts/boards/components/board_list.js.es6
index 379f4f0d72b..43ebeef39c4 100644
--- a/app/assets/javascripts/boards/components/board_list.js.es6
+++ b/app/assets/javascripts/boards/components/board_list.js.es6
@@ -80,6 +80,7 @@
},
mounted () {
const options = gl.issueBoards.getBoardSortableDefaultOptions({
+ scroll: document.querySelectorAll('.boards-list')[0],
group: 'issues',
sort: false,
disabled: this.disabled,
@@ -88,18 +89,16 @@
const card = this.$refs.issue[e.oldIndex];
card.showDetail = false;
- Store.moving.issue = card.issue;
Store.moving.list = card.list;
+ Store.moving.issue = Store.moving.list.findIssue(+e.item.dataset.issueId);
gl.issueBoards.onStart();
},
onAdd: (e) => {
- // Add the element back to original list to allow Vue to handle DOM updates
- e.from.appendChild(e.item);
+ gl.issueBoards.BoardsStore.moveIssueToList(Store.moving.list, this.list, Store.moving.issue, e.newIndex);
this.$nextTick(() => {
- // Update the issues once we know the element has been moved
- gl.issueBoards.BoardsStore.moveIssueToList(Store.moving.list, this.list, Store.moving.issue);
+ e.item.remove();
});
},
});
diff --git a/app/assets/javascripts/boards/models/list.js.es6 b/app/assets/javascripts/boards/models/list.js.es6
index 8a7dc67409e..429bd27c3fb 100644
--- a/app/assets/javascripts/boards/models/list.js.es6
+++ b/app/assets/javascripts/boards/models/list.js.es6
@@ -106,9 +106,13 @@ class List {
});
}
- addIssue (issue, listFrom) {
+ addIssue (issue, listFrom, newIndex) {
if (!this.findIssue(issue.id)) {
- this.issues.push(issue);
+ if (newIndex !== undefined) {
+ this.issues.splice(newIndex, 0, issue);
+ } else {
+ this.issues.push(issue);
+ }
if (this.label) {
issue.addLabel(this.label);
diff --git a/app/assets/javascripts/boards/stores/boards_store.js.es6 b/app/assets/javascripts/boards/stores/boards_store.js.es6
index 6bc95aa60f2..bb2a4de8b18 100644
--- a/app/assets/javascripts/boards/stores/boards_store.js.es6
+++ b/app/assets/javascripts/boards/stores/boards_store.js.es6
@@ -89,14 +89,14 @@
});
listFrom.update();
},
- moveIssueToList (listFrom, listTo, issue) {
+ moveIssueToList (listFrom, listTo, issue, newIndex) {
const issueTo = listTo.findIssue(issue.id),
issueLists = issue.getLists(),
listLabels = issueLists.map( listIssue => listIssue.label );
// Add to new lists issues if it doesn't already exist
if (!issueTo) {
- listTo.addIssue(issue, listFrom);
+ listTo.addIssue(issue, listFrom, newIndex);
}
if (listTo.type === 'done' && listFrom.type !== 'backlog') {
diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js
index e198306e67a..116a47b0907 100644
--- a/app/assets/javascripts/build.js
+++ b/app/assets/javascripts/build.js
@@ -12,7 +12,7 @@
this.pageUrl = options.pageUrl;
this.buildUrl = options.buildUrl;
this.buildStatus = options.buildStatus;
- this.state = options.state1;
+ this.state = options.logState;
this.buildStage = options.buildStage;
this.updateDropdown = bind(this.updateDropdown, this);
this.$document = $(document);
diff --git a/app/assets/javascripts/commits.js b/app/assets/javascripts/commits.js
index 951fb338f9d..3627aaf5080 100644
--- a/app/assets/javascripts/commits.js
+++ b/app/assets/javascripts/commits.js
@@ -1,4 +1,4 @@
-/* eslint-disable func-names, space-before-function-paren, wrap-iife, quotes, consistent-return, no-undef, no-return-assign, no-param-reassign, one-var, no-var, one-var-declaration-per-line, no-unused-vars, prefer-template, object-shorthand, comma-dangle, padded-blocks, max-len */
+/* eslint-disable func-names, space-before-function-paren, wrap-iife, quotes, consistent-return, no-undef, no-return-assign, no-param-reassign, one-var, no-var, one-var-declaration-per-line, no-unused-vars, prefer-template, object-shorthand, comma-dangle, padded-blocks, max-len, prefer-arrow-callback */
(function() {
this.CommitsList = (function() {
function CommitsList() {}
@@ -13,7 +13,9 @@
return false;
}
});
- Pager.init(limit, false);
+ Pager.init(limit, false, false, function() {
+ gl.utils.localTimeAgo($('.js-timeago'));
+ });
this.content = $("#commits-list");
this.searchField = $("#commits-search");
return this.initSearch();
diff --git a/app/assets/javascripts/cycle_analytics/components/stage_code_component.js.es6 b/app/assets/javascripts/cycle_analytics/components/stage_code_component.js.es6
index 520cee7738b..b83a4c63fad 100644
--- a/app/assets/javascripts/cycle_analytics/components/stage_code_component.js.es6
+++ b/app/assets/javascripts/cycle_analytics/components/stage_code_component.js.es6
@@ -1,4 +1,6 @@
/* eslint-disable no-param-reassign */
+/* global Vue */
+
((global) => {
global.cycleAnalytics = global.cycleAnalytics || {};
diff --git a/app/assets/javascripts/cycle_analytics/components/stage_issue_component.js.es6 b/app/assets/javascripts/cycle_analytics/components/stage_issue_component.js.es6
index 3bb01c67206..cb1687dcc7a 100644
--- a/app/assets/javascripts/cycle_analytics/components/stage_issue_component.js.es6
+++ b/app/assets/javascripts/cycle_analytics/components/stage_issue_component.js.es6
@@ -1,4 +1,6 @@
/* eslint-disable no-param-reassign */
+/* global Vue */
+
((global) => {
global.cycleAnalytics = global.cycleAnalytics || {};
diff --git a/app/assets/javascripts/cycle_analytics/components/stage_plan_component.js.es6 b/app/assets/javascripts/cycle_analytics/components/stage_plan_component.js.es6
index b568ab62a69..513298ba4e7 100644
--- a/app/assets/javascripts/cycle_analytics/components/stage_plan_component.js.es6
+++ b/app/assets/javascripts/cycle_analytics/components/stage_plan_component.js.es6
@@ -1,4 +1,6 @@
/* eslint-disable no-param-reassign */
+/* global Vue */
+
((global) => {
global.cycleAnalytics = global.cycleAnalytics || {};
diff --git a/app/assets/javascripts/cycle_analytics/components/stage_production_component.js.es6 b/app/assets/javascripts/cycle_analytics/components/stage_production_component.js.es6
index a6b6d817a82..73f4205b578 100644
--- a/app/assets/javascripts/cycle_analytics/components/stage_production_component.js.es6
+++ b/app/assets/javascripts/cycle_analytics/components/stage_production_component.js.es6
@@ -1,4 +1,6 @@
/* eslint-disable no-param-reassign */
+/* global Vue */
+
((global) => {
global.cycleAnalytics = global.cycleAnalytics || {};
diff --git a/app/assets/javascripts/cycle_analytics/components/stage_review_component.js.es6 b/app/assets/javascripts/cycle_analytics/components/stage_review_component.js.es6
index 9e819c1d420..501ffb1fac9 100644
--- a/app/assets/javascripts/cycle_analytics/components/stage_review_component.js.es6
+++ b/app/assets/javascripts/cycle_analytics/components/stage_review_component.js.es6
@@ -1,4 +1,6 @@
/* eslint-disable no-param-reassign */
+/* global Vue */
+
((global) => {
global.cycleAnalytics = global.cycleAnalytics || {};
diff --git a/app/assets/javascripts/cycle_analytics/components/stage_staging_component.js.es6 b/app/assets/javascripts/cycle_analytics/components/stage_staging_component.js.es6
index b30c3a31010..82622232f64 100644
--- a/app/assets/javascripts/cycle_analytics/components/stage_staging_component.js.es6
+++ b/app/assets/javascripts/cycle_analytics/components/stage_staging_component.js.es6
@@ -1,4 +1,6 @@
/* eslint-disable no-param-reassign */
+/* global Vue */
+
((global) => {
global.cycleAnalytics = global.cycleAnalytics || {};
diff --git a/app/assets/javascripts/cycle_analytics/components/stage_test_component.js.es6 b/app/assets/javascripts/cycle_analytics/components/stage_test_component.js.es6
index c54d6b6ee37..4bfd363a1f1 100644
--- a/app/assets/javascripts/cycle_analytics/components/stage_test_component.js.es6
+++ b/app/assets/javascripts/cycle_analytics/components/stage_test_component.js.es6
@@ -1,4 +1,6 @@
/* eslint-disable no-param-reassign */
+/* global Vue */
+
((global) => {
global.cycleAnalytics = global.cycleAnalytics || {};
diff --git a/app/assets/javascripts/cycle_analytics/components/total_time_component.js.es6 b/app/assets/javascripts/cycle_analytics/components/total_time_component.js.es6
index 8403fbeaab5..0d85e1a4678 100644
--- a/app/assets/javascripts/cycle_analytics/components/total_time_component.js.es6
+++ b/app/assets/javascripts/cycle_analytics/components/total_time_component.js.es6
@@ -1,4 +1,6 @@
/* eslint-disable no-param-reassign */
+/* global Vue */
+
((global) => {
global.cycleAnalytics = global.cycleAnalytics || {};
@@ -8,10 +10,15 @@
},
template: `
<span class="total-time">
- <template v-if="time.days">{{ time.days }} <span>{{ time.days === 1 ? 'day' : 'days' }}</span></template>
- <template v-if="time.hours">{{ time.hours }} <span>hr</span></template>
- <template v-if="time.mins && !time.days">{{ time.mins }} <span>mins</span></template>
- <template v-if="time.seconds && Object.keys(time).length === 1 || time.seconds === 0">{{ time.seconds }} <span>s</span></template>
+ <template v-if="Object.keys(time).length">
+ <template v-if="time.days">{{ time.days }} <span>{{ time.days === 1 ? 'day' : 'days' }}</span></template>
+ <template v-if="time.hours">{{ time.hours }} <span>hr</span></template>
+ <template v-if="time.mins && !time.days">{{ time.mins }} <span>mins</span></template>
+ <template v-if="time.seconds && Object.keys(time).length === 1 || time.seconds === 0">{{ time.seconds }} <span>s</span></template>
+ </template>
+ <template v-else>
+ --
+ </template>
</span>
`,
});
diff --git a/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js.es6 b/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js.es6
index f1ddd139c48..2f810a69758 100644
--- a/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js.es6
+++ b/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js.es6
@@ -1,3 +1,7 @@
+/* global Vue */
+/* global Cookies */
+/* global Flash */
+
//= require vue
//= require_tree ./svg
//= require_tree .
diff --git a/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js.es6 b/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js.es6
index 9b905874167..be732971c7f 100644
--- a/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js.es6
+++ b/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js.es6
@@ -62,9 +62,11 @@
this.state.events = this.decorateEvents(events);
},
decorateEvents(events) {
- const newEvents = events;
+ const newEvents = [];
+
+ events.forEach((item) => {
+ if (!item) return;
- newEvents.forEach((item) => {
item.totalTime = item.total_time;
item.author.webUrl = item.author.web_url;
item.author.avatarUrl = item.author.avatar_url;
@@ -79,6 +81,8 @@
delete item.created_at;
delete item.short_sha;
delete item.commit_url;
+
+ newEvents.push(item);
});
return newEvents;
diff --git a/app/assets/javascripts/diff_notes/models/discussion.js.es6 b/app/assets/javascripts/diff_notes/models/discussion.js.es6
index 439f55520ef..badcdccc840 100644
--- a/app/assets/javascripts/diff_notes/models/discussion.js.es6
+++ b/app/assets/javascripts/diff_notes/models/discussion.js.es6
@@ -57,14 +57,17 @@ class DiscussionModel {
}
updateHeadline (data) {
- const $discussionHeadline = $(`.discussion[data-discussion-id="${this.id}"] .js-discussion-headline`);
+ const discussionSelector = `.discussion[data-discussion-id="${this.id}"]`;
+ const $discussionHeadline = $(`${discussionSelector} .js-discussion-headline`);
if (data.discussion_headline_html) {
if ($discussionHeadline.length) {
$discussionHeadline.replaceWith(data.discussion_headline_html);
} else {
- $(`.discussion[data-discussion-id="${this.id}"] .discussion-header`).append(data.discussion_headline_html);
+ $(`${discussionSelector} .discussion-header`).append(data.discussion_headline_html);
}
+
+ gl.utils.localTimeAgo($('.js-timeago', `${discussionSelector}`));
} else {
$discussionHeadline.remove();
}
@@ -74,7 +77,7 @@ class DiscussionModel {
if (!this.canResolve) {
return false;
}
-
+
for (const noteId in this.notes) {
const note = this.notes[noteId];
diff --git a/app/assets/javascripts/dispatcher.js.es6 b/app/assets/javascripts/dispatcher.js.es6
index c2d4670b7e9..16df4b0b005 100644
--- a/app/assets/javascripts/dispatcher.js.es6
+++ b/app/assets/javascripts/dispatcher.js.es6
@@ -208,6 +208,9 @@
new gl.ProtectedBranchCreate();
new gl.ProtectedBranchEditList();
break;
+ case 'projects:variables:index':
+ new gl.ProjectVariables();
+ break;
}
switch (path.first()) {
case 'admin':
diff --git a/app/assets/javascripts/due_date_select.js.es6 b/app/assets/javascripts/due_date_select.js.es6
index fd7f961aab9..e84f5ac9183 100644
--- a/app/assets/javascripts/due_date_select.js.es6
+++ b/app/assets/javascripts/due_date_select.js.es6
@@ -145,25 +145,19 @@
class DueDateSelectors {
constructor() {
- this.initMilestoneDueDate();
+ this.initMilestoneDatePicker();
this.initIssuableSelect();
}
- initMilestoneDueDate() {
- const $datePicker = $('.datepicker');
+ initMilestoneDatePicker() {
+ $('.datepicker').datepicker({
+ dateFormat: 'yy-mm-dd'
+ });
- if ($datePicker.length) {
- const $dueDate = $('#milestone_due_date');
- $datePicker.datepicker({
- dateFormat: 'yy-mm-dd',
- onSelect: (dateText, inst) => {
- $dueDate.val(dateText);
- }
- }).datepicker('setDate', $.datepicker.parseDate('yy-mm-dd', $dueDate.val()));
- }
- $('.js-clear-due-date').on('click', (e) => {
+ $('.js-clear-due-date,.js-clear-start-date').on('click', (e) => {
e.preventDefault();
- $.datepicker._clearDate($datePicker);
+ const datepicker = $(e.target).siblings('.datepicker');
+ $.datepicker._clearDate(datepicker);
});
}
diff --git a/app/assets/javascripts/environments/components/environment.js.es6 b/app/assets/javascripts/environments/components/environment.js.es6
index 1043e516483..84faabf938a 100644
--- a/app/assets/javascripts/environments/components/environment.js.es6
+++ b/app/assets/javascripts/environments/components/environment.js.es6
@@ -1,12 +1,13 @@
+/* eslint-disable no-param-reassign */
+/* global Vue */
+/* global EnvironmentsService */
+
//= require vue
//= require vue-resource
//= require_tree ../services/
//= require ./environment_item
-/* globals Vue, EnvironmentsService */
-/* eslint-disable no-param-reassign */
-
-(() => { // eslint-disable-line
+(() => {
window.gl = window.gl || {};
/**
@@ -180,7 +181,7 @@
<div class="environments-container">
<div class="environments-list-loading text-center" v-if="isLoading">
- <i class="fa fa-spinner spin"></i>
+ <i class="fa fa-spinner fa-spin"></i>
</div>
<div class="blank-state blank-state-no-icon"
@@ -209,12 +210,12 @@
<table class="table ci-table environments">
<thead>
<tr>
- <th>Environment</th>
- <th>Last deployment</th>
- <th>Build</th>
- <th>Commit</th>
- <th></th>
- <th class="hidden-xs"></th>
+ <th class="environments-name">Environment</th>
+ <th class="environments-deploy">Last deployment</th>
+ <th class="environments-build">Build</th>
+ <th class="environments-commit">Commit</th>
+ <th class="environments-date"></th>
+ <th class="hidden-xs environments-actions"></th>
</tr>
</thead>
<tbody>
diff --git a/app/assets/javascripts/environments/components/environment_item.js.es6 b/app/assets/javascripts/environments/components/environment_item.js.es6
index da7db5c05bd..07f49cce3dc 100644
--- a/app/assets/javascripts/environments/components/environment_item.js.es6
+++ b/app/assets/javascripts/environments/components/environment_item.js.es6
@@ -1,4 +1,7 @@
-/*= require lib/utils/timeago */
+/* global Vue */
+/* global timeago */
+
+/*= require timeago */
/*= require lib/utils/text_utility */
/*= require vue_common_component/commit */
/*= require ./environment_actions */
@@ -6,8 +9,6 @@
/*= require ./environment_stop */
/*= require ./environment_rollback */
-/* globals Vue, timeago */
-
(() => {
/**
* Envrionment Item Component
diff --git a/app/assets/javascripts/extensions/array.js b/app/assets/javascripts/extensions/array.js
deleted file mode 100644
index fc6c130113d..00000000000
--- a/app/assets/javascripts/extensions/array.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/* eslint-disable no-extend-native, func-names, space-before-function-paren, semi, space-infix-ops, max-len */
-Array.prototype.first = function() {
- return this[0];
-}
-
-Array.prototype.last = function() {
- return this[this.length-1];
-}
diff --git a/app/assets/javascripts/extensions/array.js.es6 b/app/assets/javascripts/extensions/array.js.es6
new file mode 100644
index 00000000000..717566a4715
--- /dev/null
+++ b/app/assets/javascripts/extensions/array.js.es6
@@ -0,0 +1,24 @@
+/* eslint-disable no-extend-native, func-names, space-before-function-paren, semi, space-infix-ops, max-len */
+Array.prototype.first = function() {
+ return this[0];
+}
+
+Array.prototype.last = function() {
+ return this[this.length-1];
+}
+
+Array.prototype.find = Array.prototype.find || function(predicate, ...args) {
+ if (!this) throw new TypeError('Array.prototype.find called on null or undefined');
+ if (typeof predicate !== 'function') throw new TypeError('predicate must be a function');
+
+ const list = Object(this);
+ const thisArg = args[1];
+ let value = {};
+
+ for (let i = 0; i < list.length; i += 1) {
+ value = list[i];
+ if (predicate.call(thisArg, value, i, list)) return value;
+ }
+
+ return undefined;
+};
diff --git a/app/assets/javascripts/extensions/element.js.es6 b/app/assets/javascripts/extensions/element.js.es6
index afb2f0d6956..6d9b0c4bc3e 100644
--- a/app/assets/javascripts/extensions/element.js.es6
+++ b/app/assets/javascripts/extensions/element.js.es6
@@ -3,7 +3,7 @@
Element.prototype.matches = Element.prototype.matches || Element.prototype.msMatchesSelector;
-Element.prototype.closest = function closest(selector, selectedElement = this) {
+Element.prototype.closest = Element.prototype.closest || function closest(selector, selectedElement = this) {
if (!selectedElement) return;
return selectedElement.matches(selector) ? selectedElement : Element.prototype.closest(selector, selectedElement.parentElement);
};
diff --git a/app/assets/javascripts/gfm_auto_complete.js.es6 b/app/assets/javascripts/gfm_auto_complete.js.es6
index 5d9ac4d350a..89fe13b7a45 100644
--- a/app/assets/javascripts/gfm_auto_complete.js.es6
+++ b/app/assets/javascripts/gfm_auto_complete.js.es6
@@ -53,6 +53,26 @@
} else {
return value;
}
+ },
+ matcher: function (flag, subtext) {
+ // The below is taken from At.js source
+ // Tweaked to commands to start without a space only if char before is a non-word character
+ // https://github.com/ichord/At.js
+ var _a, _y, regexp, match;
+ flag = flag.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
+
+ _a = decodeURI("%C3%80");
+ _y = decodeURI("%C3%BF");
+
+ regexp = new RegExp("(?:\\B|\\W|\\s)" + flag + "([A-Za-z" + _a + "-" + _y + "0-9_\'\.\+\-]*)|([^\\x00-\\xff]*)$", 'gi');
+
+ match = regexp.exec(subtext);
+
+ if (match) {
+ return match[2] || match[1];
+ } else {
+ return null;
+ }
}
},
setup: _.debounce(function(input) {
@@ -91,10 +111,12 @@
})(this),
insertTpl: ':${name}:',
data: ['loading'],
+ startWithSpace: false,
callbacks: {
sorter: this.DefaultOptions.sorter,
filter: this.DefaultOptions.filter,
- beforeInsert: this.DefaultOptions.beforeInsert
+ beforeInsert: this.DefaultOptions.beforeInsert,
+ matcher: this.DefaultOptions.matcher
}
});
// Team Members
@@ -112,11 +134,13 @@
insertTpl: '${atwho-at}${username}',
searchKey: 'search',
data: ['loading'],
+ startWithSpace: false,
alwaysHighlightFirst: true,
callbacks: {
sorter: this.DefaultOptions.sorter,
filter: this.DefaultOptions.filter,
beforeInsert: this.DefaultOptions.beforeInsert,
+ matcher: this.DefaultOptions.matcher,
beforeSave: function(members) {
return $.map(members, function(m) {
let title = '';
@@ -157,10 +181,12 @@
})(this),
data: ['loading'],
insertTpl: '${atwho-at}${id}',
+ startWithSpace: false,
callbacks: {
sorter: this.DefaultOptions.sorter,
filter: this.DefaultOptions.filter,
beforeInsert: this.DefaultOptions.beforeInsert,
+ matcher: this.DefaultOptions.matcher,
beforeSave: function(issues) {
return $.map(issues, function(i) {
if (i.title == null) {
@@ -190,7 +216,9 @@
})(this),
insertTpl: '${atwho-at}"${title}"',
data: ['loading'],
+ startWithSpace: false,
callbacks: {
+ matcher: this.DefaultOptions.matcher,
sorter: this.DefaultOptions.sorter,
beforeSave: function(milestones) {
return $.map(milestones, function(m) {
@@ -220,11 +248,13 @@
};
})(this),
data: ['loading'],
+ startWithSpace: false,
insertTpl: '${atwho-at}${id}',
callbacks: {
sorter: this.DefaultOptions.sorter,
filter: this.DefaultOptions.filter,
beforeInsert: this.DefaultOptions.beforeInsert,
+ matcher: this.DefaultOptions.matcher,
beforeSave: function(merges) {
return $.map(merges, function(m) {
if (m.title == null) {
@@ -245,7 +275,9 @@
searchKey: 'search',
displayTpl: this.Labels.template,
insertTpl: '${atwho-at}${title}',
+ startWithSpace: false,
callbacks: {
+ matcher: this.DefaultOptions.matcher,
sorter: this.DefaultOptions.sorter,
beforeSave: function(merges) {
var sanitizeLabelTitle;
diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js
index 812d5cde685..f334f35594d 100644
--- a/app/assets/javascripts/labels_select.js
+++ b/app/assets/javascripts/labels_select.js
@@ -1,4 +1,4 @@
-/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, no-underscore-dangle, prefer-arrow-callback, max-len, one-var, no-unused-vars, one-var-declaration-per-line, prefer-template, no-new, consistent-return, object-shorthand, comma-dangle, no-shadow, no-param-reassign, brace-style, vars-on-top, quotes, no-lonely-if, no-else-return, no-undef, semi, dot-notation, no-empty, no-return-assign, camelcase, prefer-spread, padded-blocks, max-len */
+/* eslint-disable no-useless-return, func-names, space-before-function-paren, wrap-iife, no-var, no-underscore-dangle, prefer-arrow-callback, max-len, one-var, no-unused-vars, one-var-declaration-per-line, prefer-template, no-new, consistent-return, object-shorthand, comma-dangle, no-shadow, no-param-reassign, brace-style, vars-on-top, quotes, no-lonely-if, no-else-return, no-undef, semi, dot-notation, no-empty, no-return-assign, camelcase, prefer-spread, padded-blocks, max-len */
(function() {
this.LabelsSelect = (function() {
function LabelsSelect() {
diff --git a/app/assets/javascripts/lib/utils/custom_event_polyfill.js.es6 b/app/assets/javascripts/lib/utils/custom_event_polyfill.js.es6
new file mode 100644
index 00000000000..5ae978010c9
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/custom_event_polyfill.js.es6
@@ -0,0 +1,12 @@
+/**
+ * CustomEvent support for IE
+ */
+if (typeof window.CustomEvent !== 'function') {
+ window.CustomEvent = function CustomEvent(e, params) {
+ const options = params || { bubbles: false, cancelable: false, detail: undefined };
+ const evt = document.createEvent('CustomEvent');
+ evt.initCustomEvent(e, options.bubbles, options.cancelable, options.detail);
+ return evt;
+ };
+ window.CustomEvent.prototype = window.Event.prototype;
+}
diff --git a/app/assets/javascripts/lib/utils/datetime_utility.js b/app/assets/javascripts/lib/utils/datetime_utility.js
index d480fdc882b..963d2851e5f 100644
--- a/app/assets/javascripts/lib/utils/datetime_utility.js
+++ b/app/assets/javascripts/lib/utils/datetime_utility.js
@@ -1,4 +1,10 @@
-/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, no-param-reassign, no-cond-assign, no-undef, comma-dangle, no-unused-expressions, prefer-template, padded-blocks, max-len */
+/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, no-param-reassign, no-cond-assign, comma-dangle, no-unused-expressions, prefer-template, padded-blocks, max-len */
+/* global timeago */
+/* global dateFormat */
+
+/*= require timeago */
+/*= require date.format */
+
(function() {
(function(w) {
var base;
diff --git a/app/assets/javascripts/lib/utils/pretty_time.js.es6 b/app/assets/javascripts/lib/utils/pretty_time.js.es6
new file mode 100644
index 00000000000..ccaf447eb0b
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/pretty_time.js.es6
@@ -0,0 +1,67 @@
+(() => {
+ /*
+ * TODO: Make these methods more configurable (e.g. parseSeconds timePeriodContstraints,
+ * stringifyTime condensed or non-condensed, abbreviateTimelengths)
+ * */
+
+ class PrettyTime {
+
+ /*
+ * Accepts seconds and returns a timeObject { weeks: #, days: #, hours: #, minutes: # }
+ * Seconds can be negative or positive, zero or non-zero.
+ */
+ static parseSeconds(seconds) {
+ const DAYS_PER_WEEK = 5;
+ const HOURS_PER_DAY = 8;
+ const MINUTES_PER_HOUR = 60;
+ const MINUTES_PER_WEEK = DAYS_PER_WEEK * HOURS_PER_DAY * MINUTES_PER_HOUR;
+ const MINUTES_PER_DAY = HOURS_PER_DAY * MINUTES_PER_HOUR;
+
+ const timePeriodConstraints = {
+ weeks: MINUTES_PER_WEEK,
+ days: MINUTES_PER_DAY,
+ hours: MINUTES_PER_HOUR,
+ minutes: 1,
+ };
+
+ let unorderedMinutes = PrettyTime.secondsToMinutes(seconds);
+
+ return _.mapObject(timePeriodConstraints, (minutesPerPeriod) => {
+ const periodCount = Math.floor(unorderedMinutes / minutesPerPeriod);
+
+ unorderedMinutes -= (periodCount * minutesPerPeriod);
+
+ return periodCount;
+ });
+ }
+
+ /*
+ * Accepts a timeObject and returns a condensed string representation of it
+ * (e.g. '1w 2d 3h 1m' or '1h 30m'). Zero value units are not included.
+ */
+
+ static stringifyTime(timeObject) {
+ const reducedTime = _.reduce(timeObject, (memo, unitValue, unitName) => {
+ const isNonZero = !!unitValue;
+ return isNonZero ? `${memo} ${unitValue}${unitName.charAt(0)}` : memo;
+ }, '').trim();
+ return reducedTime.length ? reducedTime : '0m';
+ }
+
+ /*
+ * Accepts a time string of any size (e.g. '1w 2d 3h 5m' or '1w 2d') and returns
+ * the first non-zero unit/value pair.
+ */
+
+ static abbreviateTime(timeStr) {
+ return timeStr.split(' ')
+ .filter(unitStr => unitStr.charAt(0) !== '0')[0];
+ }
+
+ static secondsToMinutes(seconds) {
+ return Math.abs(seconds / 60);
+ }
+ }
+
+ gl.PrettyTime = PrettyTime;
+})(window.gl || (window.gl = {}));
diff --git a/app/assets/javascripts/lib/utils/timeago.js b/app/assets/javascripts/lib/utils/timeago.js
deleted file mode 100644
index edf0a612374..00000000000
--- a/app/assets/javascripts/lib/utils/timeago.js
+++ /dev/null
@@ -1,239 +0,0 @@
-/* eslint-disable no-unused-expressions, wrap-iife, func-names, curly, no-param-reassign, no-trailing-spaces, prefer-arrow-callback, no-var, one-var, quote-props, space-before-function-paren, vars-on-top, radix, prefer-template, space-infix-ops, no-use-before-define, newline-per-chained-call, no-useless-escape, no-nested-ternary, indent, no-undef, no-plusplus, one-var-declaration-per-line, operator-assignment, consistent-return, keyword-spacing, max-len, space-unary-ops, no-shadow, no-restricted-syntax, guard-for-in, eol-last, max-len */
-
-/**
- * Copyright (c) 2016 hustcc
- * License: MIT
- * Version: v2.0.2
- * https://github.com/hustcc/timeago.js
- * This is a forked from (https://gitlab.com/ClemMakesApps/timeago.js)
-**/
-/* eslint-disable */
-/* jshint expr: true */
-!function (root, factory) {
- if (typeof module === 'object' && module.exports)
- module.exports = factory(root);
- else
- root.timeago = factory(root);
-}(typeof window !== 'undefined' ? window : this,
-function () {
- var cnt = 0, // the timer counter, for timer key
- indexMapEn = 'second_minute_hour_day_week_month_year'.split('_'),
-
- // build-in locales: en & zh_CN
- locales = {
- 'en': function(number, index) {
- if (index === 0) return ['just now', 'right now'];
- var unit = indexMapEn[parseInt(index / 2)];
- if (number > 1) unit += 's';
- return [number + ' ' + unit + ' ago', 'in ' + number + ' ' + unit];
- },
- },
- // second, minute, hour, day, week, month, year(365 days)
- SEC_ARRAY = [60, 60, 24, 7, 365/7/12, 12],
- SEC_ARRAY_LEN = 6,
- ATTR_DATETIME = 'datetime';
-
- // format Date / string / timestamp to Date instance.
- function toDate(input) {
- if (input instanceof Date) return input;
- if (!isNaN(input)) return new Date(toInt(input));
- if (/^\d+$/.test(input)) return new Date(toInt(input, 10));
- input = (input || '').trim().replace(/\.\d+/, '') // remove milliseconds
- .replace(/-/, '/').replace(/-/, '/')
- .replace(/T/, ' ').replace(/Z/, ' UTC')
- .replace(/([\+\-]\d\d)\:?(\d\d)/, ' $1$2'); // -04:00 -> -0400
- return new Date(input);
- }
- // change f into int, remove Decimal. just for code compression
- function toInt(f) {
- return parseInt(f);
- }
- // format the diff second to *** time ago, with setting locale
- function formatDiff(diff, locale, defaultLocale) {
- // if locale is not exist, use defaultLocale.
- // if defaultLocale is not exist, use build-in `en`.
- // be sure of no error when locale is not exist.
- locale = locales[locale] ? locale : (locales[defaultLocale] ? defaultLocale : 'en');
- // if (! locales[locale]) locale = defaultLocale;
- var i = 0;
- agoin = diff < 0 ? 1 : 0; // timein or timeago
- diff = Math.abs(diff);
-
- for (; diff >= SEC_ARRAY[i] && i < SEC_ARRAY_LEN; i++) {
- diff /= SEC_ARRAY[i];
- }
- diff = toInt(diff);
- i *= 2;
-
- if (diff > (i === 0 ? 9 : 1)) i += 1;
- return locales[locale](diff, i)[agoin].replace('%s', diff);
- }
- // calculate the diff second between date to be formated an now date.
- function diffSec(date, nowDate) {
- nowDate = nowDate ? toDate(nowDate) : new Date();
- return (nowDate - toDate(date)) / 1000;
- }
- /**
- * nextInterval: calculate the next interval time.
- * - diff: the diff sec between now and date to be formated.
- *
- * What's the meaning?
- * diff = 61 then return 59
- * diff = 3601 (an hour + 1 second), then return 3599
- * make the interval with high performace.
- **/
- function nextInterval(diff) {
- var rst = 1, i = 0, d = Math.abs(diff);
- for (; diff >= SEC_ARRAY[i] && i < SEC_ARRAY_LEN; i++) {
- diff /= SEC_ARRAY[i];
- rst *= SEC_ARRAY[i];
- }
- // return leftSec(d, rst);
- d = d % rst;
- d = d ? rst - d : rst;
- return Math.ceil(d);
- }
- // get the datetime attribute, jQuery and DOM
- function getDateAttr(node) {
- if (node.getAttribute) return node.getAttribute(ATTR_DATETIME);
- if(node.attr) return node.attr(ATTR_DATETIME);
- }
- /**
- * timeago: the function to get `timeago` instance.
- * - nowDate: the relative date, default is new Date().
- * - defaultLocale: the default locale, default is en. if your set it, then the `locale` parameter of format is not needed of you.
- *
- * How to use it?
- * var timeagoLib = require('timeago.js');
- * var timeago = timeagoLib(); // all use default.
- * var timeago = timeagoLib('2016-09-10'); // the relative date is 2016-09-10, so the 2016-09-11 will be 1 day ago.
- * var timeago = timeagoLib(null, 'zh_CN'); // set default locale is `zh_CN`.
- * var timeago = timeagoLib('2016-09-10', 'zh_CN'); // the relative date is 2016-09-10, and locale is zh_CN, so the 2016-09-11 will be 1天前.
- **/
- function Timeago(nowDate, defaultLocale) {
- var timers = {}; // real-time render timers
- // if do not set the defaultLocale, set it with `en`
- if (! defaultLocale) defaultLocale = 'en'; // use default build-in locale
- // what the timer will do
- function doRender(node, date, locale, cnt) {
- var diff = diffSec(date, nowDate);
- node.innerHTML = formatDiff(diff, locale, defaultLocale);
- // waiting %s seconds, do the next render
- timers['k' + cnt] = setTimeout(function() {
- doRender(node, date, locale, cnt);
- }, nextInterval(diff) * 1000);
- }
- /**
- * nextInterval: calculate the next interval time.
- * - diff: the diff sec between now and date to be formated.
- *
- * What's the meaning?
- * diff = 61 then return 59
- * diff = 3601 (an hour + 1 second), then return 3599
- * make the interval with high performace.
- **/
- // this.nextInterval = function(diff) { // for dev test
- // var rst = 1, i = 0, d = Math.abs(diff);
- // for (; diff >= SEC_ARRAY[i] && i < SEC_ARRAY_LEN; i++) {
- // diff /= SEC_ARRAY[i];
- // rst *= SEC_ARRAY[i];
- // }
- // // return leftSec(d, rst);
- // d = d % rst;
- // d = d ? rst - d : rst;
- // return Math.ceil(d);
- // }; // for dev test
- /**
- * format: format the date to *** time ago, with setting or default locale
- * - date: the date / string / timestamp to be formated
- * - locale: the formated string's locale name, e.g. en / zh_CN
- *
- * How to use it?
- * var timeago = require('timeago.js')();
- * timeago.format(new Date(), 'pl'); // Date instance
- * timeago.format('2016-09-10', 'fr'); // formated date string
- * timeago.format(1473473400269); // timestamp with ms
- **/
- this.format = function(date, locale) {
- return formatDiff(diffSec(date, nowDate), locale, defaultLocale);
- };
- /**
- * render: render the DOM real-time.
- * - nodes: which nodes will be rendered.
- * - locale: the locale name used to format date.
- *
- * How to use it?
- * var timeago = new require('timeago.js')();
- * // 1. javascript selector
- * timeago.render(document.querySelectorAll('.need_to_be_rendered'));
- * // 2. use jQuery selector
- * timeago.render($('.need_to_be_rendered'), 'pl');
- *
- * Notice: please be sure the dom has attribute `datetime`.
- **/
- this.render = function(nodes, locale) {
- if (nodes.length === undefined) nodes = [nodes];
- for (var i = 0; i < nodes.length; i++) {
- doRender(nodes[i], getDateAttr(nodes[i]), locale, ++ cnt); // render item
- }
- };
- /**
- * cancel: cancel all the timers which are doing real-time render.
- *
- * How to use it?
- * var timeago = new require('timeago.js')();
- * timeago.render(document.querySelectorAll('.need_to_be_rendered'));
- * timeago.cancel(); // will stop all the timer, stop render in real time.
- **/
- this.cancel = function() {
- for (var key in timers) {
- clearTimeout(timers[key]);
- }
- timers = {};
- };
- /**
- * setLocale: set the default locale name.
- *
- * How to use it?
- * var timeago = require('timeago.js');
- * timeago = new timeago();
- * timeago.setLocale('fr');
- **/
- this.setLocale = function(locale) {
- defaultLocale = locale;
- };
- return this;
- }
- /**
- * timeago: the function to get `timeago` instance.
- * - nowDate: the relative date, default is new Date().
- * - defaultLocale: the default locale, default is en. if your set it, then the `locale` parameter of format is not needed of you.
- *
- * How to use it?
- * var timeagoLib = require('timeago.js');
- * var timeago = timeagoLib(); // all use default.
- * var timeago = timeagoLib('2016-09-10'); // the relative date is 2016-09-10, so the 2016-09-11 will be 1 day ago.
- * var timeago = timeagoLib(null, 'zh_CN'); // set default locale is `zh_CN`.
- * var timeago = timeagoLib('2016-09-10', 'zh_CN'); // the relative date is 2016-09-10, and locale is zh_CN, so the 2016-09-11 will be 1天前.
- **/
- function timeagoFactory(nowDate, defaultLocale) {
- return new Timeago(nowDate, defaultLocale);
- }
- /**
- * register: register a new language locale
- * - locale: locale name, e.g. en / zh_CN, notice the standard.
- * - localeFunc: the locale process function
- *
- * How to use it?
- * var timeagoLib = require('timeago.js');
- *
- * timeagoLib.register('the locale name', the_locale_func);
- * // or
- * timeagoLib.register('pl', require('timeago.js/locales/pl'));
- **/
- timeagoFactory.register = function(locale, localeFunc) {
- locales[locale] = localeFunc;
- };
-
- return timeagoFactory;
-}); \ No newline at end of file
diff --git a/app/assets/javascripts/logo.js b/app/assets/javascripts/logo.js
index 9404b2c3a8c..0ae6df311bb 100644
--- a/app/assets/javascripts/logo.js
+++ b/app/assets/javascripts/logo.js
@@ -1,4 +1,6 @@
/* eslint-disable func-names, space-before-function-paren, prefer-arrow-callback, padded-blocks */
+/* global Turbolinks */
+
(function() {
Turbolinks.enableProgressBar();
diff --git a/app/assets/javascripts/merge_request_widget.js.es6 b/app/assets/javascripts/merge_request_widget.js.es6
index 54929cd8f24..a55fe9df0b3 100644
--- a/app/assets/javascripts/merge_request_widget.js.es6
+++ b/app/assets/javascripts/merge_request_widget.js.es6
@@ -67,7 +67,7 @@
MergeRequestWidget.prototype.addEventListeners = function() {
var allowedPages;
allowedPages = ['show', 'commits', 'builds', 'pipelines', 'changes'];
- return $(document).on('page:change.merge_request', (function(_this) {
+ $(document).on('page:change.merge_request', (function(_this) {
return function() {
var page;
page = $('body').data('page').split(':').last();
@@ -245,7 +245,7 @@
case "not_found":
return this.setMergeButtonClass('btn-danger');
case "running":
- return this.setMergeButtonClass('btn-warning');
+ return this.setMergeButtonClass('btn-info');
case "success":
case "success_with_warnings":
return this.setMergeButtonClass('btn-create');
@@ -263,7 +263,7 @@
};
MergeRequestWidget.prototype.setMergeButtonClass = function(css_class) {
- return $('.js-merge-button,.accept-action .dropdown-toggle').removeClass('btn-danger btn-warning btn-create').addClass(css_class);
+ return $('.js-merge-button,.accept-action .dropdown-toggle').removeClass('btn-danger btn-info btn-create').addClass(css_class);
};
return MergeRequestWidget;
diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js
index 6cb87f9ba81..0ca0e255595 100644
--- a/app/assets/javascripts/notes.js
+++ b/app/assets/javascripts/notes.js
@@ -1,4 +1,4 @@
-/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, no-use-before-define, camelcase, no-unused-expressions, quotes, max-len, one-var, one-var-declaration-per-line, default-case, prefer-template, no-undef, consistent-return, no-alert, no-return-assign, no-param-reassign, prefer-arrow-callback, no-else-return, comma-dangle, no-new, brace-style, no-lonely-if, vars-on-top, no-unused-vars, semi, indent, no-sequences, no-shadow, newline-per-chained-call, no-useless-escape, radix, padded-blocks, max-len */
+/* eslint-disable no-restricted-properties, func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, no-use-before-define, camelcase, no-unused-expressions, quotes, max-len, one-var, one-var-declaration-per-line, default-case, prefer-template, no-undef, consistent-return, no-alert, no-return-assign, no-param-reassign, prefer-arrow-callback, no-else-return, comma-dangle, no-new, brace-style, no-lonely-if, vars-on-top, no-unused-vars, semi, indent, no-sequences, no-shadow, newline-per-chained-call, no-useless-escape, radix, padded-blocks, max-len */
/*= require autosave */
/*= require autosize */
@@ -113,6 +113,7 @@
$(document).off("click", ".js-note-discard");
$(document).off("keydown", ".js-note-text");
$(document).off('click', '.js-comment-resolve-button');
+ $(document).off("click", '.system-note-commit-list-toggler');
$('.note .js-task-list-container').taskList('disable');
return $(document).off('tasklist:changed', '.note .js-task-list-container');
};
@@ -332,7 +333,7 @@
gl.diffNotesCompileComponents();
}
- gl.utils.localTimeAgo($('.js-timeago', note_html), false);
+ gl.utils.localTimeAgo($('.js-timeago'), false);
return this.updateNotesCount(1);
};
diff --git a/app/assets/javascripts/profile/profile.js.es6 b/app/assets/javascripts/profile/profile.js.es6
index 73858388261..3eb81808bd6 100644
--- a/app/assets/javascripts/profile/profile.js.es6
+++ b/app/assets/javascripts/profile/profile.js.es6
@@ -35,7 +35,6 @@
}
onSubmitForm(e) {
- e.preventDefault();
return this.saveForm();
}
diff --git a/app/assets/javascripts/project_variables.js.es6 b/app/assets/javascripts/project_variables.js.es6
new file mode 100644
index 00000000000..4ee2e49306d
--- /dev/null
+++ b/app/assets/javascripts/project_variables.js.es6
@@ -0,0 +1,43 @@
+(() => {
+ const HIDDEN_VALUE_TEXT = '******';
+
+ class ProjectVariables {
+ constructor() {
+ this.$revealBtn = $('.js-btn-toggle-reveal-values');
+ this.$revealBtn.on('click', this.toggleRevealState.bind(this));
+ }
+
+ toggleRevealState(e) {
+ e.preventDefault();
+
+ const oldStatus = this.$revealBtn.attr('data-status');
+ let newStatus = 'hidden';
+ let newAction = 'Reveal Values';
+
+ if (oldStatus === 'hidden') {
+ newStatus = 'revealed';
+ newAction = 'Hide Values';
+ }
+
+ this.$revealBtn.attr('data-status', newStatus);
+
+ const $variables = $('.variable-value');
+
+ $variables.each((_, variable) => {
+ const $variable = $(variable);
+ let newText = HIDDEN_VALUE_TEXT;
+
+ if (newStatus === 'revealed') {
+ newText = $variable.attr('data-value');
+ }
+
+ $variable.text(newText);
+ });
+
+ this.$revealBtn.text(newAction);
+ }
+ }
+
+ window.gl = window.gl || {};
+ window.gl.ProjectVariables = ProjectVariables;
+})();
diff --git a/app/assets/javascripts/smart_interval.js.es6 b/app/assets/javascripts/smart_interval.js.es6
new file mode 100644
index 00000000000..5eb15dba79b
--- /dev/null
+++ b/app/assets/javascripts/smart_interval.js.es6
@@ -0,0 +1,130 @@
+/*
+* Instances of SmartInterval extend the functionality of `setInterval`, make it configurable
+* and controllable by a public API.
+*
+* */
+
+(() => {
+ class SmartInterval {
+ /**
+ * @param { function } callback Function to be called on each iteration (required)
+ * @param { milliseconds } startingInterval `currentInterval` is set to this initially
+ * @param { milliseconds } maxInterval `currentInterval` will be incremented to this
+ * @param { integer } incrementByFactorOf `currentInterval` is incremented by this factor
+ * @param { boolean } lazyStart Configure if timer is initialized on instantiation or lazily
+ */
+ constructor({ callback, startingInterval, maxInterval, incrementByFactorOf, lazyStart }) {
+ this.cfg = {
+ callback,
+ startingInterval,
+ maxInterval,
+ incrementByFactorOf,
+ lazyStart,
+ };
+
+ this.state = {
+ intervalId: null,
+ currentInterval: startingInterval,
+ pageVisibility: 'visible',
+ };
+
+ this.initInterval();
+ }
+ /* public */
+
+ start() {
+ const cfg = this.cfg;
+ const state = this.state;
+
+ state.intervalId = window.setInterval(() => {
+ cfg.callback();
+
+ if (this.getCurrentInterval() === cfg.maxInterval) {
+ return;
+ }
+
+ this.incrementInterval();
+ this.resume();
+ }, this.getCurrentInterval());
+ }
+
+ // cancel the existing timer, setting the currentInterval back to startingInterval
+ cancel() {
+ this.setCurrentInterval(this.cfg.startingInterval);
+ this.stopTimer();
+ }
+
+ // start a timer, using the existing interval
+ resume() {
+ this.stopTimer(); // stop exsiting timer, in case timer was not previously stopped
+ this.start();
+ }
+
+ destroy() {
+ this.cancel();
+ $(document).off('visibilitychange').off('page:before-unload');
+ }
+
+ /* private */
+
+ initInterval() {
+ const cfg = this.cfg;
+
+ if (!cfg.lazyStart) {
+ this.start();
+ }
+
+ this.initVisibilityChangeHandling();
+ this.initPageUnloadHandling();
+ }
+
+ initVisibilityChangeHandling() {
+ // cancel interval when tab no longer shown (prevents cached pages from polling)
+ $(document)
+ .off('visibilitychange').on('visibilitychange', (e) => {
+ this.state.pageVisibility = e.target.visibilityState;
+ this.handleVisibilityChange();
+ });
+ }
+
+ initPageUnloadHandling() {
+ // prevent interval continuing after page change, when kept in cache by Turbolinks
+ $(document).on('page:before-unload', () => this.cancel());
+ }
+
+ handleVisibilityChange() {
+ const state = this.state;
+
+ const intervalAction = state.pageVisibility === 'hidden' ? this.cancel : this.resume;
+
+ intervalAction.apply(this);
+ }
+
+ getCurrentInterval() {
+ return this.state.currentInterval;
+ }
+
+ setCurrentInterval(newInterval) {
+ this.state.currentInterval = newInterval;
+ }
+
+ incrementInterval() {
+ const cfg = this.cfg;
+ const currentInterval = this.getCurrentInterval();
+ let nextInterval = currentInterval * cfg.incrementByFactorOf;
+
+ if (nextInterval > cfg.maxInterval) {
+ nextInterval = cfg.maxInterval;
+ }
+
+ this.setCurrentInterval(nextInterval);
+ }
+
+ stopTimer() {
+ const state = this.state;
+
+ state.intervalId = window.clearInterval(state.intervalId);
+ }
+ }
+ gl.SmartInterval = SmartInterval;
+})(window.gl || (window.gl = {}));
diff --git a/app/assets/javascripts/subbable_resource.js.es6 b/app/assets/javascripts/subbable_resource.js.es6
new file mode 100644
index 00000000000..932120157a3
--- /dev/null
+++ b/app/assets/javascripts/subbable_resource.js.es6
@@ -0,0 +1,54 @@
+//= require vue
+//= require vue-resource
+
+(() => {
+/*
+* SubbableResource can be extended to provide a pubsub-style service for one-off REST
+* calls. Subscribe by passing a callback or render method you will use to handle responses.
+ *
+* */
+
+ class SubbableResource {
+ constructor(resourcePath) {
+ this.endpoint = resourcePath;
+
+ // TODO: Switch to axios.create
+ this.resource = $.ajax;
+ this.subscribers = [];
+ }
+
+ subscribe(callback) {
+ this.subscribers.push(callback);
+ }
+
+ publish(newResponse) {
+ const responseCopy = _.extend({}, newResponse);
+ this.subscribers.forEach((fn) => {
+ fn(responseCopy);
+ });
+ return newResponse;
+ }
+
+ get(payload) {
+ return this.resource(payload)
+ .then(data => this.publish(data));
+ }
+
+ post(payload) {
+ return this.resource(payload)
+ .then(data => this.publish(data));
+ }
+
+ put(payload) {
+ return this.resource(payload)
+ .then(data => this.publish(data));
+ }
+
+ delete(payload) {
+ return this.resource(payload)
+ .then(data => this.publish(data));
+ }
+ }
+
+ gl.SubbableResource = SubbableResource;
+})(window.gl || (window.gl = {}));
diff --git a/app/assets/javascripts/tree.js b/app/assets/javascripts/tree.js
index 54c473d936d..f48a7ee0f55 100644
--- a/app/assets/javascripts/tree.js
+++ b/app/assets/javascripts/tree.js
@@ -1,4 +1,5 @@
/* eslint-disable func-names, space-before-function-paren, wrap-iife, max-len, quotes, consistent-return, no-var, one-var, one-var-declaration-per-line, no-else-return, prefer-arrow-callback, padded-blocks, max-len */
+/* global Turbolinks */
(function() {
this.TreeView = (function() {
function TreeView() {
diff --git a/app/assets/javascripts/users/calendar.js b/app/assets/javascripts/users/calendar.js
index 6d739039a5b..ba7f533c349 100644
--- a/app/assets/javascripts/users/calendar.js
+++ b/app/assets/javascripts/users/calendar.js
@@ -206,6 +206,7 @@
}
});
} else {
+ this.currentSelectedDate = '';
return $('.user-calendar-activities').html('');
}
};
diff --git a/app/assets/stylesheets/framework/avatar.scss b/app/assets/stylesheets/framework/avatar.scss
index ad0d387067f..c0dd1cb3667 100644
--- a/app/assets/stylesheets/framework/avatar.scss
+++ b/app/assets/stylesheets/framework/avatar.scss
@@ -80,6 +80,7 @@
border-radius: 0;
border: none;
height: auto;
+ width: 100%;
margin: 0;
align-self: center;
}
diff --git a/app/assets/stylesheets/framework/blocks.scss b/app/assets/stylesheets/framework/blocks.scss
index 7e168092522..77ae9e9a6e7 100644
--- a/app/assets/stylesheets/framework/blocks.scss
+++ b/app/assets/stylesheets/framework/blocks.scss
@@ -254,3 +254,32 @@
.content-block-small {
padding: 10px 0;
}
+
+.empty-state {
+ margin: 100px 0 0;
+
+ .text-content {
+ max-width: 460px;
+ margin: 0 auto;
+ padding: $gl-padding;
+ }
+
+ .svg-content {
+ text-align: center;
+
+ svg {
+ max-width: 425px;
+ width: 100%;
+ padding: $gl-padding;
+ }
+ }
+
+ @media(max-width: $screen-xs-max) {
+ margin-top: 50px;
+ text-align: center;
+
+ .btn {
+ width: 100%;
+ }
+ }
+}
diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss
index 4a9aa0f8717..36f530af685 100644
--- a/app/assets/stylesheets/framework/buttons.scss
+++ b/app/assets/stylesheets/framework/buttons.scss
@@ -15,7 +15,7 @@
@include btn-default;
}
-@mixin btn-outline($background, $text, $border, $hover-background, $hover-text, $hover-border) {
+@mixin btn-outline($background, $text, $border, $hover-background, $hover-text, $hover-border, $active-background, $active-border) {
background-color: $background;
color: $text;
border-color: $border;
@@ -23,8 +23,14 @@
&:hover,
&:focus {
background-color: $hover-background;
- color: $hover-text;
border-color: $hover-border;
+ color: $hover-text;
+ }
+
+ &:active {
+ background-color: $active-background;
+ border-color: $active-border;
+ color: $hover-text;
}
}
@@ -82,11 +88,11 @@
}
@mixin btn-gray {
- @include btn-color($gray-light, $border-gray-light, $gray-normal, $border-gray-light, $gray-dark, $border-gray-dark, $gl-gray-dark);
+ @include btn-color($gray-light, $border-gray-light, $gray-normal, $border-gray-normal, $gray-dark, $border-gray-dark, $gl-gray-dark);
}
@mixin btn-white {
- @include btn-color($white-light, $border-color, $white-normal, $border-white-normal, $white-dark, $border-white-dark, $btn-white-active);
+ @include btn-color($white-light, $border-color, $white-normal, $border-white-normal, $white-dark, $border-white-dark, $gl-text-color);
}
@mixin btn-with-margin {
@@ -139,11 +145,11 @@
&.btn-new,
&.btn-create,
&.btn-save {
- @include btn-outline($white-light, $green-normal, $green-normal, $green-light, $white-light, $green-light);
+ @include btn-outline($white-light, $border-green-light, $border-green-light, $green-light, $white-light, $border-green-light, $green-normal, $border-green-normal);
}
&.btn-remove {
- @include btn-outline($white-light, $red-normal, $red-normal, $red-light, $white-light, $red-light);
+ @include btn-outline($white-light, $border-red-light, $border-red-light, $red-light, $white-light, $border-red-light, $red-normal, $border-red-normal);
}
}
@@ -165,11 +171,11 @@
}
&.btn-close {
- @include btn-outline($white-light, $orange-normal, $orange-normal, $orange-light, $white-light, $orange-light);
+ @include btn-outline($white-light, $border-orange-light, $border-orange-light, $orange-light, $white-light, $border-orange-light, $orange-normal, $border-orange-normal);
}
&.btn-spam {
- @include btn-outline($white-light, $red-normal, $red-normal, $red-light, $white-light, $red-light);
+ @include btn-outline($white-light, $border-red-light, $border-red-light, $red-light, $white-light, $border-red-light, $red-normal, $border-red-normal);
}
&.btn-danger,
@@ -199,7 +205,7 @@
}
.fa-caret-down,
- .fa-caret-up {
+ .fa-chevron-down {
margin-left: 5px;
}
@@ -351,7 +357,7 @@
.btn-inverted {
&-secondary {
- @include btn-outline($white-light, $blue-normal, $blue-normal, $blue-light, $white-light, $blue-light);
+ @include btn-outline($white-light, $border-blue-light, $border-blue-light, $blue-light, $white-light, $border-blue-light, $blue-normal, $border-blue-normal);
}
}
diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss
index 7f5583c917a..b24fce6f0c2 100644
--- a/app/assets/stylesheets/framework/common.scss
+++ b/app/assets/stylesheets/framework/common.scss
@@ -299,6 +299,10 @@ table {
.well {
margin-bottom: $gl-padding;
+
+ hr {
+ border-color: $gray-darker;
+ }
}
.search_box {
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index 583c17e4a83..6d77aadd753 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -8,6 +8,12 @@
}
}
+@mixin chevron-active {
+ .fa-chevron-down {
+ color: $dropdown-toggle-hover-icon-color;
+ }
+}
+
.open {
.dropdown-menu,
.dropdown-menu-nav {
@@ -19,53 +25,27 @@
}
}
+ .dropdown-toggle,
.dropdown-menu-toggle {
+ @include chevron-active;
border-color: $dropdown-toggle-hover-border-color;
-
- .fa {
- color: $dropdown-toggle-hover-icon-color;
- }
}
}
-.dropdown-menu-toggle {
- position: relative;
- width: 160px;
- padding: 6px 20px 6px 10px;
+.dropdown-toggle {
+ padding: 6px 8px 6px 10px;
background-color: $dropdown-toggle-bg;
color: $dropdown-toggle-color;
font-size: 15px;
text-align: left;
border: 1px solid $border-color;
border-radius: $border-radius-base;
- text-overflow: ellipsis;
white-space: nowrap;
- overflow: hidden;
-
- .fa {
- position: absolute;
- top: 10px;
- right: 8px;
- color: $dropdown-toggle-icon-color;
-
- &.fa-spinner {
- font-size: 16px;
- margin-top: -8px;
- }
- }
&.no-outline {
outline: 0;
}
- &:hover, {
- border-color: $dropdown-toggle-hover-border-color;
-
- .fa {
- color: $dropdown-toggle-hover-icon-color;
- }
- }
-
&.large {
width: 200px;
}
@@ -86,6 +66,51 @@
max-width: 100%;
padding-right: 25px;
}
+
+ .fa {
+ color: $dropdown-toggle-icon-color;
+ }
+
+ .fa-chevron-down {
+ font-size: $dropdown-chevron-size;
+ position: relative;
+ top: -3px;
+ margin-left: 5px;
+ }
+
+ &:hover {
+ @include chevron-active;
+ border-color: $dropdown-toggle-hover-border-color;
+ }
+
+ &:focus:active {
+ @include chevron-active;
+ border-color: $dropdown-toggle-active-border-color;
+ }
+}
+
+.dropdown-menu-toggle {
+ @extend .dropdown-toggle;
+ padding-right: 20px;
+ position: relative;
+ width: 160px;
+ text-overflow: ellipsis;
+ overflow: hidden;
+
+ .fa {
+ position: absolute;
+
+ &.fa-spinner {
+ font-size: 16px;
+ margin-top: -8px;
+ }
+ }
+
+ .fa-chevron-down {
+ position: absolute;
+ top: 11px;
+ right: 8px;
+ }
}
.dropdown-menu,
diff --git a/app/assets/stylesheets/framework/forms.scss b/app/assets/stylesheets/framework/forms.scss
index f0727e9688a..e83a1f7ad68 100644
--- a/app/assets/stylesheets/framework/forms.scss
+++ b/app/assets/stylesheets/framework/forms.scss
@@ -68,6 +68,46 @@ label {
}
}
+.help-form .form-group {
+ margin-left: 0;
+ margin-right: 0;
+
+ .control-label {
+ font-weight: bold;
+ padding-top: 4px;
+ }
+
+ .form-control {
+ height: 29px;
+ background: $white-light;
+ font-family: $monospace_font;
+ }
+
+ .input-group-btn .btn {
+ padding: 3px $gl-btn-padding;
+ background-color: $gray-light;
+ border: 1px solid $border-color;
+ }
+
+ .text-block {
+ line-height: 0.8;
+ padding-top: 9px;
+
+ code {
+ line-height: 1.8;
+ }
+ }
+
+ @media(max-width: $screen-sm-min) {
+ padding: 0 $gl-padding;
+
+ .control-label,
+ .text-block {
+ padding-left: 0;
+ }
+ }
+}
+
.fieldset-form fieldset {
margin-bottom: 20px;
}
@@ -167,4 +207,3 @@ label {
color: $gl-text-color;
}
}
-
diff --git a/app/assets/stylesheets/framework/issue_box.scss b/app/assets/stylesheets/framework/issue_box.scss
index ba3930e03bd..ff6f316d576 100644
--- a/app/assets/stylesheets/framework/issue_box.scss
+++ b/app/assets/stylesheets/framework/issue_box.scss
@@ -39,4 +39,8 @@
&.status-box-expired {
background: #cea61b;
}
+
+ &.status-box-upcoming {
+ background: #8f8f8f;
+ }
}
diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss
index ce864c2de5e..1839ffa0976 100644
--- a/app/assets/stylesheets/framework/nav.scss
+++ b/app/assets/stylesheets/framework/nav.scss
@@ -51,19 +51,26 @@
margin-bottom: -1px;
font-size: 15px;
line-height: 28px;
- color: #959494;
+ color: $note-toolbar-color;
border-bottom: 2px solid transparent;
&:hover,
&:active,
&:focus {
text-decoration: none;
+ border-bottom: 2px solid $gray-darkest;
+ color: $black;
+
+ .badge {
+ color: $black;
+ }
}
}
&.active a {
border-bottom: 2px solid $link-underline-blue;
color: $black;
+ font-weight: 600;
}
.badge {
@@ -85,14 +92,20 @@
li {
+ &.active a {
+ border-bottom: none;
+ color: $link-underline-blue;
+ }
+
a {
margin: 0;
padding: 11px 10px 9px;
- }
- &.active a {
- border-bottom: none;
- color: $link-underline-blue;
+ &:hover,
+ &:active,
+ &:focus {
+ border-bottom: none;
+ }
}
}
}
@@ -310,37 +323,9 @@
height: 51px;
li {
-
a {
padding-top: 10px;
}
-
- a,
- i {
- color: $layout-link-gray;
- }
-
- &.active {
-
- a,
- i {
- color: $black;
- }
-
- svg {
- path,
- polygon {
- fill: $black;
- }
- }
- }
-
- &:hover {
- a,
- i {
- color: $black;
- }
- }
}
}
}
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index 750d99ebabe..8a9c279d124 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -12,67 +12,71 @@ $sidebar-breakpoint: 1024px;
/*
* Color schema
*/
+$darken-normal-factor: 7%;
+$darken-dark-factor: 10%;
+$darken-border-factor: 5%;
+
$white-light: #fff;
-$white-normal: #ededed;
-$white-dark: #ececec;
+$white-normal: darken($white-light, $darken-normal-factor);
+$white-dark: darken($white-light, $darken-dark-factor);
$gray-lightest: #fdfdfd;
$gray-light: #fafafa;
$gray-lighter: #f9f9f9;
-$gray-normal: #f5f5f5;
-$gray-dark: #ededed;
+$gray-normal: darken($gray-light, $darken-normal-factor);
+$gray-dark: darken($gray-light, $darken-dark-factor);
$gray-darker: #eee;
$gray-darkest: #c9c9c9;
-$green-light: #38ae67;
-$green-normal: #2faa60;
-$green-dark: #2ca05b;
+$green-light: #3cbd70;
+$green-normal: darken($green-light, $darken-normal-factor);
+$green-dark: darken($green-light, $darken-dark-factor);
$blue-light: #2ea8e5;
-$blue-normal: #2d9fd8;
-$blue-dark: #2897ce;
+$blue-normal: darken($blue-light, $darken-normal-factor);
+$blue-dark: darken($blue-light, $darken-dark-factor);
$blue-medium-light: #3498cb;
-$blue-medium: #2f8ebf;
-$blue-medium-dark: #2d86b4;
+$blue-medium: darken($blue-medium-light, $darken-normal-factor);
+$blue-medium-dark: darken($blue-medium-light, $darken-dark-factor);
$blue-light-transparent: rgba(44, 159, 216, 0.05);
$orange-light: #fc8a51;
-$orange-normal: #e75e40;
-$orange-dark: #ce5237;
+$orange-normal: darken($orange-light, $darken-normal-factor);
+$orange-dark: darken($orange-light, $darken-dark-factor);
$red-light: #e52c5a;
-$red-normal: #d22852;
-$red-dark: darken($red-normal, 5%);
+$red-normal: darken($red-light, $darken-normal-factor);
+$red-dark: darken($red-light, $darken-dark-factor);
$black: #000;
$black-transparent: rgba(0, 0, 0, 0.3);
-$border-white-light: #f1f2f4;
-$border-white-normal: #d6dae2;
-$border-white-dark: #c6cacf;
+$border-white-light: darken($white-light, $darken-border-factor);
+$border-white-normal: darken($white-normal, $darken-border-factor);
+$border-white-dark: darken($white-dark, $darken-border-factor);
-$border-gray-light: #dcdcdc;
-$border-gray-normal: #d7d7d7;
-$border-gray-dark: #c6cacf;
+$border-gray-light: darken($gray-light, $darken-border-factor);
+$border-gray-normal: darken($gray-normal, $darken-border-factor);
+$border-gray-dark: darken($gray-dark, $darken-border-factor);
$border-green-extra-light: #9adb84;
-$border-green-light: #2faa60;
-$border-green-normal: #2ca05b;
-$border-green-dark: #279654;
+$border-green-light: darken($green-light, $darken-border-factor);
+$border-green-normal: darken($green-normal, $darken-border-factor);
+$border-green-dark: darken($green-dark, $darken-border-factor);
-$border-blue-light: #2d9fd8;
-$border-blue-normal: #2897ce;
-$border-blue-dark: #258dc1;
+$border-blue-light: darken($blue-light, $darken-border-factor);
+$border-blue-normal: darken($blue-normal, $darken-border-factor);
+$border-blue-dark: darken($blue-dark, $darken-border-factor);
-$border-orange-light: #fc6d26;
-$border-orange-normal: #ce5237;
-$border-orange-dark: #c14e35;
+$border-orange-light: darken($orange-light, $darken-border-factor);
+$border-orange-normal: darken($orange-normal, $darken-border-factor);
+$border-orange-dark: darken($orange-dark, $darken-border-factor);
-$border-red-light: #d22852;
-$border-red-normal: #ca264f;
-$border-red-dark: darken($border-red-normal, 5%);
+$border-red-light: darken($red-light, $darken-border-factor);
+$border-red-normal: darken($red-normal, $darken-border-factor);
+$border-red-dark: darken($red-dark, $darken-border-factor);
$help-well-bg: $gray-light;
$help-well-border: #e5e5e5;
@@ -216,7 +220,7 @@ $dropdown-bg: #fff;
$dropdown-link-color: #555;
$dropdown-link-hover-bg: $row-hover;
$dropdown-empty-row-bg: rgba(#000, .04);
-$dropdown-border-color: rgba(#000, .1);
+$dropdown-border-color: $border-color;
$dropdown-shadow-color: rgba(#000, .1);
$dropdown-divider-color: rgba(#000, .1);
$dropdown-header-color: #959494;
@@ -225,13 +229,15 @@ $dropdown-input-color: #555;
$dropdown-input-focus-border: $focus-border-color;
$dropdown-input-focus-shadow: rgba($dropdown-input-focus-border, .4);
$dropdown-loading-bg: rgba(#fff, .6);
+$dropdown-chevron-size: 10px;
$dropdown-toggle-bg: #fff;
-$dropdown-toggle-color: #626262;
-$dropdown-toggle-border-color: #eaeaea;
-$dropdown-toggle-hover-border-color: darken($dropdown-toggle-border-color, 15%);
+$dropdown-toggle-color: #5c5c5c;
+$dropdown-toggle-border-color: #e5e5e5;
+$dropdown-toggle-hover-border-color: darken($dropdown-toggle-border-color, 13%);
+$dropdown-toggle-active-border-color: darken($dropdown-toggle-border-color, 14%);
$dropdown-toggle-icon-color: #c4c4c4;
-$dropdown-toggle-hover-icon-color: $dropdown-toggle-hover-border-color;
+$dropdown-toggle-hover-icon-color: darken($dropdown-toggle-icon-color, 7%);
/*
* Buttons
@@ -255,7 +261,7 @@ $search-input-border-color: rgba(#4688f1, .8);
$search-input-focus-shadow-color: $dropdown-input-focus-shadow;
$search-input-width: 220px;
$location-badge-color: #aaa;
-$location-badge-bg: $gray-normal;
+$location-badge-bg: $dark-background-color;
$location-badge-active-bg: #4f91f8;
$location-icon-color: #e7e9ed;
$location-icon-active-color: #807e7e;
diff --git a/app/assets/stylesheets/mailers/repository_push_email.scss b/app/assets/stylesheets/mailers/highlighted_diff_email.scss
index 8d1a6020ca4..8d1a6020ca4 100644
--- a/app/assets/stylesheets/mailers/repository_push_email.scss
+++ b/app/assets/stylesheets/mailers/highlighted_diff_email.scss
diff --git a/app/assets/stylesheets/pages/boards.scss b/app/assets/stylesheets/pages/boards.scss
index 4f5753f6fc6..4327f8bf640 100644
--- a/app/assets/stylesheets/pages/boards.scss
+++ b/app/assets/stylesheets/pages/boards.scss
@@ -243,7 +243,7 @@
}
.issue-boards-search {
- width: 335px;
+ width: 290px;
.form-control {
display: inline-block;
diff --git a/app/assets/stylesheets/pages/environments.scss b/app/assets/stylesheets/pages/environments.scss
index e9ff43a8adb..4b382e8adaf 100644
--- a/app/assets/stylesheets/pages/environments.scss
+++ b/app/assets/stylesheets/pages/environments.scss
@@ -18,6 +18,31 @@
.environments {
table-layout: fixed;
+ .environments-commit,
+ .environments-actions,
+ .environments-deploy,
+ .environments-build,
+ .environments-date {
+ position: static;
+ float: none;
+ display: table-cell;
+ }
+
+ .environments-commit,
+ .environments-actions {
+ width: 20%;
+ }
+
+ .environments-deploy,
+ .environments-build,
+ .environments-date {
+ width: 10%;
+ }
+
+ .environments-name {
+ width: 30%;
+ }
+
.deployment-column {
.avatar {
float: none;
diff --git a/app/assets/stylesheets/pages/icons.scss b/app/assets/stylesheets/pages/icons.scss
index 407c8db211d..226bd2ead31 100644
--- a/app/assets/stylesheets/pages/icons.scss
+++ b/app/assets/stylesheets/pages/icons.scss
@@ -1,12 +1,51 @@
-// CI icon colors
+.ci-status-icon-success {
+ color: $gl-success;
-.ci-status-icon {
- &-created {
- fill: $gray-darkest;
+ svg {
+ fill: $gl-success;
+ }
+}
+
+.ci-status-icon-failed {
+ color: $gl-danger;
+
+ svg {
+ fill: $gl-danger;
+ }
+}
+
+.ci-status-icon-pending,
+.ci-status-icon-success_with_warnings {
+ color: $gl-warning;
+
+ svg {
+ fill: $gl-warning;
+ }
+}
+
+.ci-status-icon-running {
+ color: $blue-normal;
+
+ svg {
+ fill: $blue-normal;
+ }
+}
+
+.ci-status-icon-canceled,
+.ci-status-icon-disabled,
+.ci-status-icon-not-found {
+ color: $gl-gray;
+
+ svg {
+ fill: $gl-gray;
}
+}
- &-skipped,
- &-canceled {
- fill: $gl-text-color;
+.ci-status-icon-created,
+.ci-status-icon-skipped {
+ color: $gray-darkest;
+
+ svg {
+ fill: $gray-darkest;
}
}
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index 773155fe80a..7aad99eee4e 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -132,7 +132,7 @@
display: none;
}
- .btn-clipboard {
+ .btn-clipboard:hover {
color: $gl-gray;
}
}
@@ -235,6 +235,10 @@
padding-bottom: 10px;
color: #999;
+ &:hover {
+ color: $gl-gray;
+ }
+
span {
display: block;
margin-top: 0;
@@ -244,15 +248,17 @@
display: none;
}
+ .avatar:hover {
+ border-color: #999;
+ }
+
.btn-clipboard {
border: none;
+ color: #999;
&:hover {
background: transparent;
- }
-
- i {
- color: #999;
+ color: $gl-gray;
}
}
}
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index b6a82460f25..da1187af41c 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -24,7 +24,7 @@
.accept_merge_request {
&.ci-pending,
&.ci-running {
- @include btn-orange;
+ @include btn-blue;
}
&.ci-skipped,
@@ -62,6 +62,7 @@
.ci_widget {
border-bottom: 1px solid $well-inner-border;
+ color: $gl-gray;
svg {
margin-right: 4px;
@@ -70,48 +71,12 @@
overflow: visible;
}
- &.ci-success {
- color: $gl-success;
-
- a.environment,
- a.pipeline {
- color: inherit;
- }
- }
-
&.ci-success_with_warnings {
- color: $gl-success;
i {
color: $gl-warning;
}
}
-
- &.ci-skipped {
- background-color: #eee;
- color: #888;
- }
-
- &.ci-pending {
- color: $gl-warning;
- }
-
- &.ci-running {
- color: $blue-normal;
- }
-
- &.ci-failed,
- &.ci-error {
- color: $gl-danger;
- }
-
- &.ci-canceled {
- color: $gl-gray;
- }
-
- a.monospace {
- color: inherit;
- }
}
.mr-widget-body,
diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss
index 0dfd4ab7ec9..e66c1f8d072 100644
--- a/app/assets/stylesheets/pages/notes.scss
+++ b/app/assets/stylesheets/pages/notes.scss
@@ -43,12 +43,25 @@ ul.notes {
}
.system-note-message {
- text-transform: lowercase;
+ display: inline-block;
+
+ &::first-letter {
+ text-transform: lowercase;
+ }
a {
color: $gl-link-color;
text-decoration: none;
}
+
+ p {
+ display: inline-block;
+ margin: 0;
+
+ &::first-letter {
+ text-transform: lowercase;
+ }
+ }
}
.timeline-content {
@@ -62,6 +75,13 @@ ul.notes {
display: none;
padding: 10px 0 0;
cursor: pointer;
+ position: relative;
+ z-index: 2;
+
+ &:hover {
+ color: $gl-link-color;
+ text-decoration: underline;
+ }
}
.note-text {
@@ -87,14 +107,24 @@ ul.notes {
display: none;
}
+ p:last-child {
+ a {
+ color: $gl-text-color;
+
+ &:hover {
+ color: $gl-link-color;
+ }
+ }
+ }
+
&::after {
content: '';
width: 100%;
- height: 20px;
+ height: 67px;
position: absolute;
left: 0;
- bottom: 50px;
- background: linear-gradient(rgba($gray-light, .3) 0, $white-light);
+ bottom: 0;
+ background: linear-gradient(rgba($gray-light, 0.1) -100px, $white-light 100%);
}
&.hide-shade {
@@ -188,11 +218,6 @@ ul.notes {
padding-bottom: 3px;
padding-right: 20px;
- p {
- display: inline;
- margin: 0;
- }
-
@media (min-width: $screen-sm-min) {
padding-right: 0;
}
diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss
index a44a496c728..0027d2caf22 100644
--- a/app/assets/stylesheets/pages/pipelines.scss
+++ b/app/assets/stylesheets/pages/pipelines.scss
@@ -91,14 +91,6 @@
}
}
- .ci-status {
-
- svg {
- top: 1px;
- margin-right: 0;
- }
- }
-
a:hover {
text-decoration: none;
}
@@ -195,7 +187,7 @@
width: 8px;
position: absolute;
right: -7px;
- bottom: 8px;
+ bottom: 9px;
border-bottom: 2px solid $border-color;
}
}
@@ -691,10 +683,3 @@
}
}
}
-
-.ci-status-icon-created {
-
- svg {
- fill: $gray-darkest;
- }
-}
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index 19a7a97ea0d..0562ee7b178 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -876,3 +876,11 @@ pre.light-well {
pointer-events: none;
}
}
+
+.variables-table {
+ table-layout: fixed;
+
+ .variable-key {
+ width: 30%;
+ }
+}
diff --git a/app/assets/stylesheets/pages/settings.scss b/app/assets/stylesheets/pages/settings.scss
index 2e8f356298d..51c926608f9 100644
--- a/app/assets/stylesheets/pages/settings.scss
+++ b/app/assets/stylesheets/pages/settings.scss
@@ -20,3 +20,7 @@
.danger-title {
color: $gl-danger;
}
+
+.service-settings .control-label {
+ padding-top: 0;
+}
diff --git a/app/assets/stylesheets/pages/status.scss b/app/assets/stylesheets/pages/status.scss
index 92997eae8b9..4c258bae1f4 100644
--- a/app/assets/stylesheets/pages/status.scss
+++ b/app/assets/stylesheets/pages/status.scss
@@ -11,80 +11,108 @@
text-decoration: none;
}
+ svg {
+ height: 13px;
+ width: 13px;
+ position: relative;
+ top: 1px;
+ margin-right: 3px;
+ overflow: visible;
+ }
+
&.ci-failed {
color: $gl-danger;
border-color: $gl-danger;
+
+ &:not(span):hover {
+ background-color: rgba( $gl-danger, .07);
+ }
+
+ svg {
+ fill: $gl-danger;
+ }
}
&.ci-success,
&.ci-success_with_warnings {
color: $gl-success;
border-color: $gl-success;
+
+ &:not(span):hover {
+ background-color: rgba( $gl-success, .07);
+ }
+
+ svg {
+ fill: $gl-success;
+ }
}
&.ci-info {
color: $gl-info;
border-color: $gl-info;
+
+ &:not(span):hover {
+ background-color: rgba( $gl-info, .07);
+ }
+
+ svg {
+ fill: $gl-info;
+ }
}
&.ci-canceled,
- &.ci-skipped,
&.ci-disabled {
color: $gl-gray;
border-color: $gl-gray;
+
+ &:not(span):hover {
+ background-color: rgba( $gl-gray, .07);
+ }
+
+ svg {
+ fill: $gl-gray;
+ }
}
&.ci-pending {
color: $gl-warning;
border-color: $gl-warning;
+
+ &:not(span):hover {
+ background-color: rgba( $gl-warning, .07);
+ }
+
+ svg {
+ fill: $gl-warning;
+ }
}
&.ci-running {
color: $blue-normal;
border-color: $blue-normal;
+
+ &:not(span):hover {
+ background-color: rgba( $blue-normal, .07);
+ }
+
+ svg {
+ fill: $blue-normal;
+ }
}
- &.ci-created {
+ &.ci-created,
+ &.ci-skipped {
color: $table-text-gray;
border-color: $table-text-gray;
+ &:not(span):hover {
+ background-color: rgba( $table-text-gray, .07);
+ }
+
svg {
fill: $table-text-gray;
}
}
-
- svg {
- height: 13px;
- width: 13px;
- position: relative;
- top: 1px;
- margin: 0 3px;
- overflow: visible;
- }
- }
-
- .ci-status-icon-success {
- color: $gl-success;
- }
-
- .ci-status-icon-failed {
- color: $gl-danger;
- }
-
- .ci-status-icon-pending,
- .ci-status-icon-success_with_warning {
- color: $gl-warning;
- }
-
- .ci-status-icon-running {
- color: $blue-normal;
- }
-
- .ci-status-icon-canceled,
- .ci-status-icon-disabled,
- .ci-status-icon-not-found,
- .ci-status-icon-skipped {
- color: $gl-gray;
}
}