Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ce into 18608-lock-issues-v2
# Conflicts: # db/schema.rb
This commit is contained in:
commit
c488bcd13e
|
|
@ -8,4 +8,4 @@
|
|||
karma.config.js
|
||||
webpack.config.js
|
||||
svg.config.js
|
||||
/app/assets/javascripts/locale/**/*.js
|
||||
/app/assets/javascripts/locale/**/app.js
|
||||
|
|
|
|||
|
|
@ -404,6 +404,7 @@ docs lint:
|
|||
before_script: []
|
||||
script:
|
||||
- scripts/lint-doc.sh
|
||||
- scripts/lint-changelog-yaml
|
||||
- mv doc/ /nanoc/content/
|
||||
- cd /nanoc
|
||||
# Build HTML from Markdown
|
||||
|
|
|
|||
16
CHANGELOG.md
16
CHANGELOG.md
|
|
@ -2,6 +2,13 @@
|
|||
documentation](doc/development/changelog.md) for instructions on adding your own
|
||||
entry.
|
||||
|
||||
## 10.0.2 (2017-09-27)
|
||||
|
||||
- [FIXED] Notes will not show an empty bubble when the author isn't a member. !14450
|
||||
- [FIXED] Some checks in `rake gitlab:check` were failling with 'undefined method `run_command`'. !14469
|
||||
- [FIXED] Make locked setting of Runner to not affect jobs scheduling. !14483
|
||||
- [FIXED] Re-allow `name` attribute on user-provided anchor HTML.
|
||||
|
||||
## 10.0.1 (2017-09-23)
|
||||
|
||||
- [FIXED] Fix duplicate key errors in PostDeployMigrateUserExternalMailData migration.
|
||||
|
|
@ -78,6 +85,8 @@ entry.
|
|||
- [FIXED] Fixed merge request changes bar jumping.
|
||||
- [FIXED] Improve migrations using triggers.
|
||||
- [FIXED] Fix ConvDev Index nav item and Monitoring submenu regression.
|
||||
- [FIXED] disabling notifications globally now properly turns off group/project added
|
||||
emails !13325
|
||||
- [DEPRECATED] Deprecate custom SSH client configuration for the git user. !13930
|
||||
- [CHANGED] allow all users to delete their account. !13636 (Jacopo Beschi @jacopo-beschi)
|
||||
- [CHANGED] Use full path of project's avatar in webhooks. !13649 (Vitaliy @blackst0ne Klachkov)
|
||||
|
|
@ -186,6 +195,13 @@ entry.
|
|||
- Added type to CHANGELOG entries. (Jacopo Beschi @jacopo-beschi)
|
||||
- [BUGIFX] Improves subgroup creation permissions. !13418
|
||||
|
||||
## 9.5.6 (2017-09-29)
|
||||
|
||||
- [FIXED] Fix MR ready to merge buttons/controls at mobile breakpoint. !14242
|
||||
- [FIXED] Fix errors thrown in merge request widget with external CI service/integration.
|
||||
- [FIXED] Update x/x discussions resolved checkmark icon to be green when all discussions resolved.
|
||||
- [FIXED] Fix 500 error on merged merge requests when GitLab is restored from a backup.
|
||||
|
||||
## 9.5.5 (2017-09-18)
|
||||
|
||||
- [SECURITY] Upgrade mail and nokogiri gems due to security issues. !13662 (Markus Koller)
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ _This notice should stay as the first item in the CONTRIBUTING.md file._
|
|||
Thank you for your interest in contributing to GitLab. This guide details how
|
||||
to contribute to GitLab in a way that is efficient for everyone.
|
||||
|
||||
Looking for something to work on? Look for the label [Accepting Merge Requests](#i-want-to-contribute).
|
||||
Looking for something to work on? Look for issues with the label [Accepting Merge Requests](#i-want-to-contribute).
|
||||
|
||||
GitLab comes into two flavors, GitLab Community Edition (CE) our free and open
|
||||
source edition, and GitLab Enterprise Edition (EE) which is our commercial
|
||||
|
|
@ -101,7 +101,7 @@ the remaining issues on the GitHub issue tracker.
|
|||
## I want to contribute!
|
||||
|
||||
If you want to contribute to GitLab, but are not sure where to start,
|
||||
look for [issues with the label `Accepting Merge Requests` and weight < 5][accepting-mrs-weight].
|
||||
look for [issues with the label `Accepting Merge Requests` and small weight][accepting-mrs-weight].
|
||||
These issues will be of reasonable size and challenge, for anyone to start
|
||||
contributing to GitLab.
|
||||
|
||||
|
|
@ -209,8 +209,7 @@ We add the ~"Accepting Merge Requests" label to:
|
|||
|
||||
- Low priority ~bug issues (i.e. we do not add it to the bugs that we want to
|
||||
solve in the ~"Next Patch Release")
|
||||
- Small ~"feature proposal" that do not need ~UX / ~"Product work", or for which
|
||||
the ~UX / ~"Product work" is already done
|
||||
- Small ~"feature proposal"
|
||||
- Small ~"technical debt" issues
|
||||
|
||||
After adding the ~"Accepting Merge Requests" label, we try to estimate the
|
||||
|
|
@ -223,6 +222,17 @@ know how difficult the issue is. Additionally:
|
|||
- We encourage people that have never contributed to any open source project to
|
||||
look for ["Accepting Merge Requests" issues with a weight of 1][firt-timers]
|
||||
|
||||
If you've decided that you would like to work on an issue, please @-mention
|
||||
the [appropriate product manager](https://about.gitlab.com/handbook/product/#who-to-talk-to-for-what)
|
||||
as soon as possible. The product manager will then pull in appropriate GitLab team
|
||||
members to further discuss scope, design, and technical considerations. This will
|
||||
ensure that that your contribution is aligned with the GitLab product and minimize
|
||||
any rework and delay in getting it merged into master.
|
||||
|
||||
GitLab team members who apply the ~"Accepting Merge Requests" label to an issue
|
||||
should update the issue description with a responsible product manager, inviting
|
||||
any potential community contributor to @-mention per above.
|
||||
|
||||
[up-for-grabs]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=Accepting+Merge+Requests&scope=all&sort=weight_asc&state=opened
|
||||
[firt-timers]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name%5B%5D=Accepting+Merge+Requests&scope=all&sort=upvotes_desc&state=opened&weight=1
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
0.40.0
|
||||
0.43.0
|
||||
|
|
|
|||
|
|
@ -1 +1,2 @@
|
|||
5.9.0
|
||||
5.9.3
|
||||
|
||||
|
|
|
|||
4
Gemfile
4
Gemfile
|
|
@ -26,7 +26,7 @@ gem 'doorkeeper', '~> 4.2.0'
|
|||
gem 'doorkeeper-openid_connect', '~> 1.1.0'
|
||||
gem 'omniauth', '~> 1.4.2'
|
||||
gem 'omniauth-auth0', '~> 1.4.1'
|
||||
gem 'omniauth-azure-oauth2', '~> 0.0.6'
|
||||
gem 'omniauth-azure-oauth2', '~> 0.0.9'
|
||||
gem 'omniauth-cas3', '~> 1.1.4'
|
||||
gem 'omniauth-facebook', '~> 4.0.0'
|
||||
gem 'omniauth-github', '~> 1.1.1'
|
||||
|
|
@ -398,7 +398,7 @@ group :ed25519 do
|
|||
end
|
||||
|
||||
# Gitaly GRPC client
|
||||
gem 'gitaly-proto', '~> 0.33.0', require: 'gitaly'
|
||||
gem 'gitaly-proto', '~> 0.38.0', require: 'gitaly'
|
||||
|
||||
gem 'toml-rb', '~> 0.3.15', require: false
|
||||
|
||||
|
|
|
|||
14
Gemfile.lock
14
Gemfile.lock
|
|
@ -194,7 +194,7 @@ GEM
|
|||
factory_girl_rails (4.7.0)
|
||||
factory_girl (~> 4.7.0)
|
||||
railties (>= 3.0.0)
|
||||
faraday (0.12.1)
|
||||
faraday (0.12.2)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
faraday_middleware (0.11.0.1)
|
||||
faraday (>= 0.7.4, < 1.0)
|
||||
|
|
@ -275,7 +275,7 @@ GEM
|
|||
po_to_json (>= 1.0.0)
|
||||
rails (>= 3.2.0)
|
||||
gherkin-ruby (0.3.2)
|
||||
gitaly-proto (0.33.0)
|
||||
gitaly-proto (0.38.0)
|
||||
google-protobuf (~> 3.1)
|
||||
grpc (~> 1.0)
|
||||
github-linguist (4.7.6)
|
||||
|
|
@ -516,10 +516,10 @@ GEM
|
|||
omniauth-oauth2 (~> 1.1)
|
||||
omniauth-authentiq (0.3.1)
|
||||
omniauth-oauth2 (~> 1.3, >= 1.3.1)
|
||||
omniauth-azure-oauth2 (0.0.6)
|
||||
omniauth-azure-oauth2 (0.0.9)
|
||||
jwt (~> 1.0)
|
||||
omniauth (~> 1.0)
|
||||
omniauth-oauth2 (~> 1.1)
|
||||
omniauth-oauth2 (~> 1.4)
|
||||
omniauth-cas3 (1.1.4)
|
||||
addressable (~> 2.3)
|
||||
nokogiri (~> 1.7, >= 1.7.1)
|
||||
|
|
@ -545,7 +545,7 @@ GEM
|
|||
omniauth-oauth (1.1.0)
|
||||
oauth
|
||||
omniauth (~> 1.0)
|
||||
omniauth-oauth2 (1.3.1)
|
||||
omniauth-oauth2 (1.4.0)
|
||||
oauth2 (~> 1.0)
|
||||
omniauth (~> 1.2)
|
||||
omniauth-oauth2-generic (0.2.2)
|
||||
|
|
@ -1025,7 +1025,7 @@ DEPENDENCIES
|
|||
gettext (~> 3.2.2)
|
||||
gettext_i18n_rails (~> 1.8.0)
|
||||
gettext_i18n_rails_js (~> 1.2.0)
|
||||
gitaly-proto (~> 0.33.0)
|
||||
gitaly-proto (~> 0.38.0)
|
||||
github-linguist (~> 4.7.0)
|
||||
gitlab-flowdock-git-hook (~> 1.0.1)
|
||||
gitlab-markup (~> 1.6.2)
|
||||
|
|
@ -1075,7 +1075,7 @@ DEPENDENCIES
|
|||
omniauth (~> 1.4.2)
|
||||
omniauth-auth0 (~> 1.4.1)
|
||||
omniauth-authentiq (~> 0.3.1)
|
||||
omniauth-azure-oauth2 (~> 0.0.6)
|
||||
omniauth-azure-oauth2 (~> 0.0.9)
|
||||
omniauth-cas3 (~> 1.1.4)
|
||||
omniauth-facebook (~> 4.0.0)
|
||||
omniauth-github (~> 1.1.1)
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
|
|
@ -1 +1 @@
|
|||
{"iconCount":134,"icons":["abuse","account","admin","angle-double-left","angle-down","angle-left","angle-right","angle-up","appearance","applications","approval","arrow-right","assignee","bold","book","branch","calendar","cancel","chevron-down","chevron-left","chevron-right","chevron-up","clock","code","comment-dots","comment-next","comment","comments","commit","credit-card","disk","doc_code","doc_image","doc_text","download","duplicate","earth","eye-slash","eye","file-additions","file-deletion","file-modified","filter","folder","fork","geo-nodes","git-merge","group","history","home","hook","issue-block","issue-child","issue-close","issue-duplicate","issue-new","issue-open-m","issue-open","issue-parent","issues","key-2","key","label","labels","leave","level-up","license","link","list-bulleted","list-numbered","location-dot","location","lock-open","lock","log","mail","merge-request-close-m","merge-request-close","messages","mobile-issue-close","monitor","more","notifications-off","notifications","overview","pencil","pipeline","play","plus-square-o","plus-square","plus","preferences","profile","project","push-rules","question-o","question","quote","redo","remove","repeat","retry","scale","screen-full","screen-normal","search","settings","shield","slight-frown","slight-smile","smile","smiley","snippet","spam","star-o","star","stop","talic","task-done","template","thump-down","thump-up","timer","todo-add","todo-done","token","unapproval","unassignee","unlink","user","users","volume-up","warning","work"]}
|
||||
{"iconCount":135,"spriteSize":58718,"icons":["abuse","account","admin","angle-double-left","angle-double-right","angle-down","angle-left","angle-right","angle-up","appearance","applications","approval","arrow-right","assignee","bold","book","branch","calendar","cancel","chevron-down","chevron-left","chevron-right","chevron-up","clock","close","code","comment-dots","comment-next","comment","comments","commit","credit-card","disk","doc_code","doc_image","doc_text","download","duplicate","earth","eye-slash","eye","file-additions","file-deletion","file-modified","filter","folder","fork","geo-nodes","git-merge","group","history","home","hook","issue-block","issue-child","issue-close","issue-duplicate","issue-new","issue-open-m","issue-open","issue-parent","issues","key-2","key","label","labels","leave","level-up","license","link","list-bulleted","list-numbered","location-dot","location","lock-open","lock","log","mail","merge-request-close","messages","mobile-issue-close","monitor","more","notifications-off","notifications","overview","pencil","pipeline","play","plus-square-o","plus-square","plus","preferences","profile","project","push-rules","question-o","question","quote","redo","remove","repeat","retry","scale","screen-full","screen-normal","search","settings","shield","slight-frown","slight-smile","smile","smiley","snippet","spam","star-o","star","stop","talic","task-done","template","thump-down","thump-up","timer","todo-add","todo-done","token","unapproval","unassignee","unlink","user","users","volume-up","warning","work"]}
|
||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
File diff suppressed because it is too large
Load Diff
|
|
@ -40,10 +40,10 @@ export default () => {
|
|||
class="text-center"
|
||||
v-if="error">
|
||||
<span v-if="loadError">
|
||||
An error occured whilst loading the file. Please try again later.
|
||||
An error occurred whilst loading the file. Please try again later.
|
||||
</span>
|
||||
<span v-else>
|
||||
An error occured whilst parsing the file.
|
||||
An error occurred whilst parsing the file.
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -48,10 +48,10 @@ export default () => {
|
|||
class="text-center"
|
||||
v-if="error">
|
||||
<span v-if="loadError">
|
||||
An error occured whilst loading the file. Please try again later.
|
||||
An error occurred whilst loading the file. Please try again later.
|
||||
</span>
|
||||
<span v-else>
|
||||
An error occured whilst decoding the file.
|
||||
An error occurred whilst decoding the file.
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -77,9 +77,6 @@ $(() => {
|
|||
});
|
||||
Store.rootPath = this.boardsEndpoint;
|
||||
|
||||
this.filterManager = new FilteredSearchBoards(Store.filter, true);
|
||||
this.filterManager.setup();
|
||||
|
||||
// Listen for updateTokens event
|
||||
eventHub.$on('updateTokens', this.updateTokens);
|
||||
},
|
||||
|
|
@ -87,6 +84,9 @@ $(() => {
|
|||
eventHub.$off('updateTokens', this.updateTokens);
|
||||
},
|
||||
mounted () {
|
||||
this.filterManager = new FilteredSearchBoards(Store.filter, true);
|
||||
this.filterManager.setup();
|
||||
|
||||
Store.disabled = this.disabled;
|
||||
gl.boardService.all()
|
||||
.then(response => response.json())
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ export default {
|
|||
<div class="flash-container"
|
||||
v-if="error">
|
||||
<div class="flash-alert">
|
||||
An error occured. Please try again.
|
||||
An error occurred. Please try again.
|
||||
</div>
|
||||
</div>
|
||||
<label class="label-light"
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ window.Build = (function () {
|
|||
Build.prototype.getBuildTrace = function () {
|
||||
return $.ajax({
|
||||
url: `${this.pageUrl}/trace.json`,
|
||||
data: this.state,
|
||||
data: { state: this.state },
|
||||
})
|
||||
.done((log) => {
|
||||
setCiStatusFavicon(`${this.pageUrl}/status.json`);
|
||||
|
|
|
|||
|
|
@ -1,17 +0,0 @@
|
|||
export default {
|
||||
props: {
|
||||
count: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
template: `
|
||||
<span v-if="count === 50" class="events-info pull-right">
|
||||
<i class="fa fa-warning has-tooltip"
|
||||
aria-hidden="true"
|
||||
:title="n__('Limited to showing %d event at most', 'Limited to showing %d events at most', 50)"
|
||||
data-placement="top"></i>
|
||||
{{ n__('Showing %d event', 'Showing %d events', 50) }}
|
||||
</span>
|
||||
`,
|
||||
};
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
<script>
|
||||
import tooltip from '../../vue_shared/directives/tooltip';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
count: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
directives: {
|
||||
tooltip,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<span v-if="count === 50" class="events-info pull-right">
|
||||
<i
|
||||
class="fa fa-warning"
|
||||
v-tooltip
|
||||
aria-hidden="true"
|
||||
:title="n__('Limited to showing %d event at most', 'Limited to showing %d events at most', 50)"
|
||||
data-placement="top"></i>
|
||||
{{ n__('Showing %d event', 'Showing %d events', 50) }}
|
||||
</span>
|
||||
</template>
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
/* eslint-disable no-param-reassign */
|
||||
|
||||
import Vue from 'vue';
|
||||
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||
|
||||
const global = window.gl || (window.gl = {});
|
||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||
|
||||
global.cycleAnalytics.StageCodeComponent = Vue.extend({
|
||||
props: {
|
||||
items: Array,
|
||||
stage: Object,
|
||||
},
|
||||
components: {
|
||||
userAvatarImage,
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<div class="events-description">
|
||||
{{ stage.description }}
|
||||
<limit-warning :count="items.length" />
|
||||
</div>
|
||||
<ul class="stage-event-list">
|
||||
<li v-for="mergeRequest in items" class="stage-event-item">
|
||||
<div class="item-details">
|
||||
<!-- FIXME: Pass an alt attribute here for accessibility -->
|
||||
<user-avatar-image :img-src="mergeRequest.author.avatarUrl"/>
|
||||
<h5 class="item-title merge-merquest-title">
|
||||
<a :href="mergeRequest.url">
|
||||
{{ mergeRequest.title }}
|
||||
</a>
|
||||
</h5>
|
||||
<a :href="mergeRequest.url" class="issue-link">!{{ mergeRequest.iid }}</a>
|
||||
·
|
||||
<span>
|
||||
{{ s__('OpenedNDaysAgo|Opened') }}
|
||||
<a :href="mergeRequest.url" class="issue-date">{{ mergeRequest.createdAt }}</a>
|
||||
</span>
|
||||
<span>
|
||||
{{ s__('ByAuthor|by') }}
|
||||
<a :href="mergeRequest.author.webUrl" class="issue-author-link">{{ mergeRequest.author.name }}</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="item-time">
|
||||
<total-time :time="mergeRequest.totalTime"></total-time>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
`,
|
||||
});
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
<script>
|
||||
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||
import limitWarning from './limit_warning_component.vue';
|
||||
import totalTime from './total_time_component.vue';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
items: Array,
|
||||
stage: Object,
|
||||
},
|
||||
components: {
|
||||
userAvatarImage,
|
||||
limitWarning,
|
||||
totalTime,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<div class="events-description">
|
||||
{{ stage.description }}
|
||||
<limit-warning :count="items.length" />
|
||||
</div>
|
||||
<ul class="stage-event-list">
|
||||
<li v-for="mergeRequest in items" class="stage-event-item">
|
||||
<div class="item-details">
|
||||
<!-- FIXME: Pass an alt attribute here for accessibility -->
|
||||
<user-avatar-image :img-src="mergeRequest.author.avatarUrl"/>
|
||||
<h5 class="item-title merge-merquest-title">
|
||||
<a :href="mergeRequest.url">
|
||||
{{ mergeRequest.title }}
|
||||
</a>
|
||||
</h5>
|
||||
<a :href="mergeRequest.url" class="issue-link">!{{ mergeRequest.iid }}</a>
|
||||
·
|
||||
<span>
|
||||
{{ s__('OpenedNDaysAgo|Opened') }}
|
||||
<a :href="mergeRequest.url" class="issue-date">{{ mergeRequest.createdAt }}</a>
|
||||
</span>
|
||||
<span>
|
||||
{{ s__('ByAuthor|by') }}
|
||||
<a :href="mergeRequest.author.webUrl" class="issue-author-link">{{ mergeRequest.author.name }}</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="item-time">
|
||||
<total-time :time="mergeRequest.totalTime"></total-time>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<script>
|
||||
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||
import limitWarning from './limit_warning_component.vue';
|
||||
import totalTime from './total_time_component.vue';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
items: Array,
|
||||
stage: Object,
|
||||
},
|
||||
components: {
|
||||
userAvatarImage,
|
||||
limitWarning,
|
||||
totalTime,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<div class="events-description">
|
||||
{{ stage.description }}
|
||||
<limit-warning :count="items.length" />
|
||||
</div>
|
||||
<ul class="stage-event-list">
|
||||
<li
|
||||
v-for="(issue, i) in items"
|
||||
:key="i"
|
||||
class="stage-event-item">
|
||||
<div class="item-details">
|
||||
<!-- FIXME: Pass an alt attribute here for accessibility -->
|
||||
<user-avatar-image :img-src="issue.author.avatarUrl"/>
|
||||
<h5 class="item-title issue-title">
|
||||
<a class="issue-title" :href="issue.url">
|
||||
{{ issue.title }}
|
||||
</a>
|
||||
</h5>
|
||||
<a :href="issue.url" class="issue-link">#{{ issue.iid }}</a>
|
||||
·
|
||||
<span>
|
||||
{{ s__('OpenedNDaysAgo|Opened') }}
|
||||
<a :href="issue.url" class="issue-date">{{ issue.createdAt }}</a>
|
||||
</span>
|
||||
<span>
|
||||
{{ s__('ByAuthor|by') }}
|
||||
<a :href="issue.author.webUrl" class="issue-author-link">
|
||||
{{ issue.author.name }}
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="item-time">
|
||||
<total-time :time="issue.totalTime"/>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
/* eslint-disable no-param-reassign */
|
||||
import Vue from 'vue';
|
||||
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||
|
||||
const global = window.gl || (window.gl = {});
|
||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||
|
||||
global.cycleAnalytics.StageIssueComponent = Vue.extend({
|
||||
props: {
|
||||
items: Array,
|
||||
stage: Object,
|
||||
},
|
||||
components: {
|
||||
userAvatarImage,
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<div class="events-description">
|
||||
{{ stage.description }}
|
||||
<limit-warning :count="items.length" />
|
||||
</div>
|
||||
<ul class="stage-event-list">
|
||||
<li v-for="issue in items" class="stage-event-item">
|
||||
<div class="item-details">
|
||||
<!-- FIXME: Pass an alt attribute here for accessibility -->
|
||||
<user-avatar-image :img-src="issue.author.avatarUrl"/>
|
||||
<h5 class="item-title issue-title">
|
||||
<a class="issue-title" :href="issue.url">
|
||||
{{ issue.title }}
|
||||
</a>
|
||||
</h5>
|
||||
<a :href="issue.url" class="issue-link">#{{ issue.iid }}</a>
|
||||
·
|
||||
<span>
|
||||
{{ s__('OpenedNDaysAgo|Opened') }}
|
||||
<a :href="issue.url" class="issue-date">{{ issue.createdAt }}</a>
|
||||
</span>
|
||||
<span>
|
||||
{{ s__('ByAuthor|by') }}
|
||||
<a :href="issue.author.webUrl" class="issue-author-link">
|
||||
{{ issue.author.name }}
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="item-time">
|
||||
<total-time :time="issue.totalTime"></total-time>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
`,
|
||||
});
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
/* eslint-disable no-param-reassign */
|
||||
import Vue from 'vue';
|
||||
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||
import iconCommit from '../svg/icon_commit.svg';
|
||||
|
||||
const global = window.gl || (window.gl = {});
|
||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||
|
||||
global.cycleAnalytics.StagePlanComponent = Vue.extend({
|
||||
props: {
|
||||
items: Array,
|
||||
stage: Object,
|
||||
},
|
||||
components: {
|
||||
userAvatarImage,
|
||||
},
|
||||
data() {
|
||||
return { iconCommit };
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<div class="events-description">
|
||||
{{ stage.description }}
|
||||
<limit-warning :count="items.length" />
|
||||
</div>
|
||||
<ul class="stage-event-list">
|
||||
<li v-for="commit in items" class="stage-event-item">
|
||||
<div class="item-details item-conmmit-component">
|
||||
<!-- FIXME: Pass an alt attribute here for accessibility -->
|
||||
<user-avatar-image :img-src="commit.author.avatarUrl"/>
|
||||
<h5 class="item-title commit-title">
|
||||
<a :href="commit.commitUrl">
|
||||
{{ commit.title }}
|
||||
</a>
|
||||
</h5>
|
||||
<span>
|
||||
{{ s__('FirstPushedBy|First') }}
|
||||
<span class="commit-icon">${iconCommit}</span>
|
||||
<a :href="commit.commitUrl" class="commit-hash-link commit-sha">{{ commit.shortSha }}</a>
|
||||
{{ s__('FirstPushedBy|pushed by') }}
|
||||
<a :href="commit.author.webUrl" class="commit-author-link">
|
||||
{{ commit.author.name }}
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="item-time">
|
||||
<total-time :time="commit.totalTime"></total-time>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
`,
|
||||
});
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
<script>
|
||||
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||
import iconCommit from '../svg/icon_commit.svg';
|
||||
import limitWarning from './limit_warning_component.vue';
|
||||
import totalTime from './total_time_component.vue';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
items: Array,
|
||||
stage: Object,
|
||||
},
|
||||
components: {
|
||||
userAvatarImage,
|
||||
totalTime,
|
||||
limitWarning,
|
||||
},
|
||||
computed: {
|
||||
iconCommit() {
|
||||
return iconCommit;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<div class="events-description">
|
||||
{{ stage.description }}
|
||||
<limit-warning :count="items.length" />
|
||||
</div>
|
||||
<ul class="stage-event-list">
|
||||
<li
|
||||
v-for="(commit, i) in items"
|
||||
:key="i"
|
||||
class="stage-event-item">
|
||||
<div class="item-details item-conmmit-component">
|
||||
<!-- FIXME: Pass an alt attribute here for accessibility -->
|
||||
<user-avatar-image :img-src="commit.author.avatarUrl"/>
|
||||
<h5 class="item-title commit-title">
|
||||
<a :href="commit.commitUrl">
|
||||
{{ commit.title }}
|
||||
</a>
|
||||
</h5>
|
||||
<span>
|
||||
{{ s__('FirstPushedBy|First') }}
|
||||
<span class="commit-icon" v-html="iconCommit"></span>
|
||||
<a :href="commit.commitUrl" class="commit-hash-link commit-sha">{{ commit.shortSha }}</a>
|
||||
{{ s__('FirstPushedBy|pushed by') }}
|
||||
<a :href="commit.author.webUrl" class="commit-author-link">
|
||||
{{ commit.author.name }}
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="item-time">
|
||||
<total-time :time="commit.totalTime" />
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
/* eslint-disable no-param-reassign */
|
||||
import Vue from 'vue';
|
||||
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||
|
||||
const global = window.gl || (window.gl = {});
|
||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||
|
||||
global.cycleAnalytics.StageProductionComponent = Vue.extend({
|
||||
props: {
|
||||
items: Array,
|
||||
stage: Object,
|
||||
},
|
||||
components: {
|
||||
userAvatarImage,
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<div class="events-description">
|
||||
{{ stage.description }}
|
||||
<limit-warning :count="items.length" />
|
||||
</div>
|
||||
<ul class="stage-event-list">
|
||||
<li v-for="issue in items" class="stage-event-item">
|
||||
<div class="item-details">
|
||||
<!-- FIXME: Pass an alt attribute here for accessibility -->
|
||||
<user-avatar-image :img-src="issue.author.avatarUrl"/>
|
||||
<h5 class="item-title issue-title">
|
||||
<a class="issue-title" :href="issue.url">
|
||||
{{ issue.title }}
|
||||
</a>
|
||||
</h5>
|
||||
<a :href="issue.url" class="issue-link">#{{ issue.iid }}</a>
|
||||
·
|
||||
<span>
|
||||
{{ s__('OpenedNDaysAgo|Opened') }}
|
||||
<a :href="issue.url" class="issue-date">{{ issue.createdAt }}</a>
|
||||
</span>
|
||||
<span>
|
||||
{{ s__('ByAuthor|by') }}
|
||||
<a :href="issue.author.webUrl" class="issue-author-link">
|
||||
{{ issue.author.name }}
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="item-time">
|
||||
<total-time :time="issue.totalTime"></total-time>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
`,
|
||||
});
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
/* eslint-disable no-param-reassign */
|
||||
import Vue from 'vue';
|
||||
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||
|
||||
const global = window.gl || (window.gl = {});
|
||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||
|
||||
global.cycleAnalytics.StageReviewComponent = Vue.extend({
|
||||
props: {
|
||||
items: Array,
|
||||
stage: Object,
|
||||
},
|
||||
components: {
|
||||
userAvatarImage,
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<div class="events-description">
|
||||
{{ stage.description }}
|
||||
<limit-warning :count="items.length" />
|
||||
</div>
|
||||
<ul class="stage-event-list">
|
||||
<li v-for="mergeRequest in items" class="stage-event-item">
|
||||
<div class="item-details">
|
||||
<!-- FIXME: Pass an alt attribute here for accessibility -->
|
||||
<user-avatar-image :img-src="mergeRequest.author.avatarUrl"/>
|
||||
<h5 class="item-title merge-merquest-title">
|
||||
<a :href="mergeRequest.url">
|
||||
{{ mergeRequest.title }}
|
||||
</a>
|
||||
</h5>
|
||||
<a :href="mergeRequest.url" class="issue-link">!{{ mergeRequest.iid }}</a>
|
||||
·
|
||||
<span>
|
||||
{{ s__('OpenedNDaysAgo|Opened') }}
|
||||
<a :href="mergeRequest.url" class="issue-date">{{ mergeRequest.createdAt }}</a>
|
||||
</span>
|
||||
<span>
|
||||
{{ s__('ByAuthor|by') }}
|
||||
<a :href="mergeRequest.author.webUrl" class="issue-author-link">{{ mergeRequest.author.name }}</a>
|
||||
</span>
|
||||
<template v-if="mergeRequest.state === 'closed'">
|
||||
<span class="merge-request-state">
|
||||
<i class="fa fa-ban"></i>
|
||||
{{ mergeRequest.state.toUpperCase() }}
|
||||
</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span class="merge-request-branch" v-if="mergeRequest.branch">
|
||||
<i class= "fa fa-code-fork"></i>
|
||||
<a :href="mergeRequest.branch.url">{{ mergeRequest.branch.name }}</a>
|
||||
</span>
|
||||
</template>
|
||||
</div>
|
||||
<div class="item-time">
|
||||
<total-time :time="mergeRequest.totalTime"></total-time>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
`,
|
||||
});
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
<script>
|
||||
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||
import limitWarning from './limit_warning_component.vue';
|
||||
import totalTime from './total_time_component.vue';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
items: Array,
|
||||
stage: Object,
|
||||
},
|
||||
components: {
|
||||
userAvatarImage,
|
||||
totalTime,
|
||||
limitWarning,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<div class="events-description">
|
||||
{{ stage.description }}
|
||||
<limit-warning :count="items.length" />
|
||||
</div>
|
||||
<ul class="stage-event-list">
|
||||
<li
|
||||
v-for="(mergeRequest, i) in items"
|
||||
:key="i"
|
||||
class="stage-event-item">
|
||||
<div class="item-details">
|
||||
<!-- FIXME: Pass an alt attribute here for accessibility -->
|
||||
<user-avatar-image :img-src="mergeRequest.author.avatarUrl"/>
|
||||
<h5 class="item-title merge-merquest-title">
|
||||
<a :href="mergeRequest.url">
|
||||
{{ mergeRequest.title }}
|
||||
</a>
|
||||
</h5>
|
||||
<a :href="mergeRequest.url" class="issue-link">!{{ mergeRequest.iid }}</a>
|
||||
·
|
||||
<span>
|
||||
{{ s__('OpenedNDaysAgo|Opened') }}
|
||||
<a :href="mergeRequest.url" class="issue-date">{{ mergeRequest.createdAt }}</a>
|
||||
</span>
|
||||
<span>
|
||||
{{ s__('ByAuthor|by') }}
|
||||
<a :href="mergeRequest.author.webUrl" class="issue-author-link">{{ mergeRequest.author.name }}</a>
|
||||
</span>
|
||||
<template v-if="mergeRequest.state === 'closed'">
|
||||
<span class="merge-request-state">
|
||||
<i class="fa fa-ban"></i>
|
||||
{{ mergeRequest.state.toUpperCase() }}
|
||||
</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span class="merge-request-branch" v-if="mergeRequest.branch">
|
||||
<i class= "fa fa-code-fork"></i>
|
||||
<a :href="mergeRequest.branch.url">{{ mergeRequest.branch.name }}</a>
|
||||
</span>
|
||||
</template>
|
||||
</div>
|
||||
<div class="item-time">
|
||||
<total-time :time="mergeRequest.totalTime"/>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
/* eslint-disable no-param-reassign */
|
||||
import Vue from 'vue';
|
||||
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||
import iconBranch from '../svg/icon_branch.svg';
|
||||
|
||||
const global = window.gl || (window.gl = {});
|
||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||
|
||||
global.cycleAnalytics.StageStagingComponent = Vue.extend({
|
||||
props: {
|
||||
items: Array,
|
||||
stage: Object,
|
||||
},
|
||||
data() {
|
||||
return { iconBranch };
|
||||
},
|
||||
components: {
|
||||
userAvatarImage,
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<div class="events-description">
|
||||
{{ stage.description }}
|
||||
<limit-warning :count="items.length" />
|
||||
</div>
|
||||
<ul class="stage-event-list">
|
||||
<li v-for="build in items" class="stage-event-item item-build-component">
|
||||
<div class="item-details">
|
||||
<!-- FIXME: Pass an alt attribute here for accessibility -->
|
||||
<user-avatar-image :img-src="build.author.avatarUrl"/>
|
||||
<h5 class="item-title">
|
||||
<a :href="build.url" class="pipeline-id">#{{ build.id }}</a>
|
||||
<i class="fa fa-code-fork"></i>
|
||||
<a :href="build.branch.url" class="ref-name">{{ build.branch.name }}</a>
|
||||
<span class="icon-branch">${iconBranch}</span>
|
||||
<a :href="build.commitUrl" class="commit-sha">{{ build.shortSha }}</a>
|
||||
</h5>
|
||||
<span>
|
||||
<a :href="build.url" class="build-date">{{ build.date }}</a>
|
||||
{{ s__('ByAuthor|by') }}
|
||||
<a :href="build.author.webUrl" class="issue-author-link">
|
||||
{{ build.author.name }}
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="item-time">
|
||||
<total-time :time="build.totalTime"></total-time>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
`,
|
||||
});
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
<script>
|
||||
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||
import iconBranch from '../svg/icon_branch.svg';
|
||||
import limitWarning from './limit_warning_component.vue';
|
||||
import totalTime from './total_time_component.vue';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
items: Array,
|
||||
stage: Object,
|
||||
},
|
||||
components: {
|
||||
userAvatarImage,
|
||||
totalTime,
|
||||
limitWarning,
|
||||
},
|
||||
computed: {
|
||||
iconBranch() {
|
||||
return iconBranch;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<div class="events-description">
|
||||
{{ stage.description }}
|
||||
<limit-warning :count="items.length" />
|
||||
</div>
|
||||
<ul class="stage-event-list">
|
||||
<li
|
||||
v-for="(build, i) in items"
|
||||
class="stage-event-item item-build-component"
|
||||
:key="i">
|
||||
<div class="item-details">
|
||||
<!-- FIXME: Pass an alt attribute here for accessibility -->
|
||||
<user-avatar-image :img-src="build.author.avatarUrl"/>
|
||||
<h5 class="item-title">
|
||||
<a :href="build.url" class="pipeline-id">#{{ build.id }}</a>
|
||||
<i class="fa fa-code-fork"></i>
|
||||
<a :href="build.branch.url" class="ref-name">{{ build.branch.name }}</a>
|
||||
<span class="icon-branch" v-html="iconBranch"></span>
|
||||
<a :href="build.commitUrl" class="commit-sha">{{ build.shortSha }}</a>
|
||||
</h5>
|
||||
<span>
|
||||
<a :href="build.url" class="build-date">{{ build.date }}</a>
|
||||
{{ s__('ByAuthor|by') }}
|
||||
<a :href="build.author.webUrl" class="issue-author-link">
|
||||
{{ build.author.name }}
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="item-time">
|
||||
<total-time :time="build.totalTime"/>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
/* eslint-disable no-param-reassign */
|
||||
import Vue from 'vue';
|
||||
import iconBuildStatus from '../svg/icon_build_status.svg';
|
||||
import iconBranch from '../svg/icon_branch.svg';
|
||||
|
||||
const global = window.gl || (window.gl = {});
|
||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||
|
||||
global.cycleAnalytics.StageTestComponent = Vue.extend({
|
||||
props: {
|
||||
items: Array,
|
||||
stage: Object,
|
||||
},
|
||||
data() {
|
||||
return { iconBuildStatus, iconBranch };
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<div class="events-description">
|
||||
{{ stage.description }}
|
||||
<limit-warning :count="items.length" />
|
||||
</div>
|
||||
<ul class="stage-event-list">
|
||||
<li v-for="build in items" class="stage-event-item item-build-component">
|
||||
<div class="item-details">
|
||||
<h5 class="item-title">
|
||||
<span class="icon-build-status">${iconBuildStatus}</span>
|
||||
<a :href="build.url" class="item-build-name">{{ build.name }}</a>
|
||||
·
|
||||
<a :href="build.url" class="pipeline-id">#{{ build.id }}</a>
|
||||
<i class="fa fa-code-fork"></i>
|
||||
<a :href="build.branch.url" class="ref-name">{{ build.branch.name }}</a>
|
||||
<span class="icon-branch">${iconBranch}</span>
|
||||
<a :href="build.commitUrl" class="commit-sha">{{ build.shortSha }}</a>
|
||||
</h5>
|
||||
<span>
|
||||
<a :href="build.url" class="issue-date">
|
||||
{{ build.date }}
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="item-time">
|
||||
<total-time :time="build.totalTime"></total-time>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
`,
|
||||
});
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
<script>
|
||||
import iconBuildStatus from '../svg/icon_build_status.svg';
|
||||
import iconBranch from '../svg/icon_branch.svg';
|
||||
import limitWarning from './limit_warning_component.vue';
|
||||
import totalTime from './total_time_component.vue';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
items: Array,
|
||||
stage: Object,
|
||||
},
|
||||
components: {
|
||||
totalTime,
|
||||
limitWarning,
|
||||
},
|
||||
computed: {
|
||||
iconBuildStatus() {
|
||||
return iconBuildStatus;
|
||||
},
|
||||
iconBranch() {
|
||||
return iconBranch;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<div class="events-description">
|
||||
{{ stage.description }}
|
||||
<limit-warning :count="items.length" />
|
||||
</div>
|
||||
<ul class="stage-event-list">
|
||||
<li
|
||||
v-for="(build, i) in items"
|
||||
:key="i"
|
||||
class="stage-event-item item-build-component">
|
||||
<div class="item-details">
|
||||
<h5 class="item-title">
|
||||
<span class="icon-build-status" v-html="iconBuildStatus"></span>
|
||||
<a :href="build.url" class="item-build-name">{{ build.name }}</a>
|
||||
·
|
||||
<a :href="build.url" class="pipeline-id">#{{ build.id }}</a>
|
||||
<i class="fa fa-code-fork"></i>
|
||||
<a :href="build.branch.url" class="ref-name">{{ build.branch.name }}</a>
|
||||
<span class="icon-branch" v-html="iconBranch"></span>
|
||||
<a :href="build.commitUrl" class="commit-sha">{{ build.shortSha }}</a>
|
||||
</h5>
|
||||
<span>
|
||||
<a :href="build.url" class="issue-date">
|
||||
{{ build.date }}
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="item-time">
|
||||
<total-time :time="build.totalTime"/>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
/* eslint-disable no-param-reassign */
|
||||
|
||||
import Vue from 'vue';
|
||||
|
||||
const global = window.gl || (window.gl = {});
|
||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||
|
||||
global.cycleAnalytics.TotalTimeComponent = Vue.extend({
|
||||
props: {
|
||||
time: Object,
|
||||
},
|
||||
template: `
|
||||
<span class="total-time">
|
||||
<template v-if="Object.keys(time).length">
|
||||
<template v-if="time.days">{{ time.days }} <span>{{ n__('day', 'days', time.days) }}</span></template>
|
||||
<template v-if="time.hours">{{ time.hours }} <span>{{ n__('Time|hr', 'Time|hrs', time.hours) }}</span></template>
|
||||
<template v-if="time.mins && !time.days">{{ time.mins }} <span>{{ n__('Time|min', 'Time|mins', time.mins) }}</span></template>
|
||||
<template v-if="time.seconds && Object.keys(time).length === 1 || time.seconds === 0">{{ time.seconds }} <span>{{ s__('Time|s') }}</span></template>
|
||||
</template>
|
||||
<template v-else>
|
||||
--
|
||||
</template>
|
||||
</span>
|
||||
`,
|
||||
});
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<script>
|
||||
export default {
|
||||
props: {
|
||||
time: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
hasData() {
|
||||
return Object.keys(this.time).length;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<span class="total-time">
|
||||
<template v-if="hasData">
|
||||
<template v-if="time.days">{{ time.days }} <span>{{ n__('day', 'days', time.days) }}</span></template>
|
||||
<template v-if="time.hours">{{ time.hours }} <span>{{ n__('Time|hr', 'Time|hrs', time.hours) }}</span></template>
|
||||
<template v-if="time.mins && !time.days">{{ time.mins }} <span>{{ n__('Time|min', 'Time|mins', time.mins) }}</span></template>
|
||||
<template v-if="time.seconds && hasDa === 1 || time.seconds === 0">{{ time.seconds }} <span>{{ s__('Time|s') }}</span></template>
|
||||
</template>
|
||||
<template v-else>
|
||||
--
|
||||
</template>
|
||||
</span>
|
||||
</template>
|
||||
|
|
@ -3,15 +3,12 @@
|
|||
import Vue from 'vue';
|
||||
import Cookies from 'js-cookie';
|
||||
import Translate from '../vue_shared/translate';
|
||||
import LimitWarningComponent from './components/limit_warning_component';
|
||||
import './components/stage_code_component';
|
||||
import './components/stage_issue_component';
|
||||
import './components/stage_plan_component';
|
||||
import './components/stage_production_component';
|
||||
import './components/stage_review_component';
|
||||
import './components/stage_staging_component';
|
||||
import './components/stage_test_component';
|
||||
import './components/total_time_component';
|
||||
import stageCodeComponent from './components/stage_code_component.vue';
|
||||
import stagePlanComponent from './components/stage_plan_component.vue';
|
||||
import stageComponent from './components/stage_component.vue';
|
||||
import stageReviewComponent from './components/stage_review_component.vue';
|
||||
import stageStagingComponent from './components/stage_staging_component.vue';
|
||||
import stageTestComponent from './components/stage_test_component.vue';
|
||||
import CycleAnalyticsService from './cycle_analytics_service';
|
||||
import CycleAnalyticsStore from './cycle_analytics_store';
|
||||
|
||||
|
|
@ -47,13 +44,13 @@ $(() => {
|
|||
},
|
||||
},
|
||||
components: {
|
||||
'stage-issue-component': gl.cycleAnalytics.StageIssueComponent,
|
||||
'stage-plan-component': gl.cycleAnalytics.StagePlanComponent,
|
||||
'stage-code-component': gl.cycleAnalytics.StageCodeComponent,
|
||||
'stage-test-component': gl.cycleAnalytics.StageTestComponent,
|
||||
'stage-review-component': gl.cycleAnalytics.StageReviewComponent,
|
||||
'stage-staging-component': gl.cycleAnalytics.StageStagingComponent,
|
||||
'stage-production-component': gl.cycleAnalytics.StageProductionComponent,
|
||||
'stage-issue-component': stageComponent,
|
||||
'stage-plan-component': stagePlanComponent,
|
||||
'stage-code-component': stageCodeComponent,
|
||||
'stage-test-component': stageTestComponent,
|
||||
'stage-review-component': stageReviewComponent,
|
||||
'stage-staging-component': stageStagingComponent,
|
||||
'stage-production-component': stageComponent,
|
||||
},
|
||||
created() {
|
||||
this.fetchCycleAnalyticsData();
|
||||
|
|
@ -134,8 +131,4 @@ $(() => {
|
|||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Register global components
|
||||
Vue.component('limit-warning', LimitWarningComponent);
|
||||
Vue.component('total-time', gl.cycleAnalytics.TotalTimeComponent);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@
|
|||
/* global NotificationsDropdown */
|
||||
/* global GroupAvatar */
|
||||
/* global LineHighlighter */
|
||||
/* global ProjectFork */
|
||||
/* global BuildArtifacts */
|
||||
/* global GroupsSelect */
|
||||
/* global Search */
|
||||
|
|
@ -476,7 +475,9 @@ import { ajaxGet, convertPermissionToBoolean } from './lib/utils/common_utils';
|
|||
shortcut_handler = true;
|
||||
break;
|
||||
case 'projects:forks:new':
|
||||
new ProjectFork();
|
||||
import(/* webpackChunkName: 'project_fork' */ './project_fork')
|
||||
.then(fork => fork.default())
|
||||
.catch(() => {});
|
||||
break;
|
||||
case 'projects:artifacts:browse':
|
||||
new ShortcutsNavigation();
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ export default {
|
|||
|
||||
this.service.postAction(endpoint)
|
||||
.then(() => this.fetchEnvironments())
|
||||
.catch(() => new Flash('An error occured while making the request.'));
|
||||
.catch(() => new Flash('An error occurred while making the request.'));
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -158,7 +158,7 @@ export default {
|
|||
|
||||
this.service.postAction(endpoint)
|
||||
.then(() => this.fetchEnvironments())
|
||||
.catch(() => new Flash('An error occured while making the request.'));
|
||||
.catch(() => new Flash('An error occurred while making the request.'));
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@
|
|||
* causes reflows, visit https://gist.github.com/paulirish/5d52fb081b3570c81e3a
|
||||
*/
|
||||
|
||||
import Cookies from 'js-cookie';
|
||||
|
||||
const LINE_NUMBER_CLASS = 'diff-line-num';
|
||||
const UNFOLDABLE_LINE_CLASS = 'js-unfold';
|
||||
const NO_COMMENT_CLASS = 'no-comment-btn';
|
||||
|
|
@ -27,9 +29,7 @@ export default {
|
|||
this.userCanCreateNote = $diffFile.closest(DIFF_CONTAINER_SELECTOR).data('can-create-note') === '';
|
||||
}
|
||||
|
||||
if (typeof notes !== 'undefined' && !this.isParallelView) {
|
||||
this.isParallelView = notes.isParallelView && notes.isParallelView();
|
||||
}
|
||||
this.isParallelView = Cookies.get('diff_view') === 'parallel';
|
||||
|
||||
if (this.userCanCreateNote) {
|
||||
$diffFile.on('mouseover', LINE_COLUMN_CLASSES, e => this.showButton(this.isParallelView, e))
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ class DropdownEmoji extends gl.FilteredSearchDropdown {
|
|||
loadingTemplate: this.loadingTemplate,
|
||||
onError() {
|
||||
/* eslint-disable no-new */
|
||||
new Flash('An error occured fetching the dropdown data.');
|
||||
new Flash('An error occurred fetching the dropdown data.');
|
||||
/* eslint-enable no-new */
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class DropdownNonUser extends gl.FilteredSearchDropdown {
|
|||
preprocessing,
|
||||
onError() {
|
||||
/* eslint-disable no-new */
|
||||
new Flash('An error occured fetching the dropdown data.');
|
||||
new Flash('An error occurred fetching the dropdown data.');
|
||||
/* eslint-enable no-new */
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class DropdownUser extends gl.FilteredSearchDropdown {
|
|||
},
|
||||
onError() {
|
||||
/* eslint-disable no-new */
|
||||
new Flash('An error occured fetching the dropdown data.');
|
||||
new Flash('An error occurred fetching the dropdown data.');
|
||||
/* eslint-enable no-new */
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ class FilteredSearchManager {
|
|||
.catch((error) => {
|
||||
if (error.name === 'RecentSearchesServiceError') return undefined;
|
||||
// eslint-disable-next-line no-new
|
||||
new window.Flash('An error occured while parsing recent searches');
|
||||
new window.Flash('An error occurred while parsing recent searches');
|
||||
// Gracefully fail to empty array
|
||||
return [];
|
||||
})
|
||||
|
|
|
|||
|
|
@ -67,10 +67,13 @@ const PARTICIPANTS_ROW_COUNT = 7;
|
|||
originalText = $(this).data("original-text");
|
||||
if (currentText === originalText) {
|
||||
$(this).text(lessText);
|
||||
|
||||
if (gl.lazyLoader) gl.lazyLoader.loadCheck();
|
||||
} else {
|
||||
$(this).text(originalText);
|
||||
}
|
||||
return $(".js-participants-hidden").toggle();
|
||||
|
||||
$(".js-participants-hidden").toggle();
|
||||
};
|
||||
|
||||
return IssuableContext;
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ export const handleLocationHash = () => {
|
|||
// This is required to handle non-unicode characters in hash
|
||||
hash = decodeURIComponent(hash);
|
||||
|
||||
const target = document.getElementById(hash) || document.getElementById(`user-content-${hash}`);
|
||||
const fixedTabs = document.querySelector('.js-tabs-affix');
|
||||
const fixedDiffStats = document.querySelector('.js-diff-files-changed.is-stuck');
|
||||
const fixedNav = document.querySelector('.navbar-gitlab');
|
||||
|
|
@ -78,25 +79,19 @@ export const handleLocationHash = () => {
|
|||
let adjustment = 0;
|
||||
if (fixedNav) adjustment -= fixedNav.offsetHeight;
|
||||
|
||||
// scroll to user-generated markdown anchor if we cannot find a match
|
||||
if (document.getElementById(hash) === null) {
|
||||
const target = document.getElementById(`user-content-${hash}`);
|
||||
if (target && target.scrollIntoView) {
|
||||
target.scrollIntoView(true);
|
||||
window.scrollBy(0, adjustment);
|
||||
}
|
||||
} else {
|
||||
// only adjust for fixedTabs when not targeting user-generated content
|
||||
if (fixedTabs) {
|
||||
adjustment -= fixedTabs.offsetHeight;
|
||||
}
|
||||
|
||||
if (fixedDiffStats) {
|
||||
adjustment -= fixedDiffStats.offsetHeight;
|
||||
}
|
||||
|
||||
window.scrollBy(0, adjustment);
|
||||
if (target && target.scrollIntoView) {
|
||||
target.scrollIntoView(true);
|
||||
}
|
||||
|
||||
if (fixedTabs) {
|
||||
adjustment -= fixedTabs.offsetHeight;
|
||||
}
|
||||
|
||||
if (fixedDiffStats) {
|
||||
adjustment -= fixedDiffStats.offsetHeight;
|
||||
}
|
||||
|
||||
window.scrollBy(0, adjustment);
|
||||
};
|
||||
|
||||
// Check if element scrolled into viewport from above or below
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ window.dateFormat = dateFormat;
|
|||
if (!timeagoInstance) {
|
||||
const localeRemaining = function(number, index) {
|
||||
return [
|
||||
[s__('Timeago|less than a minute ago'), s__('Timeago|a while')],
|
||||
[s__('Timeago|less than a minute ago'), s__('Timeago|in a while')],
|
||||
[s__('Timeago|less than a minute ago'), s__('Timeago|%s seconds remaining')],
|
||||
[s__('Timeago|about a minute ago'), s__('Timeago|1 minute remaining')],
|
||||
[s__('Timeago|%s minutes ago'), s__('Timeago|%s minutes remaining')],
|
||||
|
|
@ -73,7 +73,7 @@ window.dateFormat = dateFormat;
|
|||
};
|
||||
locale = function(number, index) {
|
||||
return [
|
||||
[s__('Timeago|less than a minute ago'), s__('Timeago|a while')],
|
||||
[s__('Timeago|less than a minute ago'), s__('Timeago|in a while')],
|
||||
[s__('Timeago|less than a minute ago'), s__('Timeago|in %s seconds')],
|
||||
[s__('Timeago|about a minute ago'), s__('Timeago|in 1 minute')],
|
||||
[s__('Timeago|%s minutes ago'), s__('Timeago|in %s minutes')],
|
||||
|
|
|
|||
|
|
@ -1,14 +1,34 @@
|
|||
export const isSticky = (el, scrollY, stickyTop) => {
|
||||
export const createPlaceholder = () => {
|
||||
const placeholder = document.createElement('div');
|
||||
placeholder.classList.add('sticky-placeholder');
|
||||
|
||||
return placeholder;
|
||||
};
|
||||
|
||||
export const isSticky = (el, scrollY, stickyTop, insertPlaceholder) => {
|
||||
const top = Math.floor(el.offsetTop - scrollY);
|
||||
|
||||
if (top <= stickyTop) {
|
||||
if (top <= stickyTop && !el.classList.contains('is-stuck')) {
|
||||
const placeholder = insertPlaceholder ? createPlaceholder() : null;
|
||||
const heightBefore = el.offsetHeight;
|
||||
|
||||
el.classList.add('is-stuck');
|
||||
} else {
|
||||
|
||||
if (insertPlaceholder) {
|
||||
el.parentNode.insertBefore(placeholder, el.nextElementSibling);
|
||||
|
||||
placeholder.style.height = `${heightBefore - el.offsetHeight}px`;
|
||||
}
|
||||
} else if (top > stickyTop && el.classList.contains('is-stuck')) {
|
||||
el.classList.remove('is-stuck');
|
||||
|
||||
if (insertPlaceholder && el.nextElementSibling && el.nextElementSibling.classList.contains('sticky-placeholder')) {
|
||||
el.nextElementSibling.remove();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default (el) => {
|
||||
export default (el, insertPlaceholder = true) => {
|
||||
if (!el) return;
|
||||
|
||||
const computedStyle = window.getComputedStyle(el);
|
||||
|
|
@ -17,7 +37,7 @@ export default (el) => {
|
|||
|
||||
const stickyTop = parseInt(computedStyle.top, 10);
|
||||
|
||||
document.addEventListener('scroll', () => isSticky(el, window.scrollY, stickyTop), {
|
||||
document.addEventListener('scroll', () => isSticky(el, window.scrollY, stickyTop, insertPlaceholder), {
|
||||
passive: true,
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -28,148 +28,149 @@
|
|||
// </div>
|
||||
// </div>
|
||||
//
|
||||
(function() {
|
||||
this.LineHighlighter = (function() {
|
||||
// CSS class applied to highlighted lines
|
||||
LineHighlighter.prototype.highlightClass = 'hll';
|
||||
|
||||
// Internal copy of location.hash so we're not dependent on `location` in tests
|
||||
LineHighlighter.prototype._hash = '';
|
||||
const LineHighlighter = function(options = {}) {
|
||||
options.highlightLineClass = options.highlightLineClass || 'hll';
|
||||
options.fileHolderSelector = options.fileHolderSelector || '.file-holder';
|
||||
options.scrollFileHolder = options.scrollFileHolder || false;
|
||||
options.hash = options.hash || location.hash;
|
||||
|
||||
function LineHighlighter(hash) {
|
||||
if (hash == null) {
|
||||
// Initialize a LineHighlighter object
|
||||
//
|
||||
// hash - String URL hash for dependency injection in tests
|
||||
hash = location.hash;
|
||||
this.options = options;
|
||||
this._hash = options.hash;
|
||||
this.highlightLineClass = options.highlightLineClass;
|
||||
this.setHash = this.setHash.bind(this);
|
||||
this.highlightLine = this.highlightLine.bind(this);
|
||||
this.clickHandler = this.clickHandler.bind(this);
|
||||
this.highlightHash = this.highlightHash.bind(this);
|
||||
|
||||
this.bindEvents();
|
||||
this.highlightHash();
|
||||
};
|
||||
|
||||
LineHighlighter.prototype.bindEvents = function() {
|
||||
const $fileHolder = $(this.options.fileHolderSelector);
|
||||
|
||||
$fileHolder.on('click', 'a[data-line-number]', this.clickHandler);
|
||||
$fileHolder.on('highlight:line', this.highlightHash);
|
||||
};
|
||||
|
||||
LineHighlighter.prototype.highlightHash = function() {
|
||||
var range;
|
||||
|
||||
if (this._hash !== '') {
|
||||
range = this.hashToRange(this._hash);
|
||||
|
||||
if (range[0]) {
|
||||
this.highlightRange(range);
|
||||
const lineSelector = `#L${range[0]}`;
|
||||
const scrollOptions = {
|
||||
// Scroll to the first highlighted line on initial load
|
||||
// Offset -50 for the sticky top bar, and another -100 for some context
|
||||
offset: -150
|
||||
};
|
||||
if (this.options.scrollFileHolder) {
|
||||
$(this.options.fileHolderSelector).scrollTo(lineSelector, scrollOptions);
|
||||
} else {
|
||||
$.scrollTo(lineSelector, scrollOptions);
|
||||
}
|
||||
this.setHash = this.setHash.bind(this);
|
||||
this.highlightLine = this.highlightLine.bind(this);
|
||||
this.clickHandler = this.clickHandler.bind(this);
|
||||
this.highlightHash = this.highlightHash.bind(this);
|
||||
this._hash = hash;
|
||||
this.bindEvents();
|
||||
this.highlightHash();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
LineHighlighter.prototype.bindEvents = function() {
|
||||
const $fileHolder = $('.file-holder');
|
||||
$fileHolder.on('click', 'a[data-line-number]', this.clickHandler);
|
||||
$fileHolder.on('highlight:line', this.highlightHash);
|
||||
};
|
||||
LineHighlighter.prototype.clickHandler = function(event) {
|
||||
var current, lineNumber, range;
|
||||
event.preventDefault();
|
||||
this.clearHighlight();
|
||||
lineNumber = $(event.target).closest('a').data('line-number');
|
||||
current = this.hashToRange(this._hash);
|
||||
if (!(current[0] && event.shiftKey)) {
|
||||
// If there's no current selection, or there is but Shift wasn't held,
|
||||
// treat this like a single-line selection.
|
||||
this.setHash(lineNumber);
|
||||
return this.highlightLine(lineNumber);
|
||||
} else if (event.shiftKey) {
|
||||
if (lineNumber < current[0]) {
|
||||
range = [lineNumber, current[0]];
|
||||
} else {
|
||||
range = [current[0], lineNumber];
|
||||
}
|
||||
this.setHash(range[0], range[1]);
|
||||
return this.highlightRange(range);
|
||||
}
|
||||
};
|
||||
|
||||
LineHighlighter.prototype.highlightHash = function() {
|
||||
var range;
|
||||
if (this._hash !== '') {
|
||||
range = this.hashToRange(this._hash);
|
||||
if (range[0]) {
|
||||
this.highlightRange(range);
|
||||
$.scrollTo("#L" + range[0], {
|
||||
// Scroll to the first highlighted line on initial load
|
||||
// Offset -50 for the sticky top bar, and another -100 for some context
|
||||
offset: -150
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
LineHighlighter.prototype.clearHighlight = function() {
|
||||
return $("." + this.highlightLineClass).removeClass(this.highlightLineClass);
|
||||
};
|
||||
|
||||
LineHighlighter.prototype.clickHandler = function(event) {
|
||||
var current, lineNumber, range;
|
||||
event.preventDefault();
|
||||
this.clearHighlight();
|
||||
lineNumber = $(event.target).closest('a').data('line-number');
|
||||
current = this.hashToRange(this._hash);
|
||||
if (!(current[0] && event.shiftKey)) {
|
||||
// If there's no current selection, or there is but Shift wasn't held,
|
||||
// treat this like a single-line selection.
|
||||
this.setHash(lineNumber);
|
||||
return this.highlightLine(lineNumber);
|
||||
} else if (event.shiftKey) {
|
||||
if (lineNumber < current[0]) {
|
||||
range = [lineNumber, current[0]];
|
||||
} else {
|
||||
range = [current[0], lineNumber];
|
||||
}
|
||||
this.setHash(range[0], range[1]);
|
||||
return this.highlightRange(range);
|
||||
}
|
||||
};
|
||||
// Convert a URL hash String into line numbers
|
||||
//
|
||||
// hash - Hash String
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// hashToRange('#L5') # => [5, null]
|
||||
// hashToRange('#L5-15') # => [5, 15]
|
||||
// hashToRange('#foo') # => [null, null]
|
||||
//
|
||||
// Returns an Array
|
||||
LineHighlighter.prototype.hashToRange = function(hash) {
|
||||
var first, last, matches;
|
||||
// ?L(\d+)(?:-(\d+))?$/)
|
||||
matches = hash.match(/^#?L(\d+)(?:-(\d+))?$/);
|
||||
if (matches && matches.length) {
|
||||
first = parseInt(matches[1], 10);
|
||||
last = matches[2] ? parseInt(matches[2], 10) : null;
|
||||
return [first, last];
|
||||
} else {
|
||||
return [null, null];
|
||||
}
|
||||
};
|
||||
|
||||
LineHighlighter.prototype.clearHighlight = function() {
|
||||
return $("." + this.highlightClass).removeClass(this.highlightClass);
|
||||
// Unhighlight previously highlighted lines
|
||||
};
|
||||
// Highlight a single line
|
||||
//
|
||||
// lineNumber - Line number to highlight
|
||||
LineHighlighter.prototype.highlightLine = function(lineNumber) {
|
||||
return $("#LC" + lineNumber).addClass(this.highlightLineClass);
|
||||
};
|
||||
|
||||
// Convert a URL hash String into line numbers
|
||||
//
|
||||
// hash - Hash String
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// hashToRange('#L5') # => [5, null]
|
||||
// hashToRange('#L5-15') # => [5, 15]
|
||||
// hashToRange('#foo') # => [null, null]
|
||||
//
|
||||
// Returns an Array
|
||||
LineHighlighter.prototype.hashToRange = function(hash) {
|
||||
var first, last, matches;
|
||||
// ?L(\d+)(?:-(\d+))?$/)
|
||||
matches = hash.match(/^#?L(\d+)(?:-(\d+))?$/);
|
||||
if (matches && matches.length) {
|
||||
first = parseInt(matches[1], 10);
|
||||
last = matches[2] ? parseInt(matches[2], 10) : null;
|
||||
return [first, last];
|
||||
} else {
|
||||
return [null, null];
|
||||
}
|
||||
};
|
||||
// Highlight all lines within a range
|
||||
//
|
||||
// range - Array containing the starting and ending line numbers
|
||||
LineHighlighter.prototype.highlightRange = function(range) {
|
||||
var i, lineNumber, ref, ref1, results;
|
||||
if (range[1]) {
|
||||
results = [];
|
||||
for (lineNumber = i = ref = range[0], ref1 = range[1]; ref <= ref1 ? i <= ref1 : i >= ref1; lineNumber = ref <= ref1 ? (i += 1) : (i -= 1)) {
|
||||
results.push(this.highlightLine(lineNumber));
|
||||
}
|
||||
return results;
|
||||
} else {
|
||||
return this.highlightLine(range[0]);
|
||||
}
|
||||
};
|
||||
|
||||
// Highlight a single line
|
||||
//
|
||||
// lineNumber - Line number to highlight
|
||||
LineHighlighter.prototype.highlightLine = function(lineNumber) {
|
||||
return $("#LC" + lineNumber).addClass(this.highlightClass);
|
||||
};
|
||||
// Set the URL hash string
|
||||
LineHighlighter.prototype.setHash = function(firstLineNumber, lastLineNumber) {
|
||||
var hash;
|
||||
if (lastLineNumber) {
|
||||
hash = "#L" + firstLineNumber + "-" + lastLineNumber;
|
||||
} else {
|
||||
hash = "#L" + firstLineNumber;
|
||||
}
|
||||
this._hash = hash;
|
||||
return this.__setLocationHash__(hash);
|
||||
};
|
||||
|
||||
// Highlight all lines within a range
|
||||
//
|
||||
// range - Array containing the starting and ending line numbers
|
||||
LineHighlighter.prototype.highlightRange = function(range) {
|
||||
var i, lineNumber, ref, ref1, results;
|
||||
if (range[1]) {
|
||||
results = [];
|
||||
for (lineNumber = i = ref = range[0], ref1 = range[1]; ref <= ref1 ? i <= ref1 : i >= ref1; lineNumber = ref <= ref1 ? (i += 1) : (i -= 1)) {
|
||||
results.push(this.highlightLine(lineNumber));
|
||||
}
|
||||
return results;
|
||||
} else {
|
||||
return this.highlightLine(range[0]);
|
||||
}
|
||||
};
|
||||
// Make the actual hash change in the browser
|
||||
//
|
||||
// This method is stubbed in tests.
|
||||
LineHighlighter.prototype.__setLocationHash__ = function(value) {
|
||||
return history.pushState({
|
||||
url: value
|
||||
// We're using pushState instead of assigning location.hash directly to
|
||||
// prevent the page from scrolling on the hashchange event
|
||||
}, document.title, value);
|
||||
};
|
||||
|
||||
// Set the URL hash string
|
||||
LineHighlighter.prototype.setHash = function(firstLineNumber, lastLineNumber) {
|
||||
var hash;
|
||||
if (lastLineNumber) {
|
||||
hash = "#L" + firstLineNumber + "-" + lastLineNumber;
|
||||
} else {
|
||||
hash = "#L" + firstLineNumber;
|
||||
}
|
||||
this._hash = hash;
|
||||
return this.__setLocationHash__(hash);
|
||||
};
|
||||
|
||||
// Make the actual hash change in the browser
|
||||
//
|
||||
// This method is stubbed in tests.
|
||||
LineHighlighter.prototype.__setLocationHash__ = function(value) {
|
||||
return history.pushState({
|
||||
url: value
|
||||
// We're using pushState instead of assigning location.hash directly to
|
||||
// prevent the page from scrolling on the hashchange event
|
||||
}, document.title, value);
|
||||
};
|
||||
|
||||
return LineHighlighter;
|
||||
})();
|
||||
}).call(window);
|
||||
window.LineHighlighter = LineHighlighter;
|
||||
|
|
|
|||
|
|
@ -16,9 +16,8 @@ const locales = allLocales.reduce((d, obj) => {
|
|||
return data;
|
||||
}, {});
|
||||
|
||||
let lang = document.querySelector('html').getAttribute('lang') || 'en';
|
||||
lang = lang.replace(/-/g, '_');
|
||||
|
||||
const langAttribute = document.querySelector('html').getAttribute('lang');
|
||||
const lang = (langAttribute || 'en').replace(/-/g, '_');
|
||||
const locale = new Jed(locales[lang]);
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -124,7 +124,6 @@ import './preview_markdown';
|
|||
import './project';
|
||||
import './project_avatar';
|
||||
import './project_find_file';
|
||||
import './project_fork';
|
||||
import './project_import';
|
||||
import './project_label_subscription';
|
||||
import './project_new';
|
||||
|
|
@ -302,7 +301,10 @@ $(function () {
|
|||
return $container.remove();
|
||||
// Commit show suppressed diff
|
||||
});
|
||||
$('.navbar-toggle').on('click', () => $('.header-content').toggleClass('menu-expanded'));
|
||||
$('.navbar-toggle').on('click', () => {
|
||||
$('.header-content').toggleClass('menu-expanded');
|
||||
gl.lazyLoader.loadCheck();
|
||||
});
|
||||
// Show/hide comments on diff
|
||||
$body.on('click', '.js-toggle-diff-comments', function (e) {
|
||||
var $this = $(this);
|
||||
|
|
|
|||
|
|
@ -352,7 +352,7 @@ import {
|
|||
}
|
||||
|
||||
expandViewContainer() {
|
||||
const $wrapper = $('.content-wrapper .container-fluid');
|
||||
const $wrapper = $('.content-wrapper .container-fluid').not('.breadcrumbs');
|
||||
if (this.fixedLayoutPref === null) {
|
||||
this.fixedLayoutPref = $wrapper.hasClass('container-limited');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@
|
|||
},
|
||||
deleteHandler() {
|
||||
// eslint-disable-next-line no-alert
|
||||
if (confirm('Are you sure you want to delete this list?')) {
|
||||
if (confirm('Are you sure you want to delete this comment?')) {
|
||||
this.isDeleting = true;
|
||||
|
||||
this.deleteNote(this.note)
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
popoverOptions() {
|
||||
return {
|
||||
html: true,
|
||||
delay: { hide: 600 },
|
||||
trigger: 'hover',
|
||||
trigger: 'focus',
|
||||
placement: 'top',
|
||||
title: '<div class="autodevops-title">This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b></div>',
|
||||
content: `<a class="autodevops-link" href="${this.autoDevopsHelpPath}" target="_blank" rel="noopener noreferrer nofollow">Learn more about Auto DevOps</a>`,
|
||||
|
|
@ -75,6 +74,7 @@
|
|||
</span>
|
||||
<a
|
||||
v-if="pipeline.flags.auto_devops"
|
||||
tabindex="0"
|
||||
class="js-pipeline-url-autodevops label label-info autodevops-badge"
|
||||
v-popover="popoverOptions"
|
||||
role="button">
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ export default {
|
|||
postAction(endpoint) {
|
||||
this.service.postAction(endpoint)
|
||||
.then(() => eventHub.$emit('refreshPipelines'))
|
||||
.catch(() => new Flash('An error occured while making the request.'));
|
||||
.catch(() => new Flash('An error occurred while making the request.'));
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -73,7 +73,8 @@ import _ from 'underscore';
|
|||
aspectRatio: 1,
|
||||
modal: true,
|
||||
scalable: false,
|
||||
rotatable: false,
|
||||
rotatable: true,
|
||||
checkOrientation: true,
|
||||
zoomable: true,
|
||||
dragMode: 'move',
|
||||
guides: false,
|
||||
|
|
|
|||
|
|
@ -1,13 +1,8 @@
|
|||
/* eslint-disable func-names, space-before-function-paren, wrap-iife, prefer-arrow-callback, max-len */
|
||||
(function() {
|
||||
this.ProjectFork = (function() {
|
||||
function ProjectFork() {
|
||||
$('.fork-thumbnail a').on('click', function() {
|
||||
$('.fork-namespaces').hide();
|
||||
return $('.save-project-loader').show();
|
||||
});
|
||||
}
|
||||
export default () => {
|
||||
$('.fork-thumbnail a').on('click', function forkThumbnailClicked() {
|
||||
if ($(this).hasClass('disabled')) return false;
|
||||
|
||||
return ProjectFork;
|
||||
})();
|
||||
}).call(window);
|
||||
$('.fork-namespaces').hide();
|
||||
return $('.save-project-loader').show();
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ export default class ProjectsService {
|
|||
|
||||
getSearchedProjects(searchQuery) {
|
||||
return this.projectsPath.get({
|
||||
simple: false,
|
||||
simple: true,
|
||||
per_page: 20,
|
||||
membership: !!gon.current_user_id,
|
||||
order_by: 'last_activity_at',
|
||||
|
|
|
|||
|
|
@ -37,14 +37,14 @@ export default {
|
|||
content: f.newContent,
|
||||
}));
|
||||
const payload = {
|
||||
branch: Store.targetBranch,
|
||||
branch: Store.currentBranch,
|
||||
commit_message: commitMessage,
|
||||
actions,
|
||||
};
|
||||
Store.submitCommitsLoading = true;
|
||||
Service.commitFiles(payload)
|
||||
.then(this.resetCommitState)
|
||||
.catch(() => Flash('An error occured while committing your changes'));
|
||||
.catch(() => Flash('An error occurred while committing your changes'));
|
||||
},
|
||||
|
||||
resetCommitState() {
|
||||
|
|
@ -105,7 +105,7 @@ export default {
|
|||
</label>
|
||||
<div class="col-md-6">
|
||||
<span class="help-block">
|
||||
{{targetBranch}}
|
||||
{{currentBranch}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -26,16 +26,6 @@ export default {
|
|||
this.editMode = !this.editMode;
|
||||
Store.toggleBlobView();
|
||||
},
|
||||
toggleProjectRefsForm() {
|
||||
$('.project-refs-form').toggleClass('disabled', this.editMode);
|
||||
$('.js-tree-ref-target-holder').toggle(this.editMode);
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
editMode() {
|
||||
this.toggleProjectRefsForm();
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ export default RepoFile;
|
|||
</div>
|
||||
</td>
|
||||
|
||||
<td class="hidden-xs">
|
||||
<td class="hidden-xs text-right">
|
||||
<span
|
||||
class="commit-update"
|
||||
:title="tooltipTitle(file.lastCommitUpdate)">
|
||||
|
|
|
|||
|
|
@ -1,23 +1,27 @@
|
|||
<script>
|
||||
/* global LineHighlighter */
|
||||
|
||||
import Store from '../stores/repo_store';
|
||||
|
||||
export default {
|
||||
data: () => Store,
|
||||
mounted() {
|
||||
this.highlightFile();
|
||||
},
|
||||
computed: {
|
||||
html() {
|
||||
return this.activeFile.html;
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
highlightFile() {
|
||||
$(this.$el).find('.file-content').syntaxHighlight();
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.highlightFile();
|
||||
this.lineHighlighter = new LineHighlighter({
|
||||
fileHolderSelector: '.blob-viewer-container',
|
||||
scrollFileHolder: true,
|
||||
});
|
||||
},
|
||||
watch: {
|
||||
html() {
|
||||
this.$nextTick(() => {
|
||||
|
|
@ -45,7 +49,7 @@ export default {
|
|||
v-else
|
||||
class="vertical-center render-error">
|
||||
<p class="text-center">
|
||||
The source could not be displayed because a rendering error occured. You can <a :href="activeFile.raw_path">download</a> it instead.
|
||||
The source could not be displayed because a rendering error occurred. You can <a :href="activeFile.raw_path">download</a> it instead.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -37,17 +37,24 @@ export default {
|
|||
let file = clickedFile;
|
||||
if (file.loading) return;
|
||||
file.loading = true;
|
||||
|
||||
if (file.type === 'tree' && file.opened) {
|
||||
file = Store.removeChildFilesOfTree(file);
|
||||
file.loading = false;
|
||||
} else {
|
||||
Service.url = file.url;
|
||||
Helper.getContent(file)
|
||||
.then(() => {
|
||||
file.loading = false;
|
||||
Helper.scrollTabsRight();
|
||||
})
|
||||
.catch(Helper.loadingError);
|
||||
const openFile = Helper.getFileFromPath(file.url);
|
||||
if (openFile) {
|
||||
file.loading = false;
|
||||
Store.setActiveFiles(openFile);
|
||||
} else {
|
||||
Service.url = file.url;
|
||||
Helper.getContent(file)
|
||||
.then(() => {
|
||||
file.loading = false;
|
||||
Helper.scrollTabsRight();
|
||||
})
|
||||
.catch(Helper.loadingError);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -68,7 +75,7 @@ export default {
|
|||
<tr>
|
||||
<th class="name">Name</th>
|
||||
<th class="hidden-sm hidden-xs last-commit">Last Commit</th>
|
||||
<th class="hidden-xs last-update">Last Update</th>
|
||||
<th class="hidden-xs last-update text-right">Last Update</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
|
|
|||
|
|
@ -58,13 +58,13 @@ const RepoHelper = {
|
|||
return langs.find(lang => lang.extensions && lang.extensions.indexOf(`.${ext}`) > -1);
|
||||
},
|
||||
|
||||
setDirectoryOpen(tree) {
|
||||
setDirectoryOpen(tree, title) {
|
||||
const file = tree;
|
||||
if (!file) return undefined;
|
||||
|
||||
file.opened = true;
|
||||
file.icon = 'fa-folder-open';
|
||||
RepoHelper.updateHistoryEntry(file.url, file.name);
|
||||
RepoHelper.updateHistoryEntry(file.url, title);
|
||||
return file;
|
||||
},
|
||||
|
||||
|
|
@ -135,6 +135,8 @@ const RepoHelper = {
|
|||
return Service.getContent()
|
||||
.then((response) => {
|
||||
const data = response.data;
|
||||
if (response.headers && response.headers['page-title']) data.pageTitle = response.headers['page-title'];
|
||||
|
||||
Store.isTree = RepoHelper.isTree(data);
|
||||
if (!Store.isTree) {
|
||||
if (!file) file = data;
|
||||
|
|
@ -168,7 +170,7 @@ const RepoHelper = {
|
|||
} else {
|
||||
// it's a tree
|
||||
if (!file) Store.isRoot = RepoHelper.isRoot(Service.url);
|
||||
file = RepoHelper.setDirectoryOpen(file);
|
||||
file = RepoHelper.setDirectoryOpen(file, data.pageTitle || data.name);
|
||||
const newDirectory = RepoHelper.dataToListOfFiles(data);
|
||||
Store.addFilesToDirectory(file, Store.files, newDirectory);
|
||||
Store.prevURL = Service.blobURLtoParentTree(Service.url);
|
||||
|
|
@ -178,8 +180,8 @@ const RepoHelper = {
|
|||
|
||||
setFile(data, file) {
|
||||
const newFile = data;
|
||||
newFile.url = file.url || Service.url; // Grab the URL from service, happens on page refresh.
|
||||
|
||||
newFile.url = file.url;
|
||||
if (newFile.render_error === 'too_large' || newFile.render_error === 'collapsed') {
|
||||
newFile.tooLarge = true;
|
||||
}
|
||||
|
|
@ -255,7 +257,7 @@ const RepoHelper = {
|
|||
history.pushState({ key: RepoHelper.key }, '', url);
|
||||
|
||||
if (title) {
|
||||
document.title = `${title} · GitLab`;
|
||||
document.title = title;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -263,6 +265,10 @@ const RepoHelper = {
|
|||
return Store.openedFiles.find(openedFile => Store.activeFile.url === openedFile.url);
|
||||
},
|
||||
|
||||
getFileFromPath(path) {
|
||||
return Store.openedFiles.find(file => file.url === path);
|
||||
},
|
||||
|
||||
loadingError() {
|
||||
Flash('Unable to load this content at this time.');
|
||||
},
|
||||
|
|
|
|||
|
|
@ -11,10 +11,6 @@ function initDropdowns() {
|
|||
}
|
||||
|
||||
function addEventsForNonVueEls() {
|
||||
$(document).on('change', '.dropdown', () => {
|
||||
Store.targetBranch = $('.project-refs-target-form input[name="ref"]').val();
|
||||
});
|
||||
|
||||
window.onbeforeunload = function confirmUnload(e) {
|
||||
const hasChanged = Store.openedFiles
|
||||
.some(file => file.changed);
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ const RepoStore = {
|
|||
isCommitable: false,
|
||||
binary: false,
|
||||
currentBranch: '',
|
||||
targetBranch: 'new-branch',
|
||||
commitMessage: '',
|
||||
binaryTypes: {
|
||||
png: false,
|
||||
|
|
@ -84,7 +83,7 @@ const RepoStore = {
|
|||
}).catch(Helper.loadingError);
|
||||
}
|
||||
|
||||
if (!file.loading) Helper.updateHistoryEntry(file.url, file.name);
|
||||
if (!file.loading) Helper.updateHistoryEntry(file.url, file.pageTitle || file.name);
|
||||
RepoStore.binary = file.binary;
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -29,28 +29,32 @@ import Cookies from 'js-cookie';
|
|||
$('.dropdown').on('loading.gl.dropdown', this.sidebarDropdownLoading);
|
||||
$('.dropdown').on('loaded.gl.dropdown', this.sidebarDropdownLoaded);
|
||||
|
||||
$document.on('click', '.js-sidebar-toggle', function(e, triggered) {
|
||||
var $allGutterToggleIcons, $this, $thisIcon;
|
||||
e.preventDefault();
|
||||
$this = $(this);
|
||||
$thisIcon = $this.find('i');
|
||||
$allGutterToggleIcons = $('.js-sidebar-toggle i');
|
||||
if ($thisIcon.hasClass('fa-angle-double-right')) {
|
||||
$allGutterToggleIcons.removeClass('fa-angle-double-right').addClass('fa-angle-double-left');
|
||||
$('aside.right-sidebar').removeClass('right-sidebar-expanded').addClass('right-sidebar-collapsed');
|
||||
$('.page-with-sidebar').removeClass('right-sidebar-expanded').addClass('right-sidebar-collapsed');
|
||||
} else {
|
||||
$allGutterToggleIcons.removeClass('fa-angle-double-left').addClass('fa-angle-double-right');
|
||||
$('aside.right-sidebar').removeClass('right-sidebar-collapsed').addClass('right-sidebar-expanded');
|
||||
$('.page-with-sidebar').removeClass('right-sidebar-collapsed').addClass('right-sidebar-expanded');
|
||||
}
|
||||
if (!triggered) {
|
||||
return Cookies.set("collapsed_gutter", $('.right-sidebar').hasClass('right-sidebar-collapsed'));
|
||||
}
|
||||
});
|
||||
$document.on('click', '.js-sidebar-toggle', this.sidebarToggleClicked);
|
||||
return $(document).off('click', '.js-issuable-todo').on('click', '.js-issuable-todo', this.toggleTodo);
|
||||
};
|
||||
|
||||
Sidebar.prototype.sidebarToggleClicked = function (e, triggered) {
|
||||
var $allGutterToggleIcons, $this, $thisIcon;
|
||||
e.preventDefault();
|
||||
$this = $(this);
|
||||
$thisIcon = $this.find('i');
|
||||
$allGutterToggleIcons = $('.js-sidebar-toggle i');
|
||||
if ($thisIcon.hasClass('fa-angle-double-right')) {
|
||||
$allGutterToggleIcons.removeClass('fa-angle-double-right').addClass('fa-angle-double-left');
|
||||
$('aside.right-sidebar').removeClass('right-sidebar-expanded').addClass('right-sidebar-collapsed');
|
||||
$('.page-with-sidebar').removeClass('right-sidebar-expanded').addClass('right-sidebar-collapsed');
|
||||
} else {
|
||||
$allGutterToggleIcons.removeClass('fa-angle-double-left').addClass('fa-angle-double-right');
|
||||
$('aside.right-sidebar').removeClass('right-sidebar-collapsed').addClass('right-sidebar-expanded');
|
||||
$('.page-with-sidebar').removeClass('right-sidebar-collapsed').addClass('right-sidebar-expanded');
|
||||
|
||||
if (gl.lazyLoader) gl.lazyLoader.loadCheck();
|
||||
}
|
||||
if (!triggered) {
|
||||
Cookies.set("collapsed_gutter", $('.right-sidebar').hasClass('right-sidebar-collapsed'));
|
||||
}
|
||||
};
|
||||
|
||||
Sidebar.prototype.toggleTodo = function(e) {
|
||||
var $btnText, $this, $todoLoading, ajaxType, url;
|
||||
$this = $(e.currentTarget);
|
||||
|
|
|
|||
|
|
@ -287,6 +287,7 @@ import { isInGroupsPage, isInProjectPage, getGroupSlug, getProjectSlug } from '.
|
|||
|
||||
onClearInputClick(e) {
|
||||
e.preventDefault();
|
||||
this.wrap.toggleClass('has-value', !!e.target.value);
|
||||
return this.searchInput.val('').focus();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ class SidebarMoveIssue {
|
|||
data: (searchTerm, callback) => {
|
||||
this.mediator.fetchAutocompleteProjects(searchTerm)
|
||||
.then(callback)
|
||||
.catch(() => new Flash('An error occured while fetching projects autocomplete.'));
|
||||
.catch(() => new Flash('An error occurred while fetching projects autocomplete.'));
|
||||
},
|
||||
renderRow: project => `
|
||||
<li>
|
||||
|
|
@ -73,7 +73,7 @@ class SidebarMoveIssue {
|
|||
|
||||
this.mediator.moveIssue()
|
||||
.catch(() => {
|
||||
Flash('An error occured while moving the issue.');
|
||||
Flash('An error occurred while moving the issue.');
|
||||
this.$confirmButton
|
||||
.enable()
|
||||
.removeClass('is-loading');
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ export default class SidebarMediator {
|
|||
this.store.setAssigneeData(data);
|
||||
this.store.setTimeTrackingData(data);
|
||||
})
|
||||
.catch(() => new Flash('Error occured when fetching sidebar data'));
|
||||
.catch(() => new Flash('Error occurred when fetching sidebar data'));
|
||||
}
|
||||
|
||||
fetchAutocompleteProjects(searchTerm) {
|
||||
|
|
|
|||
|
|
@ -31,10 +31,12 @@
|
|||
@import "framework/mobile";
|
||||
@import "framework/modal";
|
||||
@import "framework/nav";
|
||||
@import "framework/new-nav";
|
||||
@import "framework/pagination";
|
||||
@import "framework/panels";
|
||||
@import "framework/selects";
|
||||
@import "framework/sidebar";
|
||||
@import "framework/new-sidebar";
|
||||
@import "framework/tables";
|
||||
@import "framework/notes";
|
||||
@import "framework/timeline";
|
||||
|
|
|
|||
|
|
@ -260,7 +260,7 @@
|
|||
position: relative;
|
||||
border: 1px solid $blue-300;
|
||||
border-radius: $border-radius-default;
|
||||
background-color: $blue-25;
|
||||
background-color: $blue-50;
|
||||
justify-content: center;
|
||||
|
||||
.dismiss-button {
|
||||
|
|
|
|||
|
|
@ -779,6 +779,14 @@
|
|||
white-space: normal;
|
||||
width: 100%;
|
||||
|
||||
&.dropdown-menu-user-link {
|
||||
white-space: nowrap;
|
||||
|
||||
.dropdown-menu-user-username {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
// make sure the text color is not overriden
|
||||
&.text-danger {
|
||||
color: $brand-danger;
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@
|
|||
.search-input-wrap {
|
||||
.search-icon,
|
||||
.clear-icon {
|
||||
color: rgba($color-200, .8);
|
||||
fill: rgba($color-200, .8);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -141,7 +141,7 @@
|
|||
|
||||
.search-input-wrap {
|
||||
.search-icon {
|
||||
color: rgba($color-200, .8);
|
||||
fill: rgba($color-200, .8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -242,17 +242,21 @@ body {
|
|||
|
||||
&:hover {
|
||||
background-color: $white-light;
|
||||
box-shadow: inset 0 0 0 1px $blue-100;
|
||||
box-shadow: inset 0 0 0 1px $blue-200;
|
||||
|
||||
.location-badge {
|
||||
box-shadow: inset 0 0 0 1px $blue-100;
|
||||
box-shadow: inset 0 0 0 1px $blue-200;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search-input-wrap {
|
||||
.search-icon {
|
||||
color: $theme-gray-200;
|
||||
fill: $theme-gray-200;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
color: $gl-text-color;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -109,8 +109,7 @@ header {
|
|||
|
||||
.user-counter {
|
||||
svg {
|
||||
height: 16px;
|
||||
width: 23px;
|
||||
margin-right: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -133,16 +132,16 @@ header {
|
|||
}
|
||||
|
||||
&.navbar-gitlab-new {
|
||||
.fa-times {
|
||||
.close-icon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.menu-expanded {
|
||||
.fa-ellipsis-v {
|
||||
.more-icon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.fa-times {
|
||||
.close-icon {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,9 @@
|
|||
}
|
||||
|
||||
svg {
|
||||
&.s8 { @include svg-size(8px); }
|
||||
&.s16 { @include svg-size(16px); }
|
||||
&.s18 { @include svg-size(18px); }
|
||||
&.s24 { @include svg-size(24px); }
|
||||
&.s32 { @include svg-size(32px); }
|
||||
&.s48 { @include svg-size(48px); }
|
||||
|
|
|
|||
|
|
@ -142,5 +142,41 @@
|
|||
}
|
||||
|
||||
@mixin green-status-color {
|
||||
@include status-color($green-50, $green-500, $green-700);
|
||||
@include status-color($green-100, $green-500, $green-700);
|
||||
}
|
||||
|
||||
@mixin fade($gradient-direction, $gradient-color) {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
bottom: 12px;
|
||||
width: 43px;
|
||||
height: 30px;
|
||||
transition-duration: .3s;
|
||||
-webkit-transform: translateZ(0);
|
||||
background: linear-gradient(to $gradient-direction, $gradient-color 45%, rgba($gradient-color, 0.4));
|
||||
|
||||
&.scrolling {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
transition-duration: .3s;
|
||||
}
|
||||
|
||||
.fa {
|
||||
position: relative;
|
||||
top: 5px;
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin scrolling-links() {
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
display: flex;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,38 +1,4 @@
|
|||
@mixin fade($gradient-direction, $gradient-color) {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
bottom: 12px;
|
||||
width: 43px;
|
||||
height: 30px;
|
||||
transition-duration: .3s;
|
||||
-webkit-transform: translateZ(0);
|
||||
background: linear-gradient(to $gradient-direction, $gradient-color 45%, rgba($gradient-color, 0.4));
|
||||
|
||||
&.scrolling {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
transition-duration: .3s;
|
||||
}
|
||||
|
||||
.fa {
|
||||
position: relative;
|
||||
top: 5px;
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin scrolling-links() {
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
display: flex;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
display: flex;
|
||||
|
|
|
|||
|
|
@ -120,17 +120,24 @@ header.navbar-gitlab-new {
|
|||
.container-fluid {
|
||||
.navbar-toggle {
|
||||
min-width: 45px;
|
||||
padding: 4px $gl-padding;
|
||||
padding: 0 $gl-padding;
|
||||
margin-right: -7px;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
color: currentColor;
|
||||
|
||||
svg {
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
&.active {
|
||||
color: currentColor;
|
||||
background-color: transparent;
|
||||
|
||||
svg {
|
||||
fill: currentColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -279,10 +286,6 @@ header.navbar-gitlab-new {
|
|||
}
|
||||
}
|
||||
|
||||
.admin-icon i {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.caret-down {
|
||||
height: 11px;
|
||||
width: 11px;
|
||||
|
|
@ -295,75 +298,6 @@ header.navbar-gitlab-new {
|
|||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.search {
|
||||
margin: 4px 8px 0;
|
||||
|
||||
form {
|
||||
height: 32px;
|
||||
border: 0;
|
||||
border-radius: $border-radius-default;
|
||||
transition: border-color ease-in-out 0.15s, background-color ease-in-out 0.15s;
|
||||
|
||||
&:hover {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.search-active form {
|
||||
box-shadow: none;
|
||||
|
||||
.search-input {
|
||||
color: $gl-text-color;
|
||||
transition: color ease-in-out 0.15s;
|
||||
}
|
||||
|
||||
.search-input::placeholder {
|
||||
color: $gl-text-color-tertiary;
|
||||
}
|
||||
|
||||
.search-input-wrap {
|
||||
.search-icon,
|
||||
.clear-icon {
|
||||
color: $gl-text-color-tertiary;
|
||||
transition: color ease-in-out 0.15s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search-input {
|
||||
color: $white-light;
|
||||
background: none;
|
||||
transition: color ease-in-out 0.15s;
|
||||
}
|
||||
|
||||
.search-input::placeholder {
|
||||
transition: color ease-in-out 0.15s;
|
||||
}
|
||||
|
||||
.location-badge {
|
||||
font-size: 12px;
|
||||
margin: -4px 4px -4px -4px;
|
||||
line-height: 25px;
|
||||
padding: 4px 8px;
|
||||
border-radius: 2px 0 0 2px;
|
||||
height: 32px;
|
||||
transition: border-color ease-in-out 0.15s;
|
||||
}
|
||||
|
||||
&.search-active {
|
||||
.location-badge {
|
||||
background-color: $nav-badge-bg;
|
||||
border-color: $border-color;
|
||||
}
|
||||
|
||||
.search-input-wrap {
|
||||
.clear-icon {
|
||||
color: $white-light;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.breadcrumbs {
|
||||
display: flex;
|
||||
min-height: 48px;
|
||||
|
|
@ -375,6 +309,8 @@ header.navbar-gitlab-new {
|
|||
display: flex;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
padding-top: $gl-padding / 2;
|
||||
padding-bottom: $gl-padding / 2;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid $border-color;
|
||||
}
|
||||
|
|
@ -386,11 +322,6 @@ header.navbar-gitlab-new {
|
|||
align-self: center;
|
||||
color: $gl-text-color-secondary;
|
||||
|
||||
@media (max-width: $screen-xs-max) {
|
||||
padding-left: 17px;
|
||||
border-left: 1px solid $gl-text-color-quaternary;
|
||||
}
|
||||
|
||||
.avatar-tile {
|
||||
margin-right: 4px;
|
||||
border: 1px solid $border-color;
|
||||
|
|
@ -420,6 +351,7 @@ header.navbar-gitlab-new {
|
|||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
padding: 2px 0;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-right: 20px;
|
||||
|
|
@ -455,7 +387,7 @@ header.navbar-gitlab-new {
|
|||
margin: 0;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
line-height: 1;
|
||||
line-height: 16px;
|
||||
|
||||
a {
|
||||
color: $gl-text-color;
|
||||
|
|
@ -56,8 +56,8 @@ $new-sidebar-collapsed-width: 50px;
|
|||
color: $hover-color;
|
||||
|
||||
.settings-avatar {
|
||||
i {
|
||||
color: $hover-color;
|
||||
svg {
|
||||
fill: $hover-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -76,12 +76,9 @@ $new-sidebar-collapsed-width: 50px;
|
|||
.settings-avatar {
|
||||
background-color: $white-light;
|
||||
|
||||
i {
|
||||
font-size: 20px;
|
||||
width: 100%;
|
||||
color: $gl-text-color-secondary;
|
||||
text-align: center;
|
||||
align-self: center;
|
||||
svg {
|
||||
fill: $gl-text-color-secondary;
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -177,16 +174,16 @@ $new-sidebar-collapsed-width: 50px;
|
|||
.nav-icon-container {
|
||||
display: flex;
|
||||
margin-right: 8px;
|
||||
|
||||
svg {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.fly-out-top-item {
|
||||
display: none;
|
||||
}
|
||||
|
||||
svg {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-sidebar-inner-scroll {
|
||||
|
|
@ -354,18 +351,22 @@ $new-sidebar-collapsed-width: 50px;
|
|||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
i {
|
||||
font-size: 20px;
|
||||
svg {
|
||||
fill: $gl-text-color-secondary;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.fa-angle-double-right {
|
||||
.icon-angle-double-right {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: $border-color;
|
||||
color: $gl-text-color;
|
||||
|
||||
svg {
|
||||
fill: $gl-text-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -407,15 +408,16 @@ $new-sidebar-collapsed-width: 50px;
|
|||
|
||||
.toggle-sidebar-button {
|
||||
width: $new-sidebar-collapsed-width - 2px;
|
||||
padding: 16px 18px;
|
||||
padding: 16px;
|
||||
|
||||
.collapse-text,
|
||||
.fa-angle-double-left {
|
||||
.icon-angle-double-left {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.fa-angle-double-right {
|
||||
.icon-angle-double-right {
|
||||
display: block;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -461,6 +463,13 @@ $new-sidebar-collapsed-width: 50px;
|
|||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: $screen-xs-max) {
|
||||
+ .breadcrumbs-links {
|
||||
padding-left: 17px;
|
||||
border-left: 1px solid $gl-text-color-quaternary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: $screen-xs-max) {
|
||||
|
|
@ -137,7 +137,7 @@ $well-border: #eee;
|
|||
//##
|
||||
|
||||
$code-color: $red-600;
|
||||
$code-bg: lighten($red-50, 2%);
|
||||
$code-bg: lighten($red-100, 2%);
|
||||
|
||||
$kbd-color: $white-light;
|
||||
$kbd-bg: #333;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ $gutter_width: 290px;
|
|||
$gutter_inner_width: 250px;
|
||||
$sidebar-transition-duration: .15s;
|
||||
$sidebar-breakpoint: 1024px;
|
||||
$default-transition-duration: .15s;
|
||||
$right-sidebar-transition-duration: .3s;
|
||||
|
||||
/*
|
||||
* Color schema
|
||||
|
|
@ -27,46 +29,45 @@ $gray-dark: darken($gray-light, $darken-dark-factor);
|
|||
$gray-darker: #eee;
|
||||
$gray-darkest: #c4c4c4;
|
||||
|
||||
$green-25: #f6fcf8;
|
||||
$green-50: #e4f5eb;
|
||||
$green-100: #bae6cc;
|
||||
$green-200: #8dd5aa;
|
||||
$green-300: #5fc488;
|
||||
$green-400: #3cb76f;
|
||||
$green-50: #f1fdf6;
|
||||
$green-100: #dcf5e7;
|
||||
$green-200: #b3e6c8;
|
||||
$green-300: #75d09b;
|
||||
$green-400: #37b96d;
|
||||
$green-500: #1aaa55;
|
||||
$green-600: #168f48;
|
||||
$green-700: #12753a;
|
||||
$green-800: #0e5a2d;
|
||||
$green-900: #0a4020;
|
||||
$green-950: #072b15;
|
||||
|
||||
$blue-25: #f6fafd;
|
||||
$blue-50: #e4eff9;
|
||||
$blue-100: #bcd7f1;
|
||||
$blue-200: #8fbce8;
|
||||
$blue-300: #62a1df;
|
||||
$blue-400: #418cd8;
|
||||
$blue-50: #f6fafe;
|
||||
$blue-100: #e4f0fb;
|
||||
$blue-200: #b8d6f4;
|
||||
$blue-300: #73afea;
|
||||
$blue-400: #2e87e0;
|
||||
$blue-500: #1f78d1;
|
||||
$blue-600: #1b69b6;
|
||||
$blue-700: #17599c;
|
||||
$blue-800: #134a81;
|
||||
$blue-900: #0f3b66;
|
||||
$blue-950: #0a2744;
|
||||
|
||||
$orange-25: #fffcf8;
|
||||
$orange-50: #fff2e1;
|
||||
$orange-100: #fedfb3;
|
||||
$orange-200: #feca81;
|
||||
$orange-300: #fdb44f;
|
||||
$orange-400: #fca429;
|
||||
$orange-50: #fffaf4;
|
||||
$orange-100: #fff1de;
|
||||
$orange-200: #fed69f;
|
||||
$orange-300: #fdbc60;
|
||||
$orange-400: #fca121;
|
||||
$orange-500: #fc9403;
|
||||
$orange-600: #de7e00;
|
||||
$orange-700: #c26700;
|
||||
$orange-800: #a35100;
|
||||
$orange-900: #853b00;
|
||||
$orange-800: #a35200;
|
||||
$orange-900: #853c00;
|
||||
$orange-950: #592800;
|
||||
|
||||
$red-25: #fef7f6;
|
||||
$red-50: #fbe7e4;
|
||||
$red-100: #f4c4bc;
|
||||
$red-200: #ed9d90;
|
||||
$red-50: #fef6f5;
|
||||
$red-100: #fbe5e1;
|
||||
$red-200: #f2b4a9;
|
||||
$red-300: #e67664;
|
||||
$red-400: #e05842;
|
||||
$red-500: #db3b21;
|
||||
|
|
@ -74,6 +75,7 @@ $red-600: #c0341d;
|
|||
$red-700: #a62d19;
|
||||
$red-800: #8b2615;
|
||||
$red-900: #711e11;
|
||||
$red-950: #4b140b;
|
||||
|
||||
// GitLab themes
|
||||
|
||||
|
|
@ -184,8 +186,8 @@ $list-text-disabled-color: $gl-text-color-tertiary;
|
|||
$list-border-light: #eee;
|
||||
$list-border: rgba(0, 0, 0, 0.05);
|
||||
$list-text-height: 42px;
|
||||
$list-warning-row-bg: $orange-50;
|
||||
$list-warning-row-border: $orange-100;
|
||||
$list-warning-row-bg: $orange-100;
|
||||
$list-warning-row-border: $orange-200;
|
||||
$list-warning-row-color: $orange-700;
|
||||
|
||||
/*
|
||||
|
|
@ -214,8 +216,8 @@ $gl-sidebar-padding: 22px;
|
|||
/*
|
||||
* Misc
|
||||
*/
|
||||
$row-hover: $blue-25;
|
||||
$row-hover-border: $blue-100;
|
||||
$row-hover: $blue-50;
|
||||
$row-hover-border: $blue-200;
|
||||
$progress-color: #c0392b;
|
||||
$header-height: 50px;
|
||||
$new-navbar-height: 40px;
|
||||
|
|
@ -265,8 +267,8 @@ $time-color: #999;
|
|||
$project-member-show-color: #aaa;
|
||||
$gl-promo-color: #aaa;
|
||||
$error-bg: $red-400;
|
||||
$warning-message-bg: $orange-50;
|
||||
$warning-message-border: $orange-100;
|
||||
$warning-message-bg: $orange-100;
|
||||
$warning-message-border: $orange-200;
|
||||
$warning-message-color: $orange-700;
|
||||
$control-group-descr-color: #666;
|
||||
$table-permission-x-bg: #d9edf7;
|
||||
|
|
@ -451,17 +453,17 @@ $builds-trace-bg: #111;
|
|||
/*
|
||||
* Callout
|
||||
*/
|
||||
$callout-danger-bg: $red-50;
|
||||
$callout-danger-border: $red-100;
|
||||
$callout-danger-bg: $red-100;
|
||||
$callout-danger-border: $red-200;
|
||||
$callout-danger-color: $red-700;
|
||||
$callout-warning-bg: $orange-50;
|
||||
$callout-warning-border: $orange-100;
|
||||
$callout-warning-bg: $orange-100;
|
||||
$callout-warning-border: $orange-200;
|
||||
$callout-warning-color: $orange-700;
|
||||
$callout-info-bg: $blue-50;
|
||||
$callout-info-border: $blue-100;
|
||||
$callout-info-bg: $blue-100;
|
||||
$callout-info-border: $blue-200;
|
||||
$callout-info-color: $blue-700;
|
||||
$callout-success-bg: $green-50;
|
||||
$callout-success-border: $green-100;
|
||||
$callout-success-bg: $green-100;
|
||||
$callout-success-border: $green-200;
|
||||
$callout-success-color: $green-700;
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -55,6 +55,15 @@
|
|||
|
||||
.boards-app {
|
||||
position: relative;
|
||||
|
||||
@media (min-width: $screen-sm-min) {
|
||||
transition: width $right-sidebar-transition-duration;
|
||||
width: 100%;
|
||||
|
||||
&.is-compact {
|
||||
width: calc(100% - #{$gutter_width});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.boards-app-loading {
|
||||
|
|
@ -78,11 +87,6 @@
|
|||
height: calc(100vh - 222px);
|
||||
// scss-lint:enable DuplicateProperty
|
||||
min-height: 475px;
|
||||
transition: width .2s;
|
||||
|
||||
&.is-compact {
|
||||
width: calc(100% - 290px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -412,14 +416,6 @@
|
|||
|
||||
.page-with-layout-nav.page-with-sub-nav .issue-boards-sidebar,
|
||||
.page-with-new-sidebar.page-with-sidebar .issue-boards-sidebar {
|
||||
position: absolute;
|
||||
|
||||
&.right-sidebar {
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.issuable-sidebar-header {
|
||||
position: relative;
|
||||
}
|
||||
|
|
@ -457,8 +453,8 @@
|
|||
.right-sidebar.right-sidebar-expanded {
|
||||
&.boards-sidebar-slide-enter-active,
|
||||
&.boards-sidebar-slide-leave-active {
|
||||
transition: width .2s,
|
||||
padding .2s;
|
||||
transition: width $right-sidebar-transition-duration,
|
||||
padding $right-sidebar-transition-duration;
|
||||
}
|
||||
|
||||
&.boards-sidebar-slide-enter,
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ $space-between-cards: 8px;
|
|||
border-top-color: $color-low-score;
|
||||
|
||||
.card-score-big {
|
||||
background-color: $red-25;
|
||||
background-color: $red-50;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -91,7 +91,7 @@ $space-between-cards: 8px;
|
|||
border-top-color: $color-average-score;
|
||||
|
||||
.card-score-big {
|
||||
background-color: $orange-25;
|
||||
background-color: $orange-50;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -99,7 +99,7 @@ $space-between-cards: 8px;
|
|||
border-top-color: $color-high-score;
|
||||
|
||||
.card-score-big {
|
||||
background-color: $green-25;
|
||||
background-color: $green-50;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -451,7 +451,7 @@
|
|||
}
|
||||
|
||||
.files {
|
||||
margin-top: -1px;
|
||||
margin-top: 1px;
|
||||
|
||||
.diff-file:last-child {
|
||||
margin-bottom: 0;
|
||||
|
|
@ -535,7 +535,6 @@
|
|||
}
|
||||
|
||||
.diff-notes-collapse {
|
||||
position: relative;
|
||||
width: 19px;
|
||||
height: 19px;
|
||||
padding: 0;
|
||||
|
|
@ -543,11 +542,7 @@
|
|||
z-index: 100;
|
||||
|
||||
svg {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
margin-left: -5.5px;
|
||||
margin-top: -5.5px;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
|
||||
path {
|
||||
|
|
@ -586,11 +581,6 @@
|
|||
top: 76px;
|
||||
}
|
||||
|
||||
+ .files,
|
||||
+ .alert {
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
&:not(.is-stuck) .diff-stats-additions-deletions-collapsed {
|
||||
display: none;
|
||||
}
|
||||
|
|
@ -605,11 +595,6 @@
|
|||
.inline-parallel-buttons {
|
||||
display: none;
|
||||
}
|
||||
|
||||
+ .files,
|
||||
+ .alert {
|
||||
margin-top: 32px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
.issuable-warning-icon {
|
||||
color: $orange-600;
|
||||
background-color: $orange-50;
|
||||
background-color: $orange-100;
|
||||
border-radius: $border-radius-default;
|
||||
padding: 5px;
|
||||
margin: 0 $btn-side-margin 0 0;
|
||||
|
|
@ -221,14 +221,14 @@
|
|||
top: $new-navbar-height;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
transition: width .3s;
|
||||
transition: width $right-sidebar-transition-duration;
|
||||
background: $gray-light;
|
||||
z-index: 200;
|
||||
overflow: hidden;
|
||||
|
||||
.issuable-sidebar {
|
||||
width: calc(100% + 100px);
|
||||
height: calc(100% - #{$new-navbar-height});
|
||||
height: 100%;
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
|
|
|
|||
|
|
@ -255,7 +255,7 @@ $colors: (
|
|||
|
||||
&.saved {
|
||||
.editor {
|
||||
border-top: solid 2px $green-200;
|
||||
border-top: solid 2px $green-300;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@
|
|||
|
||||
.issuable-note-warning {
|
||||
color: $orange-600;
|
||||
background-color: $orange-50;
|
||||
background-color: $orange-100;
|
||||
border-radius: $border-radius-default $border-radius-default 0 0;
|
||||
border: 1px solid $border-gray-normal;
|
||||
border-bottom: none;
|
||||
|
|
|
|||
|
|
@ -644,20 +644,20 @@ button.mini-pipeline-graph-dropdown-toggle {
|
|||
|
||||
// Dropdown button animation in mini pipeline graph
|
||||
&.ci-status-icon-success {
|
||||
@include mini-pipeline-graph-color($green-50, $green-500, $green-600);
|
||||
@include mini-pipeline-graph-color($green-100, $green-500, $green-600);
|
||||
}
|
||||
|
||||
&.ci-status-icon-failed {
|
||||
@include mini-pipeline-graph-color($red-50, $red-500, $red-600);
|
||||
@include mini-pipeline-graph-color($red-100, $red-500, $red-600);
|
||||
}
|
||||
|
||||
&.ci-status-icon-pending,
|
||||
&.ci-status-icon-success_with_warnings {
|
||||
@include mini-pipeline-graph-color($orange-50, $orange-500, $orange-600);
|
||||
@include mini-pipeline-graph-color($orange-100, $orange-500, $orange-600);
|
||||
}
|
||||
|
||||
&.ci-status-icon-running {
|
||||
@include mini-pipeline-graph-color($blue-50, $blue-400, $blue-600);
|
||||
@include mini-pipeline-graph-color($blue-100, $blue-400, $blue-600);
|
||||
}
|
||||
|
||||
&.ci-status-icon-canceled,
|
||||
|
|
|
|||
|
|
@ -291,7 +291,7 @@ table.u2f-registrations {
|
|||
.bordered-box {
|
||||
border: 1px solid $blue-300;
|
||||
border-radius: $border-radius-default;
|
||||
background-color: $blue-25;
|
||||
background-color: $blue-50;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
|
@ -379,7 +379,7 @@ table.u2f-registrations {
|
|||
|
||||
.nav-wip {
|
||||
border: 1px solid $blue-500;
|
||||
background: $blue-25;
|
||||
background: $blue-50;
|
||||
padding: $gl-padding;
|
||||
margin-bottom: $gl-padding;
|
||||
|
||||
|
|
|
|||
|
|
@ -516,7 +516,7 @@ a.deploy-project-label {
|
|||
text-align: center;
|
||||
width: 169px;
|
||||
|
||||
&:hover,
|
||||
&:hover:not(.disabled),
|
||||
&.forked {
|
||||
background-color: $row-hover;
|
||||
border-color: $row-hover-border;
|
||||
|
|
@ -543,6 +543,15 @@ a.deploy-project-label {
|
|||
padding-top: $gl-padding;
|
||||
color: $gl-text-color;
|
||||
|
||||
&.disabled {
|
||||
opacity: .3;
|
||||
cursor: not-allowed;
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
.caption {
|
||||
min-height: 30px;
|
||||
padding: $gl-padding 0;
|
||||
|
|
|
|||
|
|
@ -54,6 +54,10 @@
|
|||
border-radius: $border-radius-default;
|
||||
color: $almost-black;
|
||||
|
||||
.code.white pre .hll {
|
||||
background-color: $well-light-border !important;
|
||||
}
|
||||
|
||||
.tree-content-holder {
|
||||
display: flex;
|
||||
min-height: 300px;
|
||||
|
|
|
|||
|
|
@ -28,9 +28,7 @@ input[type="checkbox"]:hover {
|
|||
}
|
||||
|
||||
.search {
|
||||
margin-right: 10px;
|
||||
margin-left: 10px;
|
||||
margin-top: ($header-height - 35) / 2;
|
||||
margin: 4px 8px 0;
|
||||
|
||||
form {
|
||||
@extend .form-control;
|
||||
|
|
@ -38,15 +36,23 @@ input[type="checkbox"]:hover {
|
|||
padding: 4px;
|
||||
width: $search-input-width;
|
||||
line-height: 24px;
|
||||
height: 32px;
|
||||
border: 0;
|
||||
border-radius: $border-radius-default;
|
||||
transition: border-color ease-in-out $default-transition-duration, background-color ease-in-out $default-transition-duration;
|
||||
|
||||
&:hover {
|
||||
border-color: lighten($dropdown-input-focus-border, 20%);
|
||||
box-shadow: 0 0 4px lighten($search-input-focus-shadow-color, 20%);
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
.location-text {
|
||||
font-style: normal;
|
||||
.location-badge {
|
||||
font-size: 12px;
|
||||
margin: -4px 4px -4px -4px;
|
||||
line-height: 25px;
|
||||
padding: 4px 8px;
|
||||
border-radius: $border-radius-default 0 0 $border-radius-default;
|
||||
transition: border-color ease-in-out $default-transition-duration;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
|
|
@ -56,59 +62,36 @@ input[type="checkbox"]:hover {
|
|||
margin-left: 5px;
|
||||
line-height: 25px;
|
||||
width: 98%;
|
||||
color: $white-light;
|
||||
background: none;
|
||||
transition: color ease-in-out $default-transition-duration;
|
||||
}
|
||||
|
||||
.location-badge {
|
||||
line-height: 25px;
|
||||
padding: 0 5px;
|
||||
border-radius: $border-radius-default;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
color: $note-disabled-comment-color;
|
||||
display: inline-block;
|
||||
background-color: $gray-normal;
|
||||
vertical-align: top;
|
||||
cursor: default;
|
||||
.search-input::placeholder {
|
||||
transition: color ease-in-out $default-transition-duration;
|
||||
}
|
||||
|
||||
.search-input-container {
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.search-input-wrap {
|
||||
// Fallback if flexbox is not supported
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.search-input-wrap {
|
||||
width: 100%;
|
||||
|
||||
.search-icon,
|
||||
.clear-icon {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 0;
|
||||
color: $location-icon-color;
|
||||
|
||||
&::before {
|
||||
font-family: FontAwesome;
|
||||
font-weight: $gl-font-weight-normal;
|
||||
font-style: normal;
|
||||
}
|
||||
top: 4px;
|
||||
}
|
||||
|
||||
.search-icon {
|
||||
@extend .fa-search;
|
||||
transition: color 0.15s;
|
||||
transition: color $default-transition-duration;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
|
||||
.clear-icon {
|
||||
@extend .fa-times;
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
|
@ -148,19 +131,30 @@ input[type="checkbox"]:hover {
|
|||
form {
|
||||
@extend .form-control:focus;
|
||||
border-color: $dropdown-input-focus-border;
|
||||
box-shadow: 0 0 4px $search-input-focus-shadow-color;
|
||||
box-shadow: none;
|
||||
|
||||
.search-input-wrap {
|
||||
.search-icon,
|
||||
.clear-icon {
|
||||
color: $gl-text-color-tertiary;
|
||||
transition: color ease-in-out $default-transition-duration;
|
||||
}
|
||||
}
|
||||
|
||||
.search-input {
|
||||
color: $gl-text-color;
|
||||
transition: color ease-in-out $default-transition-duration;
|
||||
}
|
||||
|
||||
.search-input::placeholder {
|
||||
color: $gl-text-color-tertiary;
|
||||
}
|
||||
}
|
||||
|
||||
.location-badge {
|
||||
transition: all 0.15s;
|
||||
background-color: $location-badge-active-bg;
|
||||
color: $white-light;
|
||||
}
|
||||
|
||||
.search-input-wrap {
|
||||
i {
|
||||
color: $layout-link-gray;
|
||||
}
|
||||
transition: all $default-transition-duration;
|
||||
background-color: $nav-badge-bg;
|
||||
border-color: $border-color;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
}
|
||||
|
||||
&.ci-failed {
|
||||
@include status-color($red-50, $red-500, $red-600);
|
||||
@include status-color($red-100, $red-500, $red-600);
|
||||
}
|
||||
|
||||
&.ci-success {
|
||||
|
|
@ -39,12 +39,12 @@
|
|||
&.ci-pending,
|
||||
&.ci-failed_with_warnings,
|
||||
&.ci-success_with_warnings {
|
||||
@include status-color($orange-50, $orange-500, $orange-700);
|
||||
@include status-color($orange-100, $orange-500, $orange-700);
|
||||
}
|
||||
|
||||
&.ci-info,
|
||||
&.ci-running {
|
||||
@include status-color($blue-50, $blue-500, $blue-600);
|
||||
@include status-color($blue-100, $blue-500, $blue-600);
|
||||
}
|
||||
|
||||
&.ci-created,
|
||||
|
|
|
|||
|
|
@ -15,3 +15,9 @@
|
|||
-ms-animation: none !important;
|
||||
animation: none !important;
|
||||
}
|
||||
|
||||
// Disable sticky changes bar for tests
|
||||
.diff-files-changed {
|
||||
position: relative !important;
|
||||
top: 0 !important;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,8 +22,7 @@ class Admin::ApplicationsController < Admin::ApplicationController
|
|||
@application = Doorkeeper::Application.new(application_params)
|
||||
|
||||
if @application.save
|
||||
flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :create])
|
||||
redirect_to admin_application_url(@application)
|
||||
redirect_to_admin_page
|
||||
else
|
||||
render :new
|
||||
end
|
||||
|
|
@ -42,6 +41,13 @@ class Admin::ApplicationsController < Admin::ApplicationController
|
|||
redirect_to admin_applications_url, status: 302, notice: 'Application was successfully destroyed.'
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def redirect_to_admin_page
|
||||
flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :create])
|
||||
redirect_to admin_application_url(@application)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_application
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ class Admin::UsersController < Admin::ApplicationController
|
|||
end
|
||||
|
||||
respond_to do |format|
|
||||
result = Users::UpdateService.new(user, user_params_with_pass).execute do |user|
|
||||
result = Users::UpdateService.new(current_user, user_params_with_pass.merge(user: user)).execute do |user|
|
||||
user.skip_reconfirmation!
|
||||
end
|
||||
|
||||
|
|
@ -155,7 +155,7 @@ class Admin::UsersController < Admin::ApplicationController
|
|||
|
||||
def remove_email
|
||||
email = user.emails.find(params[:email_id])
|
||||
success = Emails::DestroyService.new(user, email: email.email).execute
|
||||
success = Emails::DestroyService.new(current_user, user: user, email: email.email).execute
|
||||
|
||||
respond_to do |format|
|
||||
if success
|
||||
|
|
@ -219,7 +219,7 @@ class Admin::UsersController < Admin::ApplicationController
|
|||
end
|
||||
|
||||
def update_user(&block)
|
||||
result = Users::UpdateService.new(user).execute(&block)
|
||||
result = Users::UpdateService.new(current_user, user: user).execute(&block)
|
||||
|
||||
result[:status] == :success
|
||||
end
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ class ApplicationController < ActionController::Base
|
|||
|
||||
around_action :set_locale
|
||||
|
||||
after_action :set_page_title_header, if: -> { request.format == :json }
|
||||
|
||||
protect_from_forgery with: :exception
|
||||
|
||||
helper_method :can?, :current_application_settings
|
||||
|
|
@ -335,4 +337,9 @@ class ApplicationController < ActionController::Base
|
|||
sign_in user, store: false
|
||||
end
|
||||
end
|
||||
|
||||
def set_page_title_header
|
||||
# Per https://tools.ietf.org/html/rfc5987, headers need to be ISO-8859-1, not UTF-8
|
||||
response.headers['Page-Title'] = page_title('GitLab').encode('ISO-8859-1')
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ module AuthenticatesWithTwoFactor
|
|||
sign_in(user)
|
||||
else
|
||||
user.increment_failed_attempts!
|
||||
Gitlab::AppLogger.info("Failed Login: user=#{user.username} ip=#{request.remote_ip} method=OTP")
|
||||
flash.now[:alert] = 'Invalid two-factor code.'
|
||||
prompt_for_two_factor(user)
|
||||
end
|
||||
|
|
@ -75,6 +76,7 @@ module AuthenticatesWithTwoFactor
|
|||
sign_in(user)
|
||||
else
|
||||
user.increment_failed_attempts!
|
||||
Gitlab::AppLogger.info("Failed Login: user=#{user.username} ip=#{request.remote_ip} method=U2F")
|
||||
flash.now[:alert] = 'Authentication via U2F device failed.'
|
||||
prompt_for_two_factor(user)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ module IssuableCollections
|
|||
# @filter_params[:authorized_only] = true
|
||||
end
|
||||
|
||||
@filter_params
|
||||
@filter_params.permit(IssuableFinder::VALID_PARAMS)
|
||||
end
|
||||
|
||||
def set_default_state
|
||||
|
|
|
|||
|
|
@ -12,10 +12,15 @@ class ConfirmationsController < Devise::ConfirmationsController
|
|||
|
||||
def after_confirmation_path_for(resource_name, resource)
|
||||
if signed_in?(resource_name)
|
||||
after_sign_in_path_for(resource)
|
||||
after_sign_in(resource)
|
||||
else
|
||||
Gitlab::AppLogger.info("Email Confirmed: username=#{resource.username} email=#{resource.email} ip=#{request.remote_ip}")
|
||||
flash[:notice] += " Please sign in."
|
||||
new_session_path(resource_name)
|
||||
end
|
||||
end
|
||||
|
||||
def after_sign_in(resource)
|
||||
after_sign_in_path_for(resource)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue