From 63670bb7f84d1c728c32a1914ed378de4e4ac0de Mon Sep 17 00:00:00 2001 From: keen99 Date: Tue, 29 Mar 2016 21:51:31 +0000 Subject: existing folders and existing repos should not use the same set of instructions - pushing an existing repo into gitlab using the previous instructions would result in loss (at the gitlab remote end) of exist branches and tags. so lets push those! --- app/views/projects/empty.html.haml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml index 6ad7b05155a..05e73326ee4 100644 --- a/app/views/projects/empty.html.haml +++ b/app/views/projects/empty.html.haml @@ -44,7 +44,7 @@ git push -u origin master %fieldset - %h5 Existing folder or Git repository + %h5 Existing folder %pre.light-well :preserve cd existing_folder @@ -54,6 +54,15 @@ git commit git push -u origin master + %fieldset + %h5 Existing Git repository + %pre.light-well + :preserve + cd existing_repo + git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'clone')} + git push -u origin --all + git push -u origin --tags + - if can? current_user, :remove_project, @project .prepend-top-20 = link_to 'Remove project', [@project.namespace.becomes(Namespace), @project], data: { confirm: remove_project_message(@project)}, method: :delete, class: "btn btn-remove pull-right" -- cgit v1.2.1 From 2b73aaa15ad9f651f51f8c71de461da6664a4fbb Mon Sep 17 00:00:00 2001 From: Ali Ibrahim Date: Sun, 14 Aug 2016 13:49:08 -0400 Subject: Allow to add deploy keys with write-access --- app/controllers/projects/deploy_keys_controller.rb | 2 +- app/views/projects/deploy_keys/_form.html.haml | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/controllers/projects/deploy_keys_controller.rb b/app/controllers/projects/deploy_keys_controller.rb index 529e0aa2d33..77bd883a5bd 100644 --- a/app/controllers/projects/deploy_keys_controller.rb +++ b/app/controllers/projects/deploy_keys_controller.rb @@ -53,6 +53,6 @@ class Projects::DeployKeysController < Projects::ApplicationController end def deploy_key_params - params.require(:deploy_key).permit(:key, :title) + params.require(:deploy_key).permit(:key, :title, :can_push) end end diff --git a/app/views/projects/deploy_keys/_form.html.haml b/app/views/projects/deploy_keys/_form.html.haml index 901605f7ca3..68f472e8886 100644 --- a/app/views/projects/deploy_keys/_form.html.haml +++ b/app/views/projects/deploy_keys/_form.html.haml @@ -10,4 +10,13 @@ %p.light.append-bottom-0 Paste a machine public key here. Read more about how to generate it = link_to "here", help_page_path("ssh/README") + .form-group + .checkbox + = f.label :can_push do + = f.check_box :can_push + %strong Allow write access + .form-group + %p.light.append-bottom-0 + Can this key be used to push to this repository? Deploy keys always have pull access + = f.submit "Add key", class: "btn-create btn" -- cgit v1.2.1 From 8bc7ffd4dceec118319aed680f41a8dbda275a06 Mon Sep 17 00:00:00 2001 From: Ali Ibrahim Date: Fri, 19 Aug 2016 13:39:13 -0400 Subject: Rephrase wording for pull/push access --- app/views/projects/deploy_keys/_form.html.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/views/projects/deploy_keys/_form.html.haml b/app/views/projects/deploy_keys/_form.html.haml index 68f472e8886..757260aa5b5 100644 --- a/app/views/projects/deploy_keys/_form.html.haml +++ b/app/views/projects/deploy_keys/_form.html.haml @@ -14,9 +14,9 @@ .checkbox = f.label :can_push do = f.check_box :can_push - %strong Allow write access + %strong Write access allowed? .form-group %p.light.append-bottom-0 - Can this key be used to push to this repository? Deploy keys always have pull access + Allow this key to push to repository as well? (Default only allows pull access.) = f.submit "Add key", class: "btn-create btn" -- cgit v1.2.1 From c3508851bff289fdaaa114298b3ae13513646775 Mon Sep 17 00:00:00 2001 From: Ali Ibrahim Date: Fri, 19 Aug 2016 19:31:40 -0400 Subject: Set current user as deploy key user --- app/controllers/projects/deploy_keys_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/controllers/projects/deploy_keys_controller.rb b/app/controllers/projects/deploy_keys_controller.rb index 77bd883a5bd..b094491e006 100644 --- a/app/controllers/projects/deploy_keys_controller.rb +++ b/app/controllers/projects/deploy_keys_controller.rb @@ -16,7 +16,7 @@ class Projects::DeployKeysController < Projects::ApplicationController end def create - @key = DeployKey.new(deploy_key_params) + @key = DeployKey.new(deploy_key_params.merge(user: current_user)) set_index_vars if @key.valid? && @project.deploy_keys << @key -- cgit v1.2.1 From f46acfc7abd72342bbd07cd9e87b0d5a3740a8b6 Mon Sep 17 00:00:00 2001 From: Regis Date: Tue, 25 Oct 2016 16:00:38 -0600 Subject: integrate vue components, use intance variables to pass data to vue --- app/assets/javascripts/pipeline.vue.js.es6 | 14 ++++++++ app/assets/javascripts/pipelines.vue.js.es6 | 31 +++++++++++++++++ app/views/projects/pipelines/index.html.haml | 52 +++++++++++++++++++--------- 3 files changed, 81 insertions(+), 16 deletions(-) create mode 100644 app/assets/javascripts/pipeline.vue.js.es6 create mode 100644 app/assets/javascripts/pipelines.vue.js.es6 (limited to 'app') diff --git a/app/assets/javascripts/pipeline.vue.js.es6 b/app/assets/javascripts/pipeline.vue.js.es6 new file mode 100644 index 00000000000..959d7be32fa --- /dev/null +++ b/app/assets/javascripts/pipeline.vue.js.es6 @@ -0,0 +1,14 @@ +//= require vue + +(gl => { + gl.VuePipeLine = Vue.extend({ + props: ['pipeline'], + template: ` +
+ + {{ pipeline.status }} + +
+ ` + }) +})(window.gl || (window.gl = {})) diff --git a/app/assets/javascripts/pipelines.vue.js.es6 b/app/assets/javascripts/pipelines.vue.js.es6 new file mode 100644 index 00000000000..8cf0558d94b --- /dev/null +++ b/app/assets/javascripts/pipelines.vue.js.es6 @@ -0,0 +1,31 @@ +//= require vue + +(gl => { + gl.VuePipeLines = Vue.extend({ + props: ['pipelines', 'count'], + template: ` +
+ + + + + + + + + + +
+ +
+ +
StatusPipelineCommitStages
+
+ `, + computed: { + pipes() { + return this.pipelines + } + } + }) +})(window.gl || (window.gl = {})) diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index 4bc49072f35..8bd9afd05ce 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -36,21 +36,41 @@ = link_to ci_lint_path, class: 'btn btn-default' do %span CI Lint - %div.content-list.pipelines - - stages = @pipelines.stages - - if @pipelines.blank? - %div - .nothing-here-block No pipelines to show - - else - .table-holder - %table.table.ci-table - %thead - %th Status - %th Pipeline - %th Commit - %th Stages - %th - %th.hidden-xs - = render @pipelines, commit_sha: true, stage: true, allow_retry: true, stages: stages + .app + -# %div.content-list.pipelines + -# - stages = @pipelines.stages + -# - if @pipelines.blank? + -# %div + -# .nothing-here-block No pipelines to show + -# - else + -# .table-holder + -# %table.table.ci-table + -# %thead + -# %th Status + -# %th Pipeline + -# %th Commit + -# %th Stages + -# %th + -# %th.hidden-xs + -# = render @pipelines, commit_sha: true, stage: true, allow_retry: true, stages: stages = paginate @pipelines, theme: 'gitlab' + +:javascript + var VuePipeLines = gl.VuePipeLines + var VuePipeLine = gl.VuePipeLine + + Vue.component('vue-pipelines', VuePipeLines) + Vue.component('vue-pipeline', VuePipeLine) + + new Vue({ + el: ".app", + data:{ + pipelines: JSON.parse('#{@pipelines.to_json}'), + count: JSON.parse('#{@pipeline_count.to_json}') + }, + template: "" + + "
" + + "" + + "
" + }) -- cgit v1.2.1 From 243717c0cc3172d50e4ca5c0be567bfd599b4d90 Mon Sep 17 00:00:00 2001 From: Regis Date: Tue, 25 Oct 2016 16:42:55 -0600 Subject: conditional show --- app/assets/javascripts/pipelines.vue.js.es6 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/pipelines.vue.js.es6 b/app/assets/javascripts/pipelines.vue.js.es6 index 8cf0558d94b..e98c8816dfd 100644 --- a/app/assets/javascripts/pipelines.vue.js.es6 +++ b/app/assets/javascripts/pipelines.vue.js.es6 @@ -4,7 +4,12 @@ gl.VuePipeLines = Vue.extend({ props: ['pipelines', 'count'], template: ` -
+
+
+ No pipelines to show +
+
+
-- cgit v1.2.1 From d858c54879c61afde2df07e96e31c96b8a9f9586 Mon Sep 17 00:00:00 2001 From: Regis Date: Wed, 26 Oct 2016 12:43:58 -0600 Subject: conform to eslint --- app/assets/javascripts/pipeline.vue.js.es6 | 10 ++++++---- app/assets/javascripts/pipelines.vue.js.es6 | 14 ++++++++------ 2 files changed, 14 insertions(+), 10 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/pipeline.vue.js.es6 b/app/assets/javascripts/pipeline.vue.js.es6 index 959d7be32fa..7e9da71b6ab 100644 --- a/app/assets/javascripts/pipeline.vue.js.es6 +++ b/app/assets/javascripts/pipeline.vue.js.es6 @@ -1,6 +1,8 @@ //= require vue +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ -(gl => { +((gl) => { gl.VuePipeLine = Vue.extend({ props: ['pipeline'], template: ` @@ -9,6 +11,6 @@ {{ pipeline.status }} - ` - }) -})(window.gl || (window.gl = {})) + `, + }); +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/pipelines.vue.js.es6 b/app/assets/javascripts/pipelines.vue.js.es6 index e98c8816dfd..50ecf28394d 100644 --- a/app/assets/javascripts/pipelines.vue.js.es6 +++ b/app/assets/javascripts/pipelines.vue.js.es6 @@ -1,6 +1,8 @@ //= require vue +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ -(gl => { +((gl) => { gl.VuePipeLines = Vue.extend({ props: ['pipelines', 'count'], template: ` @@ -29,8 +31,8 @@ `, computed: { pipes() { - return this.pipelines - } - } - }) -})(window.gl || (window.gl = {})) + return this.pipelines; + }, + }, + }); +})(window.gl || (window.gl = {})); -- cgit v1.2.1 From e1ad87c70d10c6a329586c8553442e69e258fff2 Mon Sep 17 00:00:00 2001 From: Regis Date: Wed, 26 Oct 2016 12:47:35 -0600 Subject: follow eslint in HAML file as well --- app/views/projects/pipelines/index.html.haml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'app') diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index 8bd9afd05ce..c6f0ab87f8d 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -57,20 +57,17 @@ = paginate @pipelines, theme: 'gitlab' :javascript - var VuePipeLines = gl.VuePipeLines - var VuePipeLine = gl.VuePipeLine - - Vue.component('vue-pipelines', VuePipeLines) - Vue.component('vue-pipeline', VuePipeLine) + Vue.component('vue-pipelines', gl.VuePipeLines); + Vue.component('vue-pipeline', gl.VuePipeLine); new Vue({ el: ".app", data:{ pipelines: JSON.parse('#{@pipelines.to_json}'), - count: JSON.parse('#{@pipeline_count.to_json}') + count: JSON.parse('#{@pipeline_count.to_json}'), }, template: "" + "
" + "" - + "
" + + "", }) -- cgit v1.2.1 From 50b4c2dc0f2844c7017a352a1df0b919f2bcc51d Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 27 Oct 2016 15:53:29 -0600 Subject: getting somewhere - now need to fix loop --- app/assets/javascripts/pipelines.vue.js.es6 | 182 ++++++++++++++++++++++++--- app/views/projects/pipelines/index.html.haml | 26 ++-- 2 files changed, 172 insertions(+), 36 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/pipelines.vue.js.es6 b/app/assets/javascripts/pipelines.vue.js.es6 index 50ecf28394d..cf3f7a729eb 100644 --- a/app/assets/javascripts/pipelines.vue.js.es6 +++ b/app/assets/javascripts/pipelines.vue.js.es6 @@ -6,28 +6,170 @@ gl.VuePipeLines = Vue.extend({ props: ['pipelines', 'count'], template: ` -
-
- No pipelines to show -
-
-
-
Status
- - - - - - - - - -
- +
+ + + + + + + + +
+
+ + + + + + -
StatusPipelineCommitStages
StatusPipelineCommitStages
+ #30 + by + API + +
+ +
+ master +
+ + + +
+ 29141ed3 +

+ + fix broken repo 500 errors in UI and added relevant specs +

+
+ + + + + + + + + +
-
+ + `, computed: { pipes() { diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index c6f0ab87f8d..085bef11338 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -36,22 +36,16 @@ = link_to ci_lint_path, class: 'btn btn-default' do %span CI Lint - .app - -# %div.content-list.pipelines - -# - stages = @pipelines.stages - -# - if @pipelines.blank? - -# %div - -# .nothing-here-block No pipelines to show - -# - else - -# .table-holder - -# %table.table.ci-table - -# %thead - -# %th Status - -# %th Pipeline - -# %th Commit - -# %th Stages - -# %th - -# %th.hidden-xs + %div.content-list.pipelines + - stages = @pipelines.stages + - if @pipelines.blank? + %div + .nothing-here-block No pipelines to show + - else + .table-holder + %table.table.ci-table + %thead + %tbody.app -# = render @pipelines, commit_sha: true, stage: true, allow_retry: true, stages: stages = paginate @pipelines, theme: 'gitlab' -- cgit v1.2.1 From 02c2ef89e9bb5f86e1fd1c3f188befea480908c1 Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 27 Oct 2016 16:18:55 -0600 Subject: fixed loop - move on to make components --- app/assets/javascripts/pipelines.vue.js.es6 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/pipelines.vue.js.es6 b/app/assets/javascripts/pipelines.vue.js.es6 index cf3f7a729eb..4d6b00553cf 100644 --- a/app/assets/javascripts/pipelines.vue.js.es6 +++ b/app/assets/javascripts/pipelines.vue.js.es6 @@ -14,8 +14,7 @@ - - - `, computed: { -- cgit v1.2.1 From 89823100b7cf37944ab8061a68e08afd46dcfc59 Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 27 Oct 2016 16:24:33 -0600 Subject: formatting --- app/assets/javascripts/pipelines.vue.js.es6 | 302 ++++++++++++++-------------- 1 file changed, 152 insertions(+), 150 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/pipelines.vue.js.es6 b/app/assets/javascripts/pipelines.vue.js.es6 index 4d6b00553cf..e20bdf8e992 100644 --- a/app/assets/javascripts/pipelines.vue.js.es6 +++ b/app/assets/javascripts/pipelines.vue.js.es6 @@ -7,166 +7,168 @@ props: ['pipelines', 'count'], template: ` - Status - Pipeline - Commit - Stages - - - + + Status + Pipeline + Commit + Stages + + + + - - - - - - - - - -  failed - - - - - #30 - by - API - - -
- -
- master -
- - - + + + + + + + + + +  {{pipeline.status}} + + + + + #30 + by + API + + +
+
- 29141ed3 -

- - fix broken repo 500 errors in UI and added relevant specs -

- - - + + + + + + + `, computed: { -- cgit v1.2.1 From 0208d6008f7d154615b510d7060c37ff5698a5e4 Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 27 Oct 2016 16:32:39 -0600 Subject: id is dynamic --- app/assets/javascripts/pipelines.vue.js.es6 | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/pipelines.vue.js.es6 b/app/assets/javascripts/pipelines.vue.js.es6 index e20bdf8e992..26a3bc2d65f 100644 --- a/app/assets/javascripts/pipelines.vue.js.es6 +++ b/app/assets/javascripts/pipelines.vue.js.es6 @@ -19,7 +19,7 @@ - + @@ -31,7 +31,7 @@ - #30 + #{{pipeline.id}} by API @@ -53,7 +53,7 @@
@@ -173,6 +173,7 @@ `, computed: { pipes() { + console.log(this.pipelines); return this.pipelines; }, }, -- cgit v1.2.1 From dc476fe6ff1c55a992fce8483b9f8a4762e302fa Mon Sep 17 00:00:00 2001 From: Regis Date: Sat, 29 Oct 2016 13:50:08 -0600 Subject: stashing --- app/assets/javascripts/pipeline.vue.js.es6 | 16 ------- app/assets/javascripts/pipelines.vue.js.es6 | 59 ++++++++++++++----------- app/assets/javascripts/runnerstats/index.js.es6 | 56 +++++++++++++++++++++++ app/assets/javascripts/status_svg.vue.js.es6 | 18 ++++++++ app/views/projects/pipelines/index.html.haml | 6 +-- 5 files changed, 107 insertions(+), 48 deletions(-) delete mode 100644 app/assets/javascripts/pipeline.vue.js.es6 create mode 100644 app/assets/javascripts/runnerstats/index.js.es6 create mode 100644 app/assets/javascripts/status_svg.vue.js.es6 (limited to 'app') diff --git a/app/assets/javascripts/pipeline.vue.js.es6 b/app/assets/javascripts/pipeline.vue.js.es6 deleted file mode 100644 index 7e9da71b6ab..00000000000 --- a/app/assets/javascripts/pipeline.vue.js.es6 +++ /dev/null @@ -1,16 +0,0 @@ -//= require vue -/* global Vue, gl */ -/* eslint-disable no-param-reassign */ - -((gl) => { - gl.VuePipeLine = Vue.extend({ - props: ['pipeline'], - template: ` -
- - {{ pipeline.status }} - -
- `, - }); -})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/pipelines.vue.js.es6 b/app/assets/javascripts/pipelines.vue.js.es6 index 26a3bc2d65f..1bd30feaf9e 100644 --- a/app/assets/javascripts/pipelines.vue.js.es6 +++ b/app/assets/javascripts/pipelines.vue.js.es6 @@ -1,9 +1,15 @@ //= require vue +//= require_tree ./runnerstats /* global Vue, gl */ /* eslint-disable no-param-reassign */ ((gl) => { gl.VuePipeLines = Vue.extend({ + data() { + return { + runnerStats: new gl.RunnerStats(), + }; + }, props: ['pipelines', 'count'], template: ` @@ -19,21 +25,19 @@ - - - - - - - -  {{pipeline.status}} - + + + + + - #{{pipeline.id}} + #{{pipeline.id}} by - API + {{pipeline.user}} + + + + `, - computed: { - pipes() { - console.log(this.pipelines); - return this.pipelines; - }, - }, }); })(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/runnerstats/index.js.es6 b/app/assets/javascripts/runnerstats/index.js.es6 new file mode 100644 index 00000000000..35f95f3a811 --- /dev/null +++ b/app/assets/javascripts/runnerstats/index.js.es6 @@ -0,0 +1,56 @@ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.RunnerStats = class { + constructor() { + return { + running: { + text: 'pending', + color: '#E75E40', + pathOne: 'M12.5,7 C12.5,3.96243388 10.0375661,1.5 7,1.5 C3.96243388,1.5 1.5,3.96243388 1.5,7 C1.5,10.0375661 3.96243388,12.5 7,12.5 C10.0375661,12.5 12.5,10.0375661 12.5,7 Z M0,7 C0,3.13400675 3.13400675,0 7,0 C10.8659932,0 14,3.13400675 14,7 C14,10.8659932 10.8659932,14 7,14 C3.13400675,14 0,10.8659932 0,7 Z', + pathTwo: 'M4.69999981,5.30065012 C4.69999981,5.13460564 4.83842754,5 5.00354719,5 L5.89645243,5 C6.06409702,5 6.19999981,5.13308716 6.19999981,5.30065012 L6.19999981,8.69934988 C6.19999981,8.86539436 6.06157207,9 5.89645243,9 L5.00354719,9 C4.8359026,9 4.69999981,8.86691284 4.69999981,8.69934988 L4.69999981,5.30065012 Z M7.69999981,5.30065012 C7.69999981,5.13460564 7.83842754,5 8.00354719,5 L8.89645243,5 C9.06409702,5 9.19999981,5.13308716 9.19999981,5.30065012 L9.19999981,8.69934988 C9.19999981,8.86539436 9.06157207,9 8.89645243,9 L8.00354719,9 C7.8359026,9 7.69999981,8.86691284 7.69999981,8.69934988 L7.69999981,5.30065012 Z', + }, + passed: ` + + + + + + + + passed + `, + failed: ` + + + + + + +  failed + `, + created: ` +  created + `, + skipped: ` + + + + + + +  skipped + `, + pending: ` + + + + + + +  pending + `, + }; + } + }; +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/status_svg.vue.js.es6 b/app/assets/javascripts/status_svg.vue.js.es6 new file mode 100644 index 00000000000..0af35ba6f3a --- /dev/null +++ b/app/assets/javascripts/status_svg.vue.js.es6 @@ -0,0 +1,18 @@ +//= require vue +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VueRunnerStatus = Vue.extend({ + props: ['status'], + template: ` + + + + + + +  {{status.text}} + `, + }); +})(window.gl || (window.gl = {})); diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index 085bef11338..30625e399b0 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -44,15 +44,11 @@ - else .table-holder %table.table.ci-table - %thead %tbody.app - -# = render @pipelines, commit_sha: true, stage: true, allow_retry: true, stages: stages - - = paginate @pipelines, theme: 'gitlab' :javascript Vue.component('vue-pipelines', gl.VuePipeLines); - Vue.component('vue-pipeline', gl.VuePipeLine); + Vue.component('vue-runner-status', gl.VueRunnerStatus); new Vue({ el: ".app", -- cgit v1.2.1 From 66727f74b806a978c4bf76a8e9bd4b86c6443651 Mon Sep 17 00:00:00 2001 From: Regis Date: Sun, 30 Oct 2016 01:28:57 -0600 Subject: change architecture - add store - make api call by default --- app/assets/javascripts/pipelines.vue.js.es6 | 186 ------------------- app/assets/javascripts/runnerstats/index.js.es6 | 56 ------ app/assets/javascripts/status_svg.vue.js.es6 | 18 -- .../javascripts/vue_pipelines_index/index.js.es6 | 7 + .../vue_pipelines_index/pipelines.vue.js.es6 | 198 +++++++++++++++++++++ .../vue_pipelines_index/status_data_icons.js.es6 | 56 ++++++ .../javascripts/vue_pipelines_index/store.js.es6 | 15 ++ .../vue_pipelines_index/vue_commit_link.vue.js.es6 | 50 ++++++ app/assets/javascripts/vue_pipelines_loader.js.es6 | 1 + app/views/projects/pipelines/index.html.haml | 15 +- 10 files changed, 336 insertions(+), 266 deletions(-) delete mode 100644 app/assets/javascripts/pipelines.vue.js.es6 delete mode 100644 app/assets/javascripts/runnerstats/index.js.es6 delete mode 100644 app/assets/javascripts/status_svg.vue.js.es6 create mode 100644 app/assets/javascripts/vue_pipelines_index/index.js.es6 create mode 100644 app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 create mode 100644 app/assets/javascripts/vue_pipelines_index/status_data_icons.js.es6 create mode 100644 app/assets/javascripts/vue_pipelines_index/store.js.es6 create mode 100644 app/assets/javascripts/vue_pipelines_index/vue_commit_link.vue.js.es6 create mode 100644 app/assets/javascripts/vue_pipelines_loader.js.es6 (limited to 'app') diff --git a/app/assets/javascripts/pipelines.vue.js.es6 b/app/assets/javascripts/pipelines.vue.js.es6 deleted file mode 100644 index 1bd30feaf9e..00000000000 --- a/app/assets/javascripts/pipelines.vue.js.es6 +++ /dev/null @@ -1,186 +0,0 @@ -//= require vue -//= require_tree ./runnerstats -/* global Vue, gl */ -/* eslint-disable no-param-reassign */ - -((gl) => { - gl.VuePipeLines = Vue.extend({ - data() { - return { - runnerStats: new gl.RunnerStats(), - }; - }, - props: ['pipelines', 'count'], - template: ` - - - Status - Pipeline - Commit - Stages - - - - - - - - - - - - - - - - #{{pipeline.id}} - by - {{pipeline.user}} - - -
- -
- master -
- - - -
- 29141ed3 -

- - fix broken repo 500 errors in UI and added relevant specs -

- - - - - - - - - - - - - - - - - - - `, - }); -})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/runnerstats/index.js.es6 b/app/assets/javascripts/runnerstats/index.js.es6 deleted file mode 100644 index 35f95f3a811..00000000000 --- a/app/assets/javascripts/runnerstats/index.js.es6 +++ /dev/null @@ -1,56 +0,0 @@ -/* eslint-disable no-param-reassign */ - -((gl) => { - gl.RunnerStats = class { - constructor() { - return { - running: { - text: 'pending', - color: '#E75E40', - pathOne: 'M12.5,7 C12.5,3.96243388 10.0375661,1.5 7,1.5 C3.96243388,1.5 1.5,3.96243388 1.5,7 C1.5,10.0375661 3.96243388,12.5 7,12.5 C10.0375661,12.5 12.5,10.0375661 12.5,7 Z M0,7 C0,3.13400675 3.13400675,0 7,0 C10.8659932,0 14,3.13400675 14,7 C14,10.8659932 10.8659932,14 7,14 C3.13400675,14 0,10.8659932 0,7 Z', - pathTwo: 'M4.69999981,5.30065012 C4.69999981,5.13460564 4.83842754,5 5.00354719,5 L5.89645243,5 C6.06409702,5 6.19999981,5.13308716 6.19999981,5.30065012 L6.19999981,8.69934988 C6.19999981,8.86539436 6.06157207,9 5.89645243,9 L5.00354719,9 C4.8359026,9 4.69999981,8.86691284 4.69999981,8.69934988 L4.69999981,5.30065012 Z M7.69999981,5.30065012 C7.69999981,5.13460564 7.83842754,5 8.00354719,5 L8.89645243,5 C9.06409702,5 9.19999981,5.13308716 9.19999981,5.30065012 L9.19999981,8.69934988 C9.19999981,8.86539436 9.06157207,9 8.89645243,9 L8.00354719,9 C7.8359026,9 7.69999981,8.86691284 7.69999981,8.69934988 L7.69999981,5.30065012 Z', - }, - passed: ` - - - - - - - - passed - `, - failed: ` - - - - - - -  failed - `, - created: ` -  created - `, - skipped: ` - - - - - - -  skipped - `, - pending: ` - - - - - - -  pending - `, - }; - } - }; -})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/status_svg.vue.js.es6 b/app/assets/javascripts/status_svg.vue.js.es6 deleted file mode 100644 index 0af35ba6f3a..00000000000 --- a/app/assets/javascripts/status_svg.vue.js.es6 +++ /dev/null @@ -1,18 +0,0 @@ -//= require vue -/* global Vue, gl */ -/* eslint-disable no-param-reassign */ - -((gl) => { - gl.VueRunnerStatus = Vue.extend({ - props: ['status'], - template: ` - - - - - - -  {{status.text}} - `, - }); -})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/index.js.es6 b/app/assets/javascripts/vue_pipelines_index/index.js.es6 new file mode 100644 index 00000000000..3657d9c5b0d --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_index/index.js.es6 @@ -0,0 +1,7 @@ +//= require vue +//= require vue-resource + +//= require ./store.js.es6 +//= require ./status_data_icons.js.es6 +//= require ./vue_commit_link.vue.js.es6 +//= require ./pipelines.vue.js.es6 diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 new file mode 100644 index 00000000000..424b29ae527 --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 @@ -0,0 +1,198 @@ +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VuePipeLines = Vue.extend({ + data() { + return { + endpoint: `/api/v3/projects/${this.scopeId}/pipelines`, + pipelines: [], + runnerStats: new gl.RunnerStats(), + }; + }, + props: ['scope', 'store'], + created() { + this.store.fetchData.call(this, Vue); + }, + methods: { + shortSha(pipeline) { + return pipeline.sha.slice(0, 8); + }, + }, + template: ` + + + Status + Pipeline + Commit + Stages + + + + + + + + +
+ + running + +
+
+ + passed + +
+
+ + + #{{pipeline.id}} + by + {{pipeline.user}} + + +
+ +
+ master +
+ + + +
+ {{shortSha(pipeline)}} +

+ + fix broken repo 500 errors in UI and added relevant specs +

+ + + + + + + + + + + + + + + + + + + `, + }); +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/status_data_icons.js.es6 b/app/assets/javascripts/vue_pipelines_index/status_data_icons.js.es6 new file mode 100644 index 00000000000..b4e0c07a665 --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_index/status_data_icons.js.es6 @@ -0,0 +1,56 @@ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.RunnerStats = class { + constructor() { + return { + running: { + text: 'running', + color: '#E75E40', + pathOne: 'M12.5,7 C12.5,3.96243388 10.0375661,1.5 7,1.5 C3.96243388,1.5 1.5,3.96243388 1.5,7 C1.5,10.0375661 3.96243388,12.5 7,12.5 C10.0375661,12.5 12.5,10.0375661 12.5,7 Z M0,7 C0,3.13400675 3.13400675,0 7,0 C10.8659932,0 14,3.13400675 14,7 C14,10.8659932 10.8659932,14 7,14 C3.13400675,14 0,10.8659932 0,7 Z', + pathTwo: 'M4.69999981,5.30065012 C4.69999981,5.13460564 4.83842754,5 5.00354719,5 L5.89645243,5 C6.06409702,5 6.19999981,5.13308716 6.19999981,5.30065012 L6.19999981,8.69934988 C6.19999981,8.86539436 6.06157207,9 5.89645243,9 L5.00354719,9 C4.8359026,9 4.69999981,8.86691284 4.69999981,8.69934988 L4.69999981,5.30065012 Z M7.69999981,5.30065012 C7.69999981,5.13460564 7.83842754,5 8.00354719,5 L8.89645243,5 C9.06409702,5 9.19999981,5.13308716 9.19999981,5.30065012 L9.19999981,8.69934988 C9.19999981,8.86539436 9.06157207,9 8.89645243,9 L8.00354719,9 C7.8359026,9 7.69999981,8.86691284 7.69999981,8.69934988 L7.69999981,5.30065012 Z', + }, + passed: ` + + + + + + + + passed + `, + failed: ` + + + + + + +  failed + `, + created: ` +  created + `, + skipped: ` + + + + + + +  skipped + `, + pending: ` + + + + + + +  pending + `, + }; + } + }; +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 new file mode 100644 index 00000000000..3f03bb31068 --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -0,0 +1,15 @@ +/* global gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.PipelineStore = class { + fetchData(Vue) { + this.$http.get(`/api/v3/projects/${this.scope}/pipelines`) + .then((response) => { + Vue.set(this, 'pipelines', JSON.parse(response.body)); + }, () => { + Vue.set(this, 'pipelines', []); + }); + } + }; +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/vue_commit_link.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/vue_commit_link.vue.js.es6 new file mode 100644 index 00000000000..9e2ef8993a2 --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_index/vue_commit_link.vue.js.es6 @@ -0,0 +1,50 @@ + +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VueCommitLink = Vue.extend({ + props: ['pipeline'], + template: ` + + +
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + `, + }); +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_loader.js.es6 b/app/assets/javascripts/vue_pipelines_loader.js.es6 new file mode 100644 index 00000000000..1b8ba72b697 --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_loader.js.es6 @@ -0,0 +1 @@ +//= require_tree ./vue_pipelines_index diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index 30625e399b0..7cb77f2034b 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -47,17 +47,20 @@ %tbody.app :javascript - Vue.component('vue-pipelines', gl.VuePipeLines); - Vue.component('vue-runner-status', gl.VueRunnerStatus); + Vue.use(VueResource); - new Vue({ + var vm = new Vue({ el: ".app", data:{ - pipelines: JSON.parse('#{@pipelines.to_json}'), - count: JSON.parse('#{@pipeline_count.to_json}'), + scope: "#{@project.id}", + store: new gl.PipelineStore(), + }, + components: { + 'vue-commit-link': gl.VueCommitLink, + 'vue-pipelines': gl.VuePipeLines, }, template: "" + "
" - + "" + + "" + "
", }) -- cgit v1.2.1 From 8658c9788370f1d7ab63270e3dcac423c27d38c5 Mon Sep 17 00:00:00 2001 From: Regis Date: Sun, 30 Oct 2016 01:31:59 -0600 Subject: remove uneeded endpoint data key --- app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 | 1 - 1 file changed, 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 index 424b29ae527..2847fa024d9 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 @@ -5,7 +5,6 @@ gl.VuePipeLines = Vue.extend({ data() { return { - endpoint: `/api/v3/projects/${this.scopeId}/pipelines`, pipelines: [], runnerStats: new gl.RunnerStats(), }; -- cgit v1.2.1 From 308e0eb554cbd271cbcbc13e8f795ae08c2af62c Mon Sep 17 00:00:00 2001 From: Regis Date: Sun, 30 Oct 2016 01:45:55 -0600 Subject: have polling working --- app/assets/javascripts/vue_pipelines_index/store.js.es6 | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index 3f03bb31068..aca603cf756 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -4,12 +4,17 @@ ((gl) => { gl.PipelineStore = class { fetchData(Vue) { - this.$http.get(`/api/v3/projects/${this.scope}/pipelines`) - .then((response) => { - Vue.set(this, 'pipelines', JSON.parse(response.body)); + const goFetch = vue => + this.$http.get(`/api/v3/projects/${this.scope}/pipelines`) + .then((response) => { + vue.set(this, 'pipelines', JSON.parse(response.body)); }, () => { - Vue.set(this, 'pipelines', []); + vue.set(this, 'pipelines', []); }); + + goFetch(Vue); + + setInterval(() => { console.log('DID IT'); goFetch(Vue) }, 3000); } }; })(window.gl || (window.gl = {})); -- cgit v1.2.1 From b4d8cb0cf031d6817952709ab90d27d9f23c04a5 Mon Sep 17 00:00:00 2001 From: Regis Date: Sun, 30 Oct 2016 01:48:26 -0600 Subject: changed fetchData to fetchDataLoop - ensured '#created' is part of Vue1 and Vue2 --- app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 | 2 +- app/assets/javascripts/vue_pipelines_index/store.js.es6 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 index 2847fa024d9..8036febd593 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 @@ -11,7 +11,7 @@ }, props: ['scope', 'store'], created() { - this.store.fetchData.call(this, Vue); + this.store.fetchDataLoop.call(this, Vue); }, methods: { shortSha(pipeline) { diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index aca603cf756..6abd160f9a4 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -3,7 +3,7 @@ ((gl) => { gl.PipelineStore = class { - fetchData(Vue) { + fetchDataLoop(Vue) { const goFetch = vue => this.$http.get(`/api/v3/projects/${this.scope}/pipelines`) .then((response) => { -- cgit v1.2.1 From ae90118e1dfaaf6db890b4bfa00bc45cf287fa21 Mon Sep 17 00:00:00 2001 From: Regis Date: Sun, 30 Oct 2016 01:50:11 -0600 Subject: formatting - eslint --- app/assets/javascripts/vue_pipelines_index/store.js.es6 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index 6abd160f9a4..7479caf107d 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -14,7 +14,10 @@ goFetch(Vue); - setInterval(() => { console.log('DID IT'); goFetch(Vue) }, 3000); + setInterval(() => { + console.log('DID IT'); + goFetch(Vue); + }, 3000); } }; })(window.gl || (window.gl = {})); -- cgit v1.2.1 From 384ea58f72d73c858769b22c81e5345e9e3e09bc Mon Sep 17 00:00:00 2001 From: Regis Date: Sun, 30 Oct 2016 14:46:31 -0600 Subject: change to more component like structure for reusable components --- .../javascripts/vue_pipelines_index/index.js.es6 | 3 +- .../vue_pipelines_index/pipelines.vue.js.es6 | 31 ++++++-------- .../vue_pipelines_index/running.vue.js.es6 | 25 +++++++++++ .../vue_pipelines_index/running_icon.vue.js.es6 | 13 ++++++ .../javascripts/vue_pipelines_index/store.js.es6 | 1 - .../vue_pipelines_index/vue_commit_link.vue.js.es6 | 50 ---------------------- app/views/projects/pipelines/index.html.haml | 1 - 7 files changed, 54 insertions(+), 70 deletions(-) create mode 100644 app/assets/javascripts/vue_pipelines_index/running.vue.js.es6 create mode 100644 app/assets/javascripts/vue_pipelines_index/running_icon.vue.js.es6 delete mode 100644 app/assets/javascripts/vue_pipelines_index/vue_commit_link.vue.js.es6 (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/index.js.es6 b/app/assets/javascripts/vue_pipelines_index/index.js.es6 index 3657d9c5b0d..36661553444 100644 --- a/app/assets/javascripts/vue_pipelines_index/index.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/index.js.es6 @@ -2,6 +2,7 @@ //= require vue-resource //= require ./store.js.es6 +//= require ./running_icon.vue.js.es6 +//= require ./running.vue.js.es6 //= require ./status_data_icons.js.es6 -//= require ./vue_commit_link.vue.js.es6 //= require ./pipelines.vue.js.es6 diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 index 8036febd593..ba6ef3011ab 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 @@ -3,13 +3,19 @@ ((gl) => { gl.VuePipeLines = Vue.extend({ + components: { + 'vue-running-pipeline': gl.VueRunningPipeline, + }, data() { return { pipelines: [], runnerStats: new gl.RunnerStats(), }; }, - props: ['scope', 'store'], + props: [ + 'scope', + 'store', + ], created() { this.store.fetchDataLoop.call(this, Vue); }, @@ -31,24 +37,15 @@ - - -
- - running - -
-
- - passed - -
-
+ + - #{{pipeline.id}} - by - {{pipeline.user}} + + #{{pipeline.id}} + + by + {{pipeline.user}}
diff --git a/app/assets/javascripts/vue_pipelines_index/running.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/running.vue.js.es6 new file mode 100644 index 00000000000..5edf8403bd9 --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_index/running.vue.js.es6 @@ -0,0 +1,25 @@ +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VueRunningPipeline = Vue.extend({ + components: { + 'vue-running-icon': gl.VueRunningIcon, + }, + props: [ + 'pipe', + ], + template: ` + + + + + + +  running + + + + `, + }); +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/running_icon.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/running_icon.vue.js.es6 new file mode 100644 index 00000000000..c37f213525c --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_index/running_icon.vue.js.es6 @@ -0,0 +1,13 @@ +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VueRunningIcon = Vue.extend({ + template: ` + + + + + `, + }); +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index 7479caf107d..38797f85f0a 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -13,7 +13,6 @@ }); goFetch(Vue); - setInterval(() => { console.log('DID IT'); goFetch(Vue); diff --git a/app/assets/javascripts/vue_pipelines_index/vue_commit_link.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/vue_commit_link.vue.js.es6 deleted file mode 100644 index 9e2ef8993a2..00000000000 --- a/app/assets/javascripts/vue_pipelines_index/vue_commit_link.vue.js.es6 +++ /dev/null @@ -1,50 +0,0 @@ - -/* global Vue, gl */ -/* eslint-disable no-param-reassign */ - -((gl) => { - gl.VueCommitLink = Vue.extend({ - props: ['pipeline'], - template: ` - - -
- - - -
-
- - - -
-
- - - -
-
- - - -
-
- - - -
-
- - - -
-
- - - -
-
- - `, - }); -})(window.gl || (window.gl = {})); diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index 7cb77f2034b..6309de51409 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -56,7 +56,6 @@ store: new gl.PipelineStore(), }, components: { - 'vue-commit-link': gl.VueCommitLink, 'vue-pipelines': gl.VuePipeLines, }, template: "" -- cgit v1.2.1 From c373706f2f188672ba24b2a545b6a50e374dd316 Mon Sep 17 00:00:00 2001 From: Regis Date: Sun, 30 Oct 2016 15:16:42 -0600 Subject: remove singleton in favor of components --- .../vue_pipelines_index/status_data_icons.js.es6 | 56 ---------------------- 1 file changed, 56 deletions(-) delete mode 100644 app/assets/javascripts/vue_pipelines_index/status_data_icons.js.es6 (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/status_data_icons.js.es6 b/app/assets/javascripts/vue_pipelines_index/status_data_icons.js.es6 deleted file mode 100644 index b4e0c07a665..00000000000 --- a/app/assets/javascripts/vue_pipelines_index/status_data_icons.js.es6 +++ /dev/null @@ -1,56 +0,0 @@ -/* eslint-disable no-param-reassign */ - -((gl) => { - gl.RunnerStats = class { - constructor() { - return { - running: { - text: 'running', - color: '#E75E40', - pathOne: 'M12.5,7 C12.5,3.96243388 10.0375661,1.5 7,1.5 C3.96243388,1.5 1.5,3.96243388 1.5,7 C1.5,10.0375661 3.96243388,12.5 7,12.5 C10.0375661,12.5 12.5,10.0375661 12.5,7 Z M0,7 C0,3.13400675 3.13400675,0 7,0 C10.8659932,0 14,3.13400675 14,7 C14,10.8659932 10.8659932,14 7,14 C3.13400675,14 0,10.8659932 0,7 Z', - pathTwo: 'M4.69999981,5.30065012 C4.69999981,5.13460564 4.83842754,5 5.00354719,5 L5.89645243,5 C6.06409702,5 6.19999981,5.13308716 6.19999981,5.30065012 L6.19999981,8.69934988 C6.19999981,8.86539436 6.06157207,9 5.89645243,9 L5.00354719,9 C4.8359026,9 4.69999981,8.86691284 4.69999981,8.69934988 L4.69999981,5.30065012 Z M7.69999981,5.30065012 C7.69999981,5.13460564 7.83842754,5 8.00354719,5 L8.89645243,5 C9.06409702,5 9.19999981,5.13308716 9.19999981,5.30065012 L9.19999981,8.69934988 C9.19999981,8.86539436 9.06157207,9 8.89645243,9 L8.00354719,9 C7.8359026,9 7.69999981,8.86691284 7.69999981,8.69934988 L7.69999981,5.30065012 Z', - }, - passed: ` - - - - - - - - passed - `, - failed: ` - - - - - - -  failed - `, - created: ` -  created - `, - skipped: ` - - - - - - -  skipped - `, - pending: ` - - - - - - -  pending - `, - }; - } - }; -})(window.gl || (window.gl = {})); -- cgit v1.2.1 From 23b9a99fccd956a3bdc5adbd299b277fdd727d9b Mon Sep 17 00:00:00 2001 From: Regis Date: Sun, 30 Oct 2016 15:23:13 -0600 Subject: will discuss what to do on error at a later time --- app/assets/javascripts/vue_pipelines_index/store.js.es6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index 38797f85f0a..f1cd991994d 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -9,7 +9,7 @@ .then((response) => { vue.set(this, 'pipelines', JSON.parse(response.body)); }, () => { - vue.set(this, 'pipelines', []); + console.error('API Error for Pipelines'); }); goFetch(Vue); -- cgit v1.2.1 From 1439b9b8d688e5650be565bd6ffe890ba4393c82 Mon Sep 17 00:00:00 2001 From: Regis Date: Sun, 30 Oct 2016 22:11:57 -0600 Subject: can grab commits prior to pipelines - might need more custom API --- .../javascripts/vue_pipelines_index/index.js.es6 | 1 - .../vue_pipelines_index/pipelines.vue.js.es6 | 27 ++++++++++++++++++---- .../javascripts/vue_pipelines_index/store.js.es6 | 21 +++++++++++++++-- app/views/projects/pipelines/index.html.haml | 1 + 4 files changed, 43 insertions(+), 7 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/index.js.es6 b/app/assets/javascripts/vue_pipelines_index/index.js.es6 index 36661553444..fcf91107da5 100644 --- a/app/assets/javascripts/vue_pipelines_index/index.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/index.js.es6 @@ -4,5 +4,4 @@ //= require ./store.js.es6 //= require ./running_icon.vue.js.es6 //= require ./running.vue.js.es6 -//= require ./status_data_icons.js.es6 //= require ./pipelines.vue.js.es6 diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 index ba6ef3011ab..1ff7b117223 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 @@ -9,7 +9,7 @@ data() { return { pipelines: [], - runnerStats: new gl.RunnerStats(), + commits: [], }; }, props: [ @@ -17,6 +17,7 @@ 'store', ], created() { + this.store.fetchCommits.call(this, Vue); this.store.fetchDataLoop.call(this, Vue); }, methods: { @@ -57,10 +58,28 @@
- {{shortSha(pipeline)}} + {{shortSha(pipeline)}} +

- - fix broken repo 500 errors in UI and added relevant specs + + + + + fix broken repo 500 errors in UI and added relevant specs +

diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index f1cd991994d..f9e802714df 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -12,11 +12,28 @@ console.error('API Error for Pipelines'); }); - goFetch(Vue); setInterval(() => { console.log('DID IT'); goFetch(Vue); - }, 3000); + }, 30000); + } + + fetchCommits(vue) { + const goFetch = vueSet => + this.$http.get(`/api/v3/projects/${this.scope}/pipelines`) + .then((response) => { + vueSet.set(this, 'pipelines', JSON.parse(response.body)); + }, () => { + console.error('API Error for Pipelines'); + }); + + this.$http.get(`/api/v3/projects/${this.scope}/repository/commits`) + .then((response) => { + vue.set(this, 'commits', JSON.parse(response.body)); + }, () => { + console.error('API Error for Pipelines'); + }) + .then(() => goFetch(vue)); } }; })(window.gl || (window.gl = {})); diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index 6309de51409..718e6b73c93 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -53,6 +53,7 @@ el: ".app", data:{ scope: "#{@project.id}", + commits: "#{@commit}", store: new gl.PipelineStore(), }, components: { -- cgit v1.2.1 From 5ed18942685d70d556f035d6eb00d374cf0a7606 Mon Sep 17 00:00:00 2001 From: Regis Date: Sun, 30 Oct 2016 22:14:15 -0600 Subject: remove non existant commit value --- app/views/projects/pipelines/index.html.haml | 1 - 1 file changed, 1 deletion(-) (limited to 'app') diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index 718e6b73c93..6309de51409 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -53,7 +53,6 @@ el: ".app", data:{ scope: "#{@project.id}", - commits: "#{@commit}", store: new gl.PipelineStore(), }, components: { -- cgit v1.2.1 From 2caf62d1a22d39f312c7306c408e40120ec362db Mon Sep 17 00:00:00 2001 From: Regis Date: Sun, 30 Oct 2016 22:22:08 -0600 Subject: refactor --- .../javascripts/vue_pipelines_index/store.js.es6 | 28 ++++++++-------------- 1 file changed, 10 insertions(+), 18 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index f9e802714df..046ec342478 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -2,38 +2,30 @@ /* eslint-disable no-param-reassign */ ((gl) => { + const goFetch = (that, vue) => + that.$http.get(`/api/v3/projects/${that.scope}/pipelines`) + .then((response) => { + vue.set(that, 'pipelines', JSON.parse(response.body)); + }, () => { + console.error('API Error for Pipelines'); + }); + gl.PipelineStore = class { fetchDataLoop(Vue) { - const goFetch = vue => - this.$http.get(`/api/v3/projects/${this.scope}/pipelines`) - .then((response) => { - vue.set(this, 'pipelines', JSON.parse(response.body)); - }, () => { - console.error('API Error for Pipelines'); - }); - setInterval(() => { console.log('DID IT'); - goFetch(Vue); + goFetch(this, Vue); }, 30000); } fetchCommits(vue) { - const goFetch = vueSet => - this.$http.get(`/api/v3/projects/${this.scope}/pipelines`) - .then((response) => { - vueSet.set(this, 'pipelines', JSON.parse(response.body)); - }, () => { - console.error('API Error for Pipelines'); - }); - this.$http.get(`/api/v3/projects/${this.scope}/repository/commits`) .then((response) => { vue.set(this, 'commits', JSON.parse(response.body)); }, () => { console.error('API Error for Pipelines'); }) - .then(() => goFetch(vue)); + .then(() => goFetch(this, vue)); } }; })(window.gl || (window.gl = {})); -- cgit v1.2.1 From cbd1303bec800dbacf2769ffb4f7ec63f4035eaf Mon Sep 17 00:00:00 2001 From: selfup Date: Mon, 31 Oct 2016 00:55:10 -0600 Subject: relative sha paths for commits --- app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 index 1ff7b117223..7bfd49344ca 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 @@ -60,7 +60,7 @@ {{shortSha(pipeline)}} + href="./commit/{{pipeline.sha}}">{{shortSha(pipeline)}}

fix broken repo 500 errors in UI and added relevant specs -- cgit v1.2.1 From c32c77a095a4fb5cebb6db47fa031e1f8752031e Mon Sep 17 00:00:00 2001 From: selfup Date: Mon, 31 Oct 2016 01:15:29 -0600 Subject: pagination exists - will become dynamic soon --- app/assets/javascripts/vue_pipelines_index/store.js.es6 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index 046ec342478..6a909f74e53 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -3,7 +3,7 @@ ((gl) => { const goFetch = (that, vue) => - that.$http.get(`/api/v3/projects/${that.scope}/pipelines`) + that.$http.get(`/api/v3/projects/${that.scope}/pipelines?per_page=5&page=1`) .then((response) => { vue.set(that, 'pipelines', JSON.parse(response.body)); }, () => { @@ -19,7 +19,7 @@ } fetchCommits(vue) { - this.$http.get(`/api/v3/projects/${this.scope}/repository/commits`) + this.$http.get(`/api/v3/projects/${this.scope}/repository/commits?per_page=5&page=1`) .then((response) => { vue.set(this, 'commits', JSON.parse(response.body)); }, () => { -- cgit v1.2.1 From a42140d08fea03acf406c64db5de67beee4b8107 Mon Sep 17 00:00:00 2001 From: Regis Date: Mon, 31 Oct 2016 13:02:34 -0600 Subject: page specific js - remove inline js - refactor --- .../javascripts/vue_pipelines_index/index.js.es6 | 23 ++++++++++++++++++++++ .../vue_pipelines_index/pipelines.vue.js.es6 | 8 ++++++++ .../javascripts/vue_pipelines_index/store.js.es6 | 13 +++++++++--- app/assets/javascripts/vue_pipelines_loader.js.es6 | 1 - app/views/projects/pipelines/index.html.haml | 22 +++------------------ 5 files changed, 44 insertions(+), 23 deletions(-) delete mode 100644 app/assets/javascripts/vue_pipelines_loader.js.es6 (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/index.js.es6 b/app/assets/javascripts/vue_pipelines_index/index.js.es6 index fcf91107da5..4b69c4d4c7d 100644 --- a/app/assets/javascripts/vue_pipelines_index/index.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/index.js.es6 @@ -1,3 +1,5 @@ +/* global Vue, VueResource, gl */ + //= require vue //= require vue-resource @@ -5,3 +7,24 @@ //= require ./running_icon.vue.js.es6 //= require ./running.vue.js.es6 //= require ./pipelines.vue.js.es6 + +(() => { + const project = document.querySelector('.table-holder'); + + Vue.use(VueResource); + + new Vue({ + el: '.vue-pipelines-index', + data: { + scope: project.dataset.projectId, + store: new gl.PipelineStore(), + }, + components: { + 'vue-pipelines': gl.VuePipeLines, + }, + template: '' + + '

' + + "" + + '
', + }); +})(); diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 index 7bfd49344ca..021a5ca8743 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 @@ -10,6 +10,8 @@ return { pipelines: [], commits: [], + currentPage: '', + intervalId: '', }; }, props: [ @@ -24,6 +26,11 @@ shortSha(pipeline) { return pipeline.sha.slice(0, 8); }, + changePage() { + // clearInterval(this.intervalId); + // this.store.fetchCommits.call(this, Vue); + // this.store.fetchDataLoop.call(this, Vue); + }, }, template: ` @@ -52,6 +59,7 @@
+ master
diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index 6a909f74e53..bdba9575013 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -2,8 +2,12 @@ /* eslint-disable no-param-reassign */ ((gl) => { + const api = '/api/v3/projects'; + const goFetch = (that, vue) => - that.$http.get(`/api/v3/projects/${that.scope}/pipelines?per_page=5&page=1`) + that.$http.get( + `${api}/${that.scope}/pipelines?per_page=5&page=1` + ) .then((response) => { vue.set(that, 'pipelines', JSON.parse(response.body)); }, () => { @@ -12,14 +16,17 @@ gl.PipelineStore = class { fetchDataLoop(Vue) { - setInterval(() => { + // eventually clearInterval(this.intervalId) + this.intervalId = setInterval(() => { console.log('DID IT'); goFetch(this, Vue); }, 30000); } fetchCommits(vue) { - this.$http.get(`/api/v3/projects/${this.scope}/repository/commits?per_page=5&page=1`) + this.$http.get( + `${api}/${this.scope}/repository/commits?per_page=5&page=1` + ) .then((response) => { vue.set(this, 'commits', JSON.parse(response.body)); }, () => { diff --git a/app/assets/javascripts/vue_pipelines_loader.js.es6 b/app/assets/javascripts/vue_pipelines_loader.js.es6 deleted file mode 100644 index 1b8ba72b697..00000000000 --- a/app/assets/javascripts/vue_pipelines_loader.js.es6 +++ /dev/null @@ -1 +0,0 @@ -//= require_tree ./vue_pipelines_index diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index 6309de51409..d7aebe584f8 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -42,24 +42,8 @@ %div .nothing-here-block No pipelines to show - else - .table-holder + .table-holder{"data-project-id": "#{@project.id}"} %table.table.ci-table - %tbody.app + %tbody.vue-pipelines-index -:javascript - Vue.use(VueResource); - - var vm = new Vue({ - el: ".app", - data:{ - scope: "#{@project.id}", - store: new gl.PipelineStore(), - }, - components: { - 'vue-pipelines': gl.VuePipeLines, - }, - template: "" - + "
" - + "" - + "
", - }) += page_specific_javascript_tag('vue_pipelines_index/index.js') \ No newline at end of file -- cgit v1.2.1 From 87d4d235683f5a40acec6c73116f1217caece5c2 Mon Sep 17 00:00:00 2001 From: Regis Date: Mon, 31 Oct 2016 15:06:25 -0600 Subject: remove commit endpoint callprep for backend api to be updated or new endpoint to be built --- .../vue_pipelines_index/pipelines.vue.js.es6 | 2 -- .../javascripts/vue_pipelines_index/store.js.es6 | 36 ++++++++-------------- 2 files changed, 13 insertions(+), 25 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 index 021a5ca8743..c1a2ac3292e 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 @@ -9,7 +9,6 @@ data() { return { pipelines: [], - commits: [], currentPage: '', intervalId: '', }; @@ -19,7 +18,6 @@ 'store', ], created() { - this.store.fetchCommits.call(this, Vue); this.store.fetchDataLoop.call(this, Vue); }, methods: { diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index bdba9575013..06282744d8b 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -4,35 +4,25 @@ ((gl) => { const api = '/api/v3/projects'; - const goFetch = (that, vue) => - that.$http.get( - `${api}/${that.scope}/pipelines?per_page=5&page=1` - ) - .then((response) => { - vue.set(that, 'pipelines', JSON.parse(response.body)); - }, () => { - console.error('API Error for Pipelines'); - }); - gl.PipelineStore = class { fetchDataLoop(Vue) { + const goFetch = () => + this.$http.get( + `${api}/${this.scope}/pipelines?per_page=5&page=1` + ) + .then((response) => { + Vue.set(this, 'pipelines', JSON.parse(response.body)); + }, () => { + console.error('API Error for Pipelines'); + }); + + goFetch(); + // eventually clearInterval(this.intervalId) this.intervalId = setInterval(() => { console.log('DID IT'); - goFetch(this, Vue); + goFetch(); }, 30000); } - - fetchCommits(vue) { - this.$http.get( - `${api}/${this.scope}/repository/commits?per_page=5&page=1` - ) - .then((response) => { - vue.set(this, 'commits', JSON.parse(response.body)); - }, () => { - console.error('API Error for Pipelines'); - }) - .then(() => goFetch(this, vue)); - } }; })(window.gl || (window.gl = {})); -- cgit v1.2.1 From 257146032e1340701772097cfe7e4b29b7b56c97 Mon Sep 17 00:00:00 2001 From: Regis Date: Mon, 31 Oct 2016 15:51:24 -0600 Subject: begin pagination logic - add Flash to error - refactor --- app/assets/javascripts/vue_pipelines_index/index.js.es6 | 2 +- .../javascripts/vue_pipelines_index/pipelines.vue.js.es6 | 9 ++++++--- app/assets/javascripts/vue_pipelines_index/store.js.es6 | 16 ++++++---------- 3 files changed, 13 insertions(+), 14 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/index.js.es6 b/app/assets/javascripts/vue_pipelines_index/index.js.es6 index 4b69c4d4c7d..015716b0540 100644 --- a/app/assets/javascripts/vue_pipelines_index/index.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/index.js.es6 @@ -13,7 +13,7 @@ Vue.use(VueResource); - new Vue({ + return new Vue({ el: '.vue-pipelines-index', data: { scope: project.dataset.projectId, diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 index c1a2ac3292e..a209b9d0532 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 @@ -11,6 +11,7 @@ pipelines: [], currentPage: '', intervalId: '', + pageNum: 'page=1', }; }, props: [ @@ -18,7 +19,10 @@ 'store', ], created() { - this.store.fetchDataLoop.call(this, Vue); + const url = window.location.href; + if (url.includes('?')) this.pageNum = url.split('?')[1]; + // now fetch page appropriate data + this.store.fetchDataLoop.call(this, Vue, this.pageNum); }, methods: { shortSha(pipeline) { @@ -26,8 +30,7 @@ }, changePage() { // clearInterval(this.intervalId); - // this.store.fetchCommits.call(this, Vue); - // this.store.fetchDataLoop.call(this, Vue); + // this.store.fetchDataLoop.call(this, Vue, this.pageNum); }, }, template: ` diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index 06282744d8b..17f530a8ca2 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -1,28 +1,24 @@ -/* global gl */ +/* global gl, Flash */ /* eslint-disable no-param-reassign */ ((gl) => { const api = '/api/v3/projects'; gl.PipelineStore = class { - fetchDataLoop(Vue) { + fetchDataLoop(Vue, pageNum) { const goFetch = () => - this.$http.get( - `${api}/${this.scope}/pipelines?per_page=5&page=1` - ) + this.$http.get(`${api}/${this.scope}/pipelines?per_page=30&${pageNum}`) .then((response) => { Vue.set(this, 'pipelines', JSON.parse(response.body)); - }, () => { - console.error('API Error for Pipelines'); - }); + }, () => new Flash('Something went wrong on our end.')); + // inital fetch and then start timeout loop goFetch(); // eventually clearInterval(this.intervalId) this.intervalId = setInterval(() => { - console.log('DID IT'); goFetch(); - }, 30000); + }, 60000); } }; })(window.gl || (window.gl = {})); -- cgit v1.2.1 From c2d6969c97bf4c524c58722c2c5f0e4dba139e45 Mon Sep 17 00:00:00 2001 From: Regis Date: Mon, 31 Oct 2016 16:10:50 -0600 Subject: formatting --- app/assets/javascripts/vue_pipelines_index/store.js.es6 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index 17f530a8ca2..789e8e791b6 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -10,7 +10,9 @@ this.$http.get(`${api}/${this.scope}/pipelines?per_page=30&${pageNum}`) .then((response) => { Vue.set(this, 'pipelines', JSON.parse(response.body)); - }, () => new Flash('Something went wrong on our end.')); + }, () => new Flash( + 'Something went wrong on our end.' + )); // inital fetch and then start timeout loop goFetch(); -- cgit v1.2.1 From ae4eacadf35fec8db8d7c316dcc8fe8d0f57535b Mon Sep 17 00:00:00 2001 From: Regis Date: Mon, 31 Oct 2016 16:45:25 -0600 Subject: fix styling by removing main div --- app/assets/javascripts/vue_pipelines_index/index.js.es6 | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/index.js.es6 b/app/assets/javascripts/vue_pipelines_index/index.js.es6 index 015716b0540..35f78656856 100644 --- a/app/assets/javascripts/vue_pipelines_index/index.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/index.js.es6 @@ -22,9 +22,8 @@ components: { 'vue-pipelines': gl.VuePipeLines, }, - template: '' - + '
' - + "" - + '
', + template: ` + + `, }); })(); -- cgit v1.2.1 From c659ffcbc52c433879c4108276175f28f1105e6f Mon Sep 17 00:00:00 2001 From: Regis Date: Mon, 31 Oct 2016 17:17:29 -0600 Subject: breaking more HTML out of template --- .../javascripts/vue_pipelines_index/index.js.es6 | 4 +- .../vue_pipelines_index/pipelines.vue.js.es6 | 167 ++++++--------------- .../vue_pipelines_index/stages.vue.js.es6 | 83 ++++++++++ app/views/projects/pipelines/index.html.haml | 2 +- 4 files changed, 135 insertions(+), 121 deletions(-) create mode 100644 app/assets/javascripts/vue_pipelines_index/stages.vue.js.es6 (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/index.js.es6 b/app/assets/javascripts/vue_pipelines_index/index.js.es6 index 35f78656856..c7a5204c7d6 100644 --- a/app/assets/javascripts/vue_pipelines_index/index.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/index.js.es6 @@ -6,15 +6,17 @@ //= require ./store.js.es6 //= require ./running_icon.vue.js.es6 //= require ./running.vue.js.es6 +//= require ./stages.vue.js.es6 //= require ./pipelines.vue.js.es6 (() => { const project = document.querySelector('.table-holder'); Vue.use(VueResource); + // Vue.config.silent = true; return new Vue({ - el: '.vue-pipelines-index', + el: '#vue-pipelines-index', data: { scope: project.dataset.projectId, store: new gl.PipelineStore(), diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 index a209b9d0532..34b8ceecd29 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 @@ -5,6 +5,7 @@ gl.VuePipeLines = Vue.extend({ components: { 'vue-running-pipeline': gl.VueRunningPipeline, + 'vue-stages': gl.VueStages, }, data() { return { @@ -92,128 +93,56 @@

- - - - - - - - - - + + - diff --git a/app/assets/javascripts/vue_pipelines_index/stages.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/stages.vue.js.es6 new file mode 100644 index 00000000000..0baf90dcf60 --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_index/stages.vue.js.es6 @@ -0,0 +1,83 @@ +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VueStages = Vue.extend({ + template: ` + + + + + + + + + `, + }); +})(window.gl || (window.gl = {})); diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index d7aebe584f8..8bd718749e4 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -44,6 +44,6 @@ - else .table-holder{"data-project-id": "#{@project.id}"} %table.table.ci-table - %tbody.vue-pipelines-index + %tbody#vue-pipelines-index = page_specific_javascript_tag('vue_pipelines_index/index.js') \ No newline at end of file -- cgit v1.2.1 From 13f11b470e0b94da082099ca32f8850dbce01b19 Mon Sep 17 00:00:00 2001 From: Regis Date: Tue, 1 Nov 2016 10:38:17 -0600 Subject: add comments on data needed from API to help extract into components --- .../vue_pipelines_index/pipelines.vue.js.es6 | 43 +++++++++++++++++++--- 1 file changed, 38 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 index 34b8ceecd29..6d6c866c449 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 @@ -61,8 +61,10 @@
- - master + + master
@@ -76,6 +78,12 @@ + + fix broken repo 500 errors in UI and added relevant specs

+ @@ -108,7 +135,10 @@
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + `, }); diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index 8bd718749e4..a7d837227d5 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -36,14 +36,12 @@ = link_to ci_lint_path, class: 'btn btn-default' do %span CI Lint - %div.content-list.pipelines + %div.content-list.pipelines{"data-project-id": "#{@project.id}"} - stages = @pipelines.stages - if @pipelines.blank? %div .nothing-here-block No pipelines to show - else - .table-holder{"data-project-id": "#{@project.id}"} - %table.table.ci-table - %tbody#vue-pipelines-index + .vue-pipelines-index = page_specific_javascript_tag('vue_pipelines_index/index.js') \ No newline at end of file -- cgit v1.2.1 From 5ba83d961a7cf8bebea9f9e9814354be769041e9 Mon Sep 17 00:00:00 2001 From: Regis Date: Tue, 1 Nov 2016 18:48:45 -0600 Subject: extracted Commit Column to vue component --- .../vue_pipelines_index/branch_commit.vue.js.es6 | 54 ++++++++++++++++++++++ .../javascripts/vue_pipelines_index/index.js.es6 | 1 + .../vue_pipelines_index/pipelines.vue.js.es6 | 52 +++------------------ app/views/projects/pipelines/index.html.haml | 2 +- 4 files changed, 63 insertions(+), 46 deletions(-) create mode 100644 app/assets/javascripts/vue_pipelines_index/branch_commit.vue.js.es6 (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/branch_commit.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/branch_commit.vue.js.es6 new file mode 100644 index 00000000000..46cbf706d97 --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_index/branch_commit.vue.js.es6 @@ -0,0 +1,54 @@ +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VueBranchCommit = Vue.extend({ + props: ['pipeline', 'shortsha'], + template: ` +
+ +
+ + master +
+ + + +
+ {{shortsha(pipeline)}} + +

+ + + + + + + fix broken repo 500 errors in UI and added relevant specs + +

+ `, + }); +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/index.js.es6 b/app/assets/javascripts/vue_pipelines_index/index.js.es6 index 4450fde4103..14a4a5d9b1d 100644 --- a/app/assets/javascripts/vue_pipelines_index/index.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/index.js.es6 @@ -8,6 +8,7 @@ //= require ./running.vue.js.es6 //= require ./stages.vue.js.es6 //= require ./pipeline_actions.vue.js.es6 +//= require ./branch_commit.vue.js.es6 //= require ./pipelines.vue.js.es6 (() => { diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 index 16da8b8f423..0b1c2c33ca0 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 @@ -7,6 +7,7 @@ 'vue-running-pipeline': gl.VueRunningPipeline, 'vue-stages': gl.VueStages, 'vue-pipeline-actions': gl.VuePipelineActions, + 'vue-branch-commit': gl.VueBranchCommit, }, data() { return { @@ -27,7 +28,7 @@ this.store.fetchDataLoop.call(this, Vue, this.pageNum); }, methods: { - shortSha(pipeline) { + shortsha(pipeline) { return pipeline.sha.slice(0, 8); }, changePage() { @@ -61,50 +62,11 @@ {{pipeline.user}} -
- -
- - master -
- - - -
- {{shortSha(pipeline)}} - -

- - - - - - - fix broken repo 500 errors in UI and added relevant specs - -

+ + + master +
+ + +
- - master -
- - - -
- {{shortsha(pipeline)}} - -

- - - - - - fix broken repo 500 errors in UI and added relevant specs + {{shortsha(pipeline)}} -

+

+ + + + + + + fix broken repo 500 errors in UI and added relevant specs + +

+ `, }); })(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/index.js.es6 b/app/assets/javascripts/vue_pipelines_index/index.js.es6 index 14a4a5d9b1d..b8bcfdb30c3 100644 --- a/app/assets/javascripts/vue_pipelines_index/index.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/index.js.es6 @@ -4,6 +4,8 @@ //= require vue-resource //= require ./store.js.es6 +//= require ./pipeline_url.vue.js.es6 +//= require ./pipeline_head.vue.js.es6 //= require ./running_icon.vue.js.es6 //= require ./running.vue.js.es6 //= require ./stages.vue.js.es6 diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.vue.js.es6 index aa1069cff9f..a6ff2f10ccf 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.vue.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.vue.js.es6 @@ -5,6 +5,7 @@ gl.VuePipelineActions = Vue.extend({ // props: ['builds'], template: ` +
@@ -71,6 +72,7 @@
+ `, }); })(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_head.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_head.vue.js.es6 new file mode 100644 index 00000000000..2ead571aa9f --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_index/pipeline_head.vue.js.es6 @@ -0,0 +1,26 @@ +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VuePipelineHead = Vue.extend({ + components: { + 'vue-running-icon': gl.VueRunningIcon, + }, + props: [ + 'pipeline', + 'pipelineurl', + ], + template: ` + + + Status + Pipeline + Commit + Stages + + + + + `, + }); +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_url.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_url.vue.js.es6 new file mode 100644 index 00000000000..148fe58d9ce --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_index/pipeline_url.vue.js.es6 @@ -0,0 +1,23 @@ +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VuePipelineUrl = Vue.extend({ + components: { + 'vue-running-icon': gl.VueRunningIcon, + }, + props: [ + 'pipeline', + 'pipelineurl', + ], + template: ` + + + #{{pipeline.id}} + + by + {{pipeline.user}} + + `, + }); +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 index bdb52b21b20..86c18ace09e 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 @@ -1,5 +1,5 @@ /* global Vue, gl */ -/* eslint-disable no-param-reassign */ +/* eslint-disable no-param-reassign, no-bitwise*/ ((gl) => { gl.VuePipeLines = Vue.extend({ @@ -8,6 +8,8 @@ 'vue-stages': gl.VueStages, 'vue-pipeline-actions': gl.VuePipelineActions, 'vue-branch-commit': gl.VueBranchCommit, + 'vue-pipeline-url': gl.VuePipelineUrl, + 'vue-pipeline-head': gl.VuePipelineHead, }, data() { return { @@ -22,11 +24,8 @@ 'store', ], created() { - // ** `.includes` does not work in PhantomJS ** - - // const url = window.location.toString(); - // if (url.includes('?')) this.pageNum = url.split('?')[1]; - // now fetch page appropriate data + const url = window.location.toString(); + if (~url.indexOf('?')) this.pageNum = url.split('?')[1]; this.store.fetchDataLoop.call(this, Vue, this.pageNum); }, methods: { @@ -37,66 +36,36 @@ // clearInterval(this.intervalId); // this.store.fetchDataLoop.call(this, Vue, this.pageNum); }, + pipelineurl(id) { + return `pipelines/${id}`; + }, }, template: `
- - - - - - - - - - - - - - - + + - + + + + + - +
StatusPipelineCommitStages
- - #{{pipeline.id}} - - by - {{pipeline.user}} - - +
- - +
diff --git a/app/assets/javascripts/vue_pipelines_index/running.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/running.vue.js.es6 index 5edf8403bd9..8d18f5f3aa3 100644 --- a/app/assets/javascripts/vue_pipelines_index/running.vue.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/running.vue.js.es6 @@ -7,11 +7,12 @@ 'vue-running-icon': gl.VueRunningIcon, }, props: [ - 'pipe', + 'pipeline', + 'pipelineurl', ], template: ` - + diff --git a/app/assets/javascripts/vue_pipelines_index/stages.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/stages.vue.js.es6 index 400eb0e4d3f..da8c9280486 100644 --- a/app/assets/javascripts/vue_pipelines_index/stages.vue.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/stages.vue.js.es6 @@ -4,86 +4,107 @@ ((gl) => { gl.VueStages = Vue.extend({ template: ` - - - - - - - - + + + + + + + + + + + `, }); })(window.gl || (window.gl = {})); -- cgit v1.2.1 From 25e60f879fc21e55902ad5c069a5de0a3e340db7 Mon Sep 17 00:00:00 2001 From: Regis Date: Wed, 2 Nov 2016 18:54:04 -0600 Subject: basic pagination ^_^ - will make component dynamic soon --- .../javascripts/vue_pipelines_index/index.js.es6 | 1 + .../vue_pipelines_index/pipelines.vue.js.es6 | 71 +++++++++++++--------- .../javascripts/vue_pipelines_index/store.js.es6 | 5 +- .../vue_gl_pagination.vue.js.es6 | 54 ++++++++++++++++ 4 files changed, 99 insertions(+), 32 deletions(-) create mode 100644 app/assets/javascripts/vue_pipelines_index/vue_gl_pagination.vue.js.es6 (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/index.js.es6 b/app/assets/javascripts/vue_pipelines_index/index.js.es6 index b8bcfdb30c3..6ecbc1ba8ff 100644 --- a/app/assets/javascripts/vue_pipelines_index/index.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/index.js.es6 @@ -5,6 +5,7 @@ //= require ./store.js.es6 //= require ./pipeline_url.vue.js.es6 +//= require ./vue_gl_pagination.vue.js.es6 //= require ./pipeline_head.vue.js.es6 //= require ./running_icon.vue.js.es6 //= require ./running.vue.js.es6 diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 index 86c18ace09e..4706ea61c8e 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 @@ -10,13 +10,14 @@ 'vue-branch-commit': gl.VueBranchCommit, 'vue-pipeline-url': gl.VuePipelineUrl, 'vue-pipeline-head': gl.VuePipelineHead, + 'vue-gl-pagination': gl.VueGlPagination, }, data() { return { pipelines: [], currentPage: '', intervalId: '', - pageNum: 'page=1', + pageNum: 1, }; }, props: [ @@ -25,50 +26,60 @@ ], created() { const url = window.location.toString(); - if (~url.indexOf('?')) this.pageNum = url.split('?')[1]; + if (~url.indexOf('?')) this.pageNum = url.split('?')[1].split('=')[1]; this.store.fetchDataLoop.call(this, Vue, this.pageNum); }, methods: { shortsha(pipeline) { return pipeline.sha.slice(0, 8); }, - changePage() { - // clearInterval(this.intervalId); - // this.store.fetchDataLoop.call(this, Vue, this.pageNum); + changepage(event) { + this.pageNum = +event.target.innerText; + // use p instead of page to avoid rails tyring to make an actual request + window.history.pushState({}, null, `?p=${this.pageNum}`); + clearInterval(this.intervalId); + this.store.fetchDataLoop.call(this, Vue, this.pageNum); }, pipelineurl(id) { return `pipelines/${id}`; }, }, template: ` -
- - - - - + + + +
+
+ +
`, }); diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index 66cb989030a..bf5fba45194 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -3,11 +3,12 @@ ((gl) => { const api = '/api/v3/projects'; + const paginate = '?per_page=5&page='; gl.PipelineStore = class { fetchDataLoop(Vue, pageNum) { const goFetch = () => - this.$http.get(`${api}/${this.scope}/pipelines?per_page=30&${pageNum}`) + this.$http.get(`${api}/${this.scope}/pipelines${paginate}${pageNum}`) .then((response) => { Vue.set(this, 'pipelines', JSON.parse(response.body)); }, () => new Flash( @@ -20,7 +21,7 @@ // eventually clearInterval(this.intervalId) this.intervalId = setInterval(() => { goFetch(); - }, 3000); + }, 30000); } }; })(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/vue_gl_pagination.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/vue_gl_pagination.vue.js.es6 new file mode 100644 index 00000000000..29d4a4df511 --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_index/vue_gl_pagination.vue.js.es6 @@ -0,0 +1,54 @@ +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VueGlPagination = Vue.extend({ + props: [ + 'changepage', + 'pages', + ], + template: ` +
+ +
+ `, + }); +})(window.gl || (window.gl = {})); -- cgit v1.2.1 From c249fb2ee9b522d02f49eee9734a1d6665d01e14 Mon Sep 17 00:00:00 2001 From: Regis Date: Wed, 2 Nov 2016 22:14:46 -0600 Subject: formatting --- app/assets/javascripts/vue_pipelines_index/running.vue.js.es6 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/running.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/running.vue.js.es6 index 8d18f5f3aa3..e363cb3c14e 100644 --- a/app/assets/javascripts/vue_pipelines_index/running.vue.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/running.vue.js.es6 @@ -14,7 +14,12 @@ - +  running -- cgit v1.2.1 From 77b0d6058ead2f42200c8a69dcd0e31561deae9e Mon Sep 17 00:00:00 2001 From: Regis Date: Wed, 2 Nov 2016 22:41:51 -0600 Subject: count passing through - last page known --- app/assets/javascripts/vue_pipelines_index/index.js.es6 | 9 +++++++-- app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 | 2 ++ .../javascripts/vue_pipelines_index/vue_gl_pagination.vue.js.es6 | 9 ++++++++- app/views/projects/pipelines/index.html.haml | 2 +- 4 files changed, 18 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/index.js.es6 b/app/assets/javascripts/vue_pipelines_index/index.js.es6 index 6ecbc1ba8ff..4e335ca1d13 100644 --- a/app/assets/javascripts/vue_pipelines_index/index.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/index.js.es6 @@ -18,12 +18,12 @@ const project = document.querySelector('.pipelines'); Vue.use(VueResource); - // Vue.config.silent = true; return new Vue({ el: '.vue-pipelines-index', data: { scope: project.dataset.projectId, + count: project.dataset.count, store: new gl.PipelineStore(), }, components: { @@ -31,7 +31,12 @@ }, template: `
- + +
`, }); diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 index 4706ea61c8e..2f3bdc7a2a9 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 @@ -23,6 +23,7 @@ props: [ 'scope', 'store', + 'count', ], created() { const url = window.location.toString(); @@ -78,6 +79,7 @@
diff --git a/app/assets/javascripts/vue_pipelines_index/vue_gl_pagination.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/vue_gl_pagination.vue.js.es6 index 29d4a4df511..977d0e2b240 100644 --- a/app/assets/javascripts/vue_pipelines_index/vue_gl_pagination.vue.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/vue_gl_pagination.vue.js.es6 @@ -6,7 +6,14 @@ props: [ 'changepage', 'pages', + 'count', ], + computed: { + lastpage() { + const lastPage = Math.ceil(+this.count / 5); + return `pipelines?page=${lastPage}`; + }, + }, template: ` diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index bd649a4fa2e..7bf727be930 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -36,7 +36,7 @@ = link_to ci_lint_path, class: 'btn btn-default' do %span CI Lint - %div.content-list.pipelines{"data-project-id": "#{@project.id}"} + %div.content-list.pipelines{"data-project-id": "#{@project.id}", "data-count": "#{@pipelines_count}"} - stages = @pipelines.stages - if @pipelines.blank? %div -- cgit v1.2.1 From 64e8ab95be436ccd22e087f39774b93ce6e4eeba Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 3 Nov 2016 11:20:15 -0600 Subject: pagination logic almost complete - active and inactive elements next - page gap not working --- .../vue_pipelines_index/pipelines.vue.js.es6 | 13 ++-- .../vue_gl_pagination.vue.js.es6 | 74 ++++++++++++---------- 2 files changed, 47 insertions(+), 40 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 index 2f3bdc7a2a9..77923e68004 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 @@ -17,7 +17,7 @@ pipelines: [], currentPage: '', intervalId: '', - pageNum: 1, + pagenum: 1, }; }, props: [ @@ -27,19 +27,19 @@ ], created() { const url = window.location.toString(); - if (~url.indexOf('?')) this.pageNum = url.split('?')[1].split('=')[1]; - this.store.fetchDataLoop.call(this, Vue, this.pageNum); + if (~url.indexOf('?')) this.pagenum = url.split('?')[1].split('=')[1]; + this.store.fetchDataLoop.call(this, Vue, this.pagenum); }, methods: { shortsha(pipeline) { return pipeline.sha.slice(0, 8); }, changepage(event) { - this.pageNum = +event.target.innerText; + this.pagenum = +event.target.innerText; // use p instead of page to avoid rails tyring to make an actual request - window.history.pushState({}, null, `?p=${this.pageNum}`); + window.history.pushState({}, null, `?p=${this.pagenum}`); clearInterval(this.intervalId); - this.store.fetchDataLoop.call(this, Vue, this.pageNum); + this.store.fetchDataLoop.call(this, Vue, this.pagenum); }, pipelineurl(id) { return `pipelines/${id}`; @@ -77,6 +77,7 @@ { gl.VueGlPagination = Vue.extend({ + data() { + return { + last: Math.ceil(+this.count / 5), + }; + }, props: [ 'changepage', 'pages', 'count', + 'pagenum', ], + methods: { + pagenumberstatus(n) { + if (n - 1 === +this.pagenum) return 'page active'; + return ''; + }, + }, computed: { lastpage() { - const lastPage = Math.ceil(+this.count / 5); - return `pipelines?page=${lastPage}`; + return `pipelines?p=${this.last}`; + }, + upcount() { + return +this.last + 1; + }, + prev() { + if (this.pagenum === 1) return 1; + return this.pagenum - 1; + }, + next() { + if (this.pagenum === this.last) return `pipelines?p=${this.pagenum}`; + return `pipelines?p=${this.pagenum + 1}`; }, }, template: `
-
    -
  • {{(n - 1)}}
  • - +
  • + +
  • -
  • - Last » +
  • + Last »
-- cgit v1.2.1 From 4d8314ae0f07549b4e77f3aca8a2e3a84f80cb9b Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 3 Nov 2016 11:34:18 -0600 Subject: move last to computed --- .../vue_pipelines_index/vue_gl_pagination.vue.js.es6 | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/vue_gl_pagination.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/vue_gl_pagination.vue.js.es6 index 48efa4bd57e..5f9e47bf3b2 100644 --- a/app/assets/javascripts/vue_pipelines_index/vue_gl_pagination.vue.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/vue_gl_pagination.vue.js.es6 @@ -3,11 +3,6 @@ ((gl) => { gl.VueGlPagination = Vue.extend({ - data() { - return { - last: Math.ceil(+this.count / 5), - }; - }, props: [ 'changepage', 'pages', @@ -21,6 +16,9 @@ }, }, computed: { + last() { + return Math.ceil(+this.count / 5) + }, lastpage() { return `pipelines?p=${this.last}`; }, @@ -38,10 +36,7 @@ }, template: `
-
    +
      -- cgit v1.2.1 From ea71e327f17c57e42d86717479a34af160d73d8e Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 3 Nov 2016 11:42:12 -0600 Subject: page gap works --- .../javascripts/vue_pipelines_index/vue_gl_pagination.vue.js.es6 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/vue_gl_pagination.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/vue_gl_pagination.vue.js.es6 index 5f9e47bf3b2..84b75b469f0 100644 --- a/app/assets/javascripts/vue_pipelines_index/vue_gl_pagination.vue.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/vue_gl_pagination.vue.js.es6 @@ -11,7 +11,7 @@ ], methods: { pagenumberstatus(n) { - if (n - 1 === +this.pagenum) return 'page active'; + if (n - 1 === +this.pagenum) return 'active'; return ''; }, }, @@ -43,8 +43,8 @@
    • {{(n - 1)}}
    • -
    • - +
    • +
    • {{(n - 1)}}
    • +
    • diff --git a/app/assets/javascripts/vue_pipelinesindex/store.js.es6 b/app/assets/javascripts/vue_pipelinesindex/store.js.es6 new file mode 100644 index 00000000000..bf5fba45194 --- /dev/null +++ b/app/assets/javascripts/vue_pipelinesindex/store.js.es6 @@ -0,0 +1,27 @@ +/* global gl, Flash */ +/* eslint-disable no-param-reassign */ + +((gl) => { + const api = '/api/v3/projects'; + const paginate = '?per_page=5&page='; + + gl.PipelineStore = class { + fetchDataLoop(Vue, pageNum) { + const goFetch = () => + this.$http.get(`${api}/${this.scope}/pipelines${paginate}${pageNum}`) + .then((response) => { + Vue.set(this, 'pipelines', JSON.parse(response.body)); + }, () => new Flash( + 'Something went wrong on our end.' + )); + + // inital fetch and then start timeout loop + goFetch(); + + // eventually clearInterval(this.intervalId) + this.intervalId = setInterval(() => { + goFetch(); + }, 30000); + } + }; +})(window.gl || (window.gl = {})); diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index 7bf727be930..0e3cec4aa07 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -41,6 +41,19 @@ - if @pipelines.blank? %div .nothing-here-block No pipelines to show + - elsif @scope == 'branches' || @scope == 'tags' || @scope == 'running' + .table-holder + %table.table.ci-table + %thead + %th Status + %th Pipeline + %th Commit + %th Stages + %th + %th.hidden-xs + + = render @pipelines, commit_sha: true, stage: true, allow_retry: true, stages: stages + = paginate @pipelines, theme: 'gitlab' - else .vue-pipelines-index -- cgit v1.2.1 From 18ff82c6a6949aa4c4b4efa77fc6e08e856eb79a Mon Sep 17 00:00:00 2001 From: Regis Date: Fri, 4 Nov 2016 09:56:45 -0600 Subject: remove extra dir when debugging eslint --- .../javascripts/vue_pipelinesindex/store.js.es6 | 27 ---------------------- 1 file changed, 27 deletions(-) delete mode 100644 app/assets/javascripts/vue_pipelinesindex/store.js.es6 (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelinesindex/store.js.es6 b/app/assets/javascripts/vue_pipelinesindex/store.js.es6 deleted file mode 100644 index bf5fba45194..00000000000 --- a/app/assets/javascripts/vue_pipelinesindex/store.js.es6 +++ /dev/null @@ -1,27 +0,0 @@ -/* global gl, Flash */ -/* eslint-disable no-param-reassign */ - -((gl) => { - const api = '/api/v3/projects'; - const paginate = '?per_page=5&page='; - - gl.PipelineStore = class { - fetchDataLoop(Vue, pageNum) { - const goFetch = () => - this.$http.get(`${api}/${this.scope}/pipelines${paginate}${pageNum}`) - .then((response) => { - Vue.set(this, 'pipelines', JSON.parse(response.body)); - }, () => new Flash( - 'Something went wrong on our end.' - )); - - // inital fetch and then start timeout loop - goFetch(); - - // eventually clearInterval(this.intervalId) - this.intervalId = setInterval(() => { - goFetch(); - }, 30000); - } - }; -})(window.gl || (window.gl = {})); -- cgit v1.2.1 From 45992dc98c027701b8c187ef50ad9afaf6e8e052 Mon Sep 17 00:00:00 2001 From: Regis Date: Fri, 4 Nov 2016 11:25:50 -0600 Subject: rename files for eslint --- .../vue_pipelines_index/branch_commit.js.es6 | 63 ++++++++++++ .../vue_pipelines_index/branch_commit.vue.js.es6 | 63 ------------ .../vue_pipelines_index/gl_pagination.js.es6 | 64 ++++++++++++ .../vue_pipelines_index/pipeline_actions.js.es6 | 78 +++++++++++++++ .../pipeline_actions.vue.js.es6 | 78 --------------- .../vue_pipelines_index/pipeline_head.js.es6 | 26 +++++ .../vue_pipelines_index/pipeline_head.vue.js.es6 | 26 ----- .../vue_pipelines_index/pipeline_url.js.es6 | 23 +++++ .../vue_pipelines_index/pipeline_url.vue.js.es6 | 23 ----- .../vue_pipelines_index/pipelines.js.es6 | 89 +++++++++++++++++ .../vue_pipelines_index/pipelines.vue.js.es6 | 89 ----------------- .../javascripts/vue_pipelines_index/running.js.es6 | 31 ++++++ .../vue_pipelines_index/running.vue.js.es6 | 31 ------ .../vue_pipelines_index/running_icon.js.es6 | 13 +++ .../vue_pipelines_index/running_icon.vue.js.es6 | 13 --- .../javascripts/vue_pipelines_index/stages.js.es6 | 110 +++++++++++++++++++++ .../vue_pipelines_index/stages.vue.js.es6 | 110 --------------------- .../vue_gl_pagination.vue.js.es6 | 64 ------------ 18 files changed, 497 insertions(+), 497 deletions(-) create mode 100644 app/assets/javascripts/vue_pipelines_index/branch_commit.js.es6 delete mode 100644 app/assets/javascripts/vue_pipelines_index/branch_commit.vue.js.es6 create mode 100644 app/assets/javascripts/vue_pipelines_index/gl_pagination.js.es6 create mode 100644 app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 delete mode 100644 app/assets/javascripts/vue_pipelines_index/pipeline_actions.vue.js.es6 create mode 100644 app/assets/javascripts/vue_pipelines_index/pipeline_head.js.es6 delete mode 100644 app/assets/javascripts/vue_pipelines_index/pipeline_head.vue.js.es6 create mode 100644 app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 delete mode 100644 app/assets/javascripts/vue_pipelines_index/pipeline_url.vue.js.es6 create mode 100644 app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 delete mode 100644 app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 create mode 100644 app/assets/javascripts/vue_pipelines_index/running.js.es6 delete mode 100644 app/assets/javascripts/vue_pipelines_index/running.vue.js.es6 create mode 100644 app/assets/javascripts/vue_pipelines_index/running_icon.js.es6 delete mode 100644 app/assets/javascripts/vue_pipelines_index/running_icon.vue.js.es6 create mode 100644 app/assets/javascripts/vue_pipelines_index/stages.js.es6 delete mode 100644 app/assets/javascripts/vue_pipelines_index/stages.vue.js.es6 delete mode 100644 app/assets/javascripts/vue_pipelines_index/vue_gl_pagination.vue.js.es6 (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/branch_commit.js.es6 b/app/assets/javascripts/vue_pipelines_index/branch_commit.js.es6 new file mode 100644 index 00000000000..ee8b1234697 --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_index/branch_commit.js.es6 @@ -0,0 +1,63 @@ +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VueBranchCommit = Vue.extend({ + props: ['pipeline', 'shortsha'], + methods: { + commiturl(sha) { + return `./commit/${sha}`; + }, + }, + template: ` + +
      + +
      + + master +
      + + + +
      + + {{shortsha(pipeline)}} + +

      + + + + + + + fix broken repo 500 errors in UI and added relevant specs + +

      + + `, + }); +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/branch_commit.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/branch_commit.vue.js.es6 deleted file mode 100644 index ee8b1234697..00000000000 --- a/app/assets/javascripts/vue_pipelines_index/branch_commit.vue.js.es6 +++ /dev/null @@ -1,63 +0,0 @@ -/* global Vue, gl */ -/* eslint-disable no-param-reassign */ - -((gl) => { - gl.VueBranchCommit = Vue.extend({ - props: ['pipeline', 'shortsha'], - methods: { - commiturl(sha) { - return `./commit/${sha}`; - }, - }, - template: ` - -
      - -
      - - master -
      - - - -
      - - {{shortsha(pipeline)}} - -

      - - - - - - - fix broken repo 500 errors in UI and added relevant specs - -

      - - `, - }); -})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/gl_pagination.js.es6 b/app/assets/javascripts/vue_pipelines_index/gl_pagination.js.es6 new file mode 100644 index 00000000000..84d908f8e52 --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_index/gl_pagination.js.es6 @@ -0,0 +1,64 @@ +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VueGlPagination = Vue.extend({ + props: [ + 'changepage', + 'pages', + 'count', + 'pagenum', + ], + methods: { + pagenumberstatus(n) { + if (n - 1 === +this.pagenum) return 'active'; + return ''; + }, + }, + computed: { + last() { + return Math.ceil(+this.count / 5); + }, + lastpage() { + return `pipelines?p=${this.last}`; + }, + upcount() { + return +this.last + 1; + }, + prev() { + if (this.pagenum === 1) return 1; + return this.pagenum - 1; + }, + next() { + if (this.pagenum === this.last) return `pipelines?p=${this.pagenum}`; + return `pipelines?p=${this.pagenum + 1}`; + }, + }, + template: ` +
      + +
      + `, + }); +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 new file mode 100644 index 00000000000..a6ff2f10ccf --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 @@ -0,0 +1,78 @@ +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VuePipelineActions = Vue.extend({ + // props: ['builds'], + template: ` + + + + `, + }); +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.vue.js.es6 deleted file mode 100644 index a6ff2f10ccf..00000000000 --- a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.vue.js.es6 +++ /dev/null @@ -1,78 +0,0 @@ -/* global Vue, gl */ -/* eslint-disable no-param-reassign */ - -((gl) => { - gl.VuePipelineActions = Vue.extend({ - // props: ['builds'], - template: ` - - - - `, - }); -})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_head.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_head.js.es6 new file mode 100644 index 00000000000..2ead571aa9f --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_index/pipeline_head.js.es6 @@ -0,0 +1,26 @@ +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VuePipelineHead = Vue.extend({ + components: { + 'vue-running-icon': gl.VueRunningIcon, + }, + props: [ + 'pipeline', + 'pipelineurl', + ], + template: ` + + + Status + Pipeline + Commit + Stages + + + + + `, + }); +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_head.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_head.vue.js.es6 deleted file mode 100644 index 2ead571aa9f..00000000000 --- a/app/assets/javascripts/vue_pipelines_index/pipeline_head.vue.js.es6 +++ /dev/null @@ -1,26 +0,0 @@ -/* global Vue, gl */ -/* eslint-disable no-param-reassign */ - -((gl) => { - gl.VuePipelineHead = Vue.extend({ - components: { - 'vue-running-icon': gl.VueRunningIcon, - }, - props: [ - 'pipeline', - 'pipelineurl', - ], - template: ` - - - Status - Pipeline - Commit - Stages - - - - - `, - }); -})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 new file mode 100644 index 00000000000..148fe58d9ce --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 @@ -0,0 +1,23 @@ +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VuePipelineUrl = Vue.extend({ + components: { + 'vue-running-icon': gl.VueRunningIcon, + }, + props: [ + 'pipeline', + 'pipelineurl', + ], + template: ` + + + #{{pipeline.id}} + + by + {{pipeline.user}} + + `, + }); +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_url.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_url.vue.js.es6 deleted file mode 100644 index 148fe58d9ce..00000000000 --- a/app/assets/javascripts/vue_pipelines_index/pipeline_url.vue.js.es6 +++ /dev/null @@ -1,23 +0,0 @@ -/* global Vue, gl */ -/* eslint-disable no-param-reassign */ - -((gl) => { - gl.VuePipelineUrl = Vue.extend({ - components: { - 'vue-running-icon': gl.VueRunningIcon, - }, - props: [ - 'pipeline', - 'pipelineurl', - ], - template: ` - - - #{{pipeline.id}} - - by - {{pipeline.user}} - - `, - }); -})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 new file mode 100644 index 00000000000..a1d472cc464 --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -0,0 +1,89 @@ +/* global Vue, gl */ +/* eslint-disable no-param-reassign, no-bitwise*/ + +((gl) => { + gl.VuePipeLines = Vue.extend({ + components: { + 'vue-running-pipeline': gl.VueRunningPipeline, + 'vue-stages': gl.VueStages, + 'vue-pipeline-actions': gl.VuePipelineActions, + 'vue-branch-commit': gl.VueBranchCommit, + 'vue-pipeline-url': gl.VuePipelineUrl, + 'vue-pipeline-head': gl.VuePipelineHead, + 'vue-gl-pagination': gl.VueGlPagination, + }, + data() { + return { + pipelines: [], + currentPage: '', + intervalId: '', + pagenum: 1, + }; + }, + props: [ + 'scope', + 'store', + 'count', + ], + created() { + const url = window.location.toString(); + if (~url.indexOf('?')) this.pagenum = url.split('?')[1].split('=')[1]; + this.store.fetchDataLoop.call(this, Vue, this.pagenum); + }, + methods: { + shortsha(pipeline) { + return pipeline.sha.slice(0, 8); + }, + changepage(event, last) { + if (last) this.pagenum = +last; + if (!last) this.pagenum = +event.target.innerText; + // use p instead of page to avoid rails tyring to make an actual request + window.history.pushState({}, null, `?p=${this.pagenum}`); + clearInterval(this.intervalId); + this.store.fetchDataLoop.call(this, Vue, this.pagenum); + }, + pipelineurl(id) { + return `pipelines/${id}`; + }, + }, + template: ` +
      +
      + + + + + + + + + + + + + + +
      +
      + + +
      + `, + }); +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 deleted file mode 100644 index a1d472cc464..00000000000 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.vue.js.es6 +++ /dev/null @@ -1,89 +0,0 @@ -/* global Vue, gl */ -/* eslint-disable no-param-reassign, no-bitwise*/ - -((gl) => { - gl.VuePipeLines = Vue.extend({ - components: { - 'vue-running-pipeline': gl.VueRunningPipeline, - 'vue-stages': gl.VueStages, - 'vue-pipeline-actions': gl.VuePipelineActions, - 'vue-branch-commit': gl.VueBranchCommit, - 'vue-pipeline-url': gl.VuePipelineUrl, - 'vue-pipeline-head': gl.VuePipelineHead, - 'vue-gl-pagination': gl.VueGlPagination, - }, - data() { - return { - pipelines: [], - currentPage: '', - intervalId: '', - pagenum: 1, - }; - }, - props: [ - 'scope', - 'store', - 'count', - ], - created() { - const url = window.location.toString(); - if (~url.indexOf('?')) this.pagenum = url.split('?')[1].split('=')[1]; - this.store.fetchDataLoop.call(this, Vue, this.pagenum); - }, - methods: { - shortsha(pipeline) { - return pipeline.sha.slice(0, 8); - }, - changepage(event, last) { - if (last) this.pagenum = +last; - if (!last) this.pagenum = +event.target.innerText; - // use p instead of page to avoid rails tyring to make an actual request - window.history.pushState({}, null, `?p=${this.pagenum}`); - clearInterval(this.intervalId); - this.store.fetchDataLoop.call(this, Vue, this.pagenum); - }, - pipelineurl(id) { - return `pipelines/${id}`; - }, - }, - template: ` -
      -
      - - - - - - - - - - - - - - -
      -
      - - -
      - `, - }); -})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/running.js.es6 b/app/assets/javascripts/vue_pipelines_index/running.js.es6 new file mode 100644 index 00000000000..e363cb3c14e --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_index/running.js.es6 @@ -0,0 +1,31 @@ +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VueRunningPipeline = Vue.extend({ + components: { + 'vue-running-icon': gl.VueRunningIcon, + }, + props: [ + 'pipeline', + 'pipelineurl', + ], + template: ` + + + + + + +  running + + + + `, + }); +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/running.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/running.vue.js.es6 deleted file mode 100644 index e363cb3c14e..00000000000 --- a/app/assets/javascripts/vue_pipelines_index/running.vue.js.es6 +++ /dev/null @@ -1,31 +0,0 @@ -/* global Vue, gl */ -/* eslint-disable no-param-reassign */ - -((gl) => { - gl.VueRunningPipeline = Vue.extend({ - components: { - 'vue-running-icon': gl.VueRunningIcon, - }, - props: [ - 'pipeline', - 'pipelineurl', - ], - template: ` - - - - - - -  running - - - - `, - }); -})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/running_icon.js.es6 b/app/assets/javascripts/vue_pipelines_index/running_icon.js.es6 new file mode 100644 index 00000000000..c37f213525c --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_index/running_icon.js.es6 @@ -0,0 +1,13 @@ +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VueRunningIcon = Vue.extend({ + template: ` + + + + + `, + }); +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/running_icon.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/running_icon.vue.js.es6 deleted file mode 100644 index c37f213525c..00000000000 --- a/app/assets/javascripts/vue_pipelines_index/running_icon.vue.js.es6 +++ /dev/null @@ -1,13 +0,0 @@ -/* global Vue, gl */ -/* eslint-disable no-param-reassign */ - -((gl) => { - gl.VueRunningIcon = Vue.extend({ - template: ` - - - - - `, - }); -})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/stages.js.es6 b/app/assets/javascripts/vue_pipelines_index/stages.js.es6 new file mode 100644 index 00000000000..da8c9280486 --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_index/stages.js.es6 @@ -0,0 +1,110 @@ +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VueStages = Vue.extend({ + template: ` + + + + + + + + + + + + `, + }); +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/stages.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/stages.vue.js.es6 deleted file mode 100644 index da8c9280486..00000000000 --- a/app/assets/javascripts/vue_pipelines_index/stages.vue.js.es6 +++ /dev/null @@ -1,110 +0,0 @@ -/* global Vue, gl */ -/* eslint-disable no-param-reassign */ - -((gl) => { - gl.VueStages = Vue.extend({ - template: ` - - - - - - - - - - - - `, - }); -})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/vue_gl_pagination.vue.js.es6 b/app/assets/javascripts/vue_pipelines_index/vue_gl_pagination.vue.js.es6 deleted file mode 100644 index 84d908f8e52..00000000000 --- a/app/assets/javascripts/vue_pipelines_index/vue_gl_pagination.vue.js.es6 +++ /dev/null @@ -1,64 +0,0 @@ -/* global Vue, gl */ -/* eslint-disable no-param-reassign */ - -((gl) => { - gl.VueGlPagination = Vue.extend({ - props: [ - 'changepage', - 'pages', - 'count', - 'pagenum', - ], - methods: { - pagenumberstatus(n) { - if (n - 1 === +this.pagenum) return 'active'; - return ''; - }, - }, - computed: { - last() { - return Math.ceil(+this.count / 5); - }, - lastpage() { - return `pipelines?p=${this.last}`; - }, - upcount() { - return +this.last + 1; - }, - prev() { - if (this.pagenum === 1) return 1; - return this.pagenum - 1; - }, - next() { - if (this.pagenum === this.last) return `pipelines?p=${this.pagenum}`; - return `pipelines?p=${this.pagenum + 1}`; - }, - }, - template: ` -
      - -
      - `, - }); -})(window.gl || (window.gl = {})); -- cgit v1.2.1 From 35066c8558398e5d2dc096801b93e5c693e080fd Mon Sep 17 00:00:00 2001 From: Regis Date: Sat, 5 Nov 2016 16:36:33 -0600 Subject: making reusable status and status icons components --- app/assets/javascripts/svg_icons/index.js.es6 | 38 +++++++++++++++++ app/assets/javascripts/vue_icons/index.js.es6 | 49 ++++++++++++++++++++++ .../javascripts/vue_pipelines_index/index.js.es6 | 22 +++++----- .../vue_pipelines_index/pipelines.js.es6 | 13 +++--- .../javascripts/vue_pipelines_index/running.js.es6 | 31 -------------- .../vue_pipelines_index/running_icon.js.es6 | 13 ------ .../javascripts/vue_pipelines_index/store.js.es6 | 9 ++++ .../javascripts/vue_pipelines_status/failed.js.es6 | 24 +++++++++++ .../javascripts/vue_pipelines_status/index.js.es6 | 4 ++ .../vue_pipelines_status/pending.js.es6 | 24 +++++++++++ .../vue_pipelines_status/running.js.es6 | 24 +++++++++++ .../javascripts/vue_pipelines_status/status.js.es6 | 38 +++++++++++++++++ app/views/projects/pipelines/index.html.haml | 2 + 13 files changed, 229 insertions(+), 62 deletions(-) create mode 100644 app/assets/javascripts/svg_icons/index.js.es6 create mode 100644 app/assets/javascripts/vue_icons/index.js.es6 delete mode 100644 app/assets/javascripts/vue_pipelines_index/running.js.es6 delete mode 100644 app/assets/javascripts/vue_pipelines_index/running_icon.js.es6 create mode 100644 app/assets/javascripts/vue_pipelines_status/failed.js.es6 create mode 100644 app/assets/javascripts/vue_pipelines_status/index.js.es6 create mode 100644 app/assets/javascripts/vue_pipelines_status/pending.js.es6 create mode 100644 app/assets/javascripts/vue_pipelines_status/running.js.es6 create mode 100644 app/assets/javascripts/vue_pipelines_status/status.js.es6 (limited to 'app') diff --git a/app/assets/javascripts/svg_icons/index.js.es6 b/app/assets/javascripts/svg_icons/index.js.es6 new file mode 100644 index 00000000000..b84c5f85a01 --- /dev/null +++ b/app/assets/javascripts/svg_icons/index.js.es6 @@ -0,0 +1,38 @@ +//= require vue +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VueRunningIcon = Vue.extend({ + template: ` + + + + + + + `, + }); + + gl.VuePendingIcon = Vue.extend({ + template: ` + + + + + + + `, + }); + + gl.VueSuccessIcon = Vue.extend({ + template: ` + + + + + + + `, + }); +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_icons/index.js.es6 b/app/assets/javascripts/vue_icons/index.js.es6 new file mode 100644 index 00000000000..413f9b45393 --- /dev/null +++ b/app/assets/javascripts/vue_icons/index.js.es6 @@ -0,0 +1,49 @@ +//= require vue +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VueRunningIcon = Vue.extend({ + template: ` + + + + + + + `, + }); + + gl.VuePendingIcon = Vue.extend({ + template: ` + + + + + + + `, + }); + + gl.VueSuccessIcon = Vue.extend({ + template: ` + + + + + + + `, + }); + + gl.VueFailedIcon = Vue.extend({ + template: ` + + + + + + + `, + }); +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/index.js.es6 b/app/assets/javascripts/vue_pipelines_index/index.js.es6 index ecdb3e397c2..0ba043ef612 100644 --- a/app/assets/javascripts/vue_pipelines_index/index.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/index.js.es6 @@ -1,21 +1,21 @@ /* global Vue, VueResource, gl */ +/* eslint-disable no-bitwise*/ -//= require vue //= require vue-resource //= require ./store.js.es6 -//= require ./pipeline_url.vue.js.es6 -//= require ./vue_gl_pagination.vue.js.es6 -//= require ./pipeline_head.vue.js.es6 -//= require ./running_icon.vue.js.es6 -//= require ./running.vue.js.es6 -//= require ./stages.vue.js.es6 -//= require ./pipeline_actions.vue.js.es6 -//= require ./branch_commit.vue.js.es6 -//= require ./pipelines.vue.js.es6 +//= require ./pipeline_url.js.es6 +//= require ./gl_pagination.js.es6 +//= require ./pipeline_head.js.es6 +//= require ./stages.js.es6 +//= require ./pipeline_actions.js.es6 +//= require ./branch_commit.js.es6 +//= require ./pipelines.js.es6 (() => { - if (~window.location.href.indexOf('scope')) return null; + const url = window.location.href; + if (~url.indexOf('scope')) return null; + const project = document.querySelector('.pipelines'); Vue.use(VueResource); diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index a1d472cc464..6cc516d025f 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -11,6 +11,7 @@ 'vue-pipeline-url': gl.VuePipelineUrl, 'vue-pipeline-head': gl.VuePipelineHead, 'vue-gl-pagination': gl.VueGlPagination, + 'vue-status-pipeline': gl.VueStatusPipeline, }, data() { return { @@ -53,13 +54,11 @@ - - - - + + { - gl.VueRunningPipeline = Vue.extend({ - components: { - 'vue-running-icon': gl.VueRunningIcon, - }, - props: [ - 'pipeline', - 'pipelineurl', - ], - template: ` - - - - - - -  running - - - - `, - }); -})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/running_icon.js.es6 b/app/assets/javascripts/vue_pipelines_index/running_icon.js.es6 deleted file mode 100644 index c37f213525c..00000000000 --- a/app/assets/javascripts/vue_pipelines_index/running_icon.js.es6 +++ /dev/null @@ -1,13 +0,0 @@ -/* global Vue, gl */ -/* eslint-disable no-param-reassign */ - -((gl) => { - gl.VueRunningIcon = Vue.extend({ - template: ` - - - - - `, - }); -})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index 89982b11b31..b4bdc27ede3 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -23,5 +23,14 @@ goFetch(); }, 60000); } + + fetchSvg(type, icon) { + this.$http.get(`/shared/icons/${icon}`) + .then((response) => { + this[type] = JSON.parse(response.body); + }, () => new Flash( + 'Something went wrong on our end.' + )); + } }; })(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_status/failed.js.es6 b/app/assets/javascripts/vue_pipelines_status/failed.js.es6 new file mode 100644 index 00000000000..33050186fe5 --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_status/failed.js.es6 @@ -0,0 +1,24 @@ +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VueFailedPipeline = Vue.extend({ + components: { + 'vue-failed-icon': gl.VuePendingIcon, + }, + props: [ + 'pipeline', + 'pipelineurl', + ], + template: ` + + + + +  failed + + + + `, + }); +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_status/index.js.es6 b/app/assets/javascripts/vue_pipelines_status/index.js.es6 new file mode 100644 index 00000000000..cea02b5d6af --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_status/index.js.es6 @@ -0,0 +1,4 @@ +//= require ./pending.js.es6 +//= require ./failed.js.es6 +//= require ./running.js.es6 +//= require ./status.js.es6 diff --git a/app/assets/javascripts/vue_pipelines_status/pending.js.es6 b/app/assets/javascripts/vue_pipelines_status/pending.js.es6 new file mode 100644 index 00000000000..4c4a5ade09d --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_status/pending.js.es6 @@ -0,0 +1,24 @@ +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VuePendingPipeline = Vue.extend({ + components: { + 'vue-pending-icon': gl.VuePendingIcon, + }, + props: [ + 'pipeline', + 'pipelineurl', + ], + template: ` + + + + +  pending + + + + `, + }); +})(window.gl || (window.gl = {})); \ No newline at end of file diff --git a/app/assets/javascripts/vue_pipelines_status/running.js.es6 b/app/assets/javascripts/vue_pipelines_status/running.js.es6 new file mode 100644 index 00000000000..af8480f4795 --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_status/running.js.es6 @@ -0,0 +1,24 @@ +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VueRunningPipeline = Vue.extend({ + components: { + 'vue-running-icon': gl.VueRunningIcon, + }, + props: [ + 'pipeline', + 'pipelineurl', + ], + template: ` + + + + +  running + + + + `, + }); +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_status/status.js.es6 b/app/assets/javascripts/vue_pipelines_status/status.js.es6 new file mode 100644 index 00000000000..043468ea538 --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_status/status.js.es6 @@ -0,0 +1,38 @@ +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VueStatusPipeline = Vue.extend({ + components: { + 'vue-running-pipeline': gl.VueRunningPipeline, + 'vue-pending-pipeline': gl.VuePendingPipeline, + 'vue-failed-pipeline': gl.VueFailedPipeline, + }, + props: [ + 'pipeline', + 'pipelineurl', + ], + template: ` + + + + + + + + + `, + }); +})(window.gl || (window.gl = {})); diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index 0e3cec4aa07..a09f23b2fde 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -57,4 +57,6 @@ - else .vue-pipelines-index += page_specific_javascript_tag('vue_icons/index.js') += page_specific_javascript_tag('vue_pipelines_status/index.js') = page_specific_javascript_tag('vue_pipelines_index/index.js') -- cgit v1.2.1 From 905f7391e76deb92f787f3701224214bd2b4663b Mon Sep 17 00:00:00 2001 From: Regis Date: Sat, 5 Nov 2016 16:43:21 -0600 Subject: status icon and status components dynamic by scope --- .../vue_pipelines_index/pipelines.js.es6 | 10 +++--- .../javascripts/vue_pipelines_status/failed.js.es6 | 8 ++--- .../vue_pipelines_status/pending.js.es6 | 8 ++--- .../vue_pipelines_status/running.js.es6 | 8 ++--- .../javascripts/vue_pipelines_status/status.js.es6 | 42 +++++++++++----------- 5 files changed, 38 insertions(+), 38 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index 6cc516d025f..30f8806fdf2 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -11,7 +11,7 @@ 'vue-pipeline-url': gl.VuePipelineUrl, 'vue-pipeline-head': gl.VuePipelineHead, 'vue-gl-pagination': gl.VueGlPagination, - 'vue-status-pipeline': gl.VueStatusPipeline, + 'vue-status-scope': gl.VueStatusScope, }, data() { return { @@ -54,11 +54,11 @@ - - + { - gl.VueFailedPipeline = Vue.extend({ + gl.VueFailedScope = Vue.extend({ components: { 'vue-failed-icon': gl.VuePendingIcon, }, props: [ - 'pipeline', - 'pipelineurl', + 'scope', + 'scopeurl', ], template: ` - +  failed diff --git a/app/assets/javascripts/vue_pipelines_status/pending.js.es6 b/app/assets/javascripts/vue_pipelines_status/pending.js.es6 index 4c4a5ade09d..1742e52a2bb 100644 --- a/app/assets/javascripts/vue_pipelines_status/pending.js.es6 +++ b/app/assets/javascripts/vue_pipelines_status/pending.js.es6 @@ -2,17 +2,17 @@ /* eslint-disable no-param-reassign */ ((gl) => { - gl.VuePendingPipeline = Vue.extend({ + gl.VuePendingScope = Vue.extend({ components: { 'vue-pending-icon': gl.VuePendingIcon, }, props: [ - 'pipeline', - 'pipelineurl', + 'scope', + 'scopeurl', ], template: ` - +  pending diff --git a/app/assets/javascripts/vue_pipelines_status/running.js.es6 b/app/assets/javascripts/vue_pipelines_status/running.js.es6 index af8480f4795..bc2b2b0b1e9 100644 --- a/app/assets/javascripts/vue_pipelines_status/running.js.es6 +++ b/app/assets/javascripts/vue_pipelines_status/running.js.es6 @@ -2,17 +2,17 @@ /* eslint-disable no-param-reassign */ ((gl) => { - gl.VueRunningPipeline = Vue.extend({ + gl.VueRunningScope = Vue.extend({ components: { 'vue-running-icon': gl.VueRunningIcon, }, props: [ - 'pipeline', - 'pipelineurl', + 'scope', + 'scopeurl', ], template: ` - +  running diff --git a/app/assets/javascripts/vue_pipelines_status/status.js.es6 b/app/assets/javascripts/vue_pipelines_status/status.js.es6 index 043468ea538..6695b600488 100644 --- a/app/assets/javascripts/vue_pipelines_status/status.js.es6 +++ b/app/assets/javascripts/vue_pipelines_status/status.js.es6 @@ -2,36 +2,36 @@ /* eslint-disable no-param-reassign */ ((gl) => { - gl.VueStatusPipeline = Vue.extend({ + gl.VueStatusScope = Vue.extend({ components: { - 'vue-running-pipeline': gl.VueRunningPipeline, - 'vue-pending-pipeline': gl.VuePendingPipeline, - 'vue-failed-pipeline': gl.VueFailedPipeline, + 'vue-running-scope': gl.VueRunningScope, + 'vue-pending-scope': gl.VuePendingScope, + 'vue-failed-scope': gl.VueFailedScope, }, props: [ - 'pipeline', - 'pipelineurl', + 'scope', + 'scopeurl', ], template: ` - - - + - - + - + `, }); -- cgit v1.2.1 From f140da6b55013c1170285be84cf1f53b23bfe67e Mon Sep 17 00:00:00 2001 From: Regis Date: Sat, 5 Nov 2016 16:50:18 -0600 Subject: remove files/folders --- app/assets/javascripts/svg_icons/index.js.es6 | 38 --------------------------- 1 file changed, 38 deletions(-) delete mode 100644 app/assets/javascripts/svg_icons/index.js.es6 (limited to 'app') diff --git a/app/assets/javascripts/svg_icons/index.js.es6 b/app/assets/javascripts/svg_icons/index.js.es6 deleted file mode 100644 index b84c5f85a01..00000000000 --- a/app/assets/javascripts/svg_icons/index.js.es6 +++ /dev/null @@ -1,38 +0,0 @@ -//= require vue -/* global Vue, gl */ -/* eslint-disable no-param-reassign */ - -((gl) => { - gl.VueRunningIcon = Vue.extend({ - template: ` - - - - - - - `, - }); - - gl.VuePendingIcon = Vue.extend({ - template: ` - - - - - - - `, - }); - - gl.VueSuccessIcon = Vue.extend({ - template: ` - - - - - - - `, - }); -})(window.gl || (window.gl = {})); -- cgit v1.2.1 From 0c9a4c14209c16d14d856fdb3b5e88c917232c6c Mon Sep 17 00:00:00 2001 From: Regis Date: Sun, 6 Nov 2016 11:17:18 -0700 Subject: icon and status comps - pagination logic almost done --- .../javascripts/vue_pipeline_status/failed.js.es6 | 24 ++++++++++++++ .../javascripts/vue_pipeline_status/pending.js.es6 | 24 ++++++++++++++ .../javascripts/vue_pipeline_status/running.js.es6 | 24 ++++++++++++++ .../javascripts/vue_pipeline_status/status.js.es6 | 38 ++++++++++++++++++++++ .../vue_pipelines_index/gl_pagination.js.es6 | 24 +++++++------- .../vue_pipelines_index/pipelines.js.es6 | 10 +++--- 6 files changed, 129 insertions(+), 15 deletions(-) create mode 100644 app/assets/javascripts/vue_pipeline_status/failed.js.es6 create mode 100644 app/assets/javascripts/vue_pipeline_status/pending.js.es6 create mode 100644 app/assets/javascripts/vue_pipeline_status/running.js.es6 create mode 100644 app/assets/javascripts/vue_pipeline_status/status.js.es6 (limited to 'app') diff --git a/app/assets/javascripts/vue_pipeline_status/failed.js.es6 b/app/assets/javascripts/vue_pipeline_status/failed.js.es6 new file mode 100644 index 00000000000..33050186fe5 --- /dev/null +++ b/app/assets/javascripts/vue_pipeline_status/failed.js.es6 @@ -0,0 +1,24 @@ +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VueFailedPipeline = Vue.extend({ + components: { + 'vue-failed-icon': gl.VuePendingIcon, + }, + props: [ + 'pipeline', + 'pipelineurl', + ], + template: ` + + + + +  failed + + + + `, + }); +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipeline_status/pending.js.es6 b/app/assets/javascripts/vue_pipeline_status/pending.js.es6 new file mode 100644 index 00000000000..bd2a1d0a496 --- /dev/null +++ b/app/assets/javascripts/vue_pipeline_status/pending.js.es6 @@ -0,0 +1,24 @@ +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VuePendingPipeline = Vue.extend({ + components: { + 'vue-pending-icon': gl.VuePendingIcon, + }, + props: [ + 'pipeline', + 'pipelineurl', + ], + template: ` + + + + +  pending + + + + `, + }); +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipeline_status/running.js.es6 b/app/assets/javascripts/vue_pipeline_status/running.js.es6 new file mode 100644 index 00000000000..af8480f4795 --- /dev/null +++ b/app/assets/javascripts/vue_pipeline_status/running.js.es6 @@ -0,0 +1,24 @@ +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VueRunningPipeline = Vue.extend({ + components: { + 'vue-running-icon': gl.VueRunningIcon, + }, + props: [ + 'pipeline', + 'pipelineurl', + ], + template: ` + + + + +  running + + + + `, + }); +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipeline_status/status.js.es6 b/app/assets/javascripts/vue_pipeline_status/status.js.es6 new file mode 100644 index 00000000000..043468ea538 --- /dev/null +++ b/app/assets/javascripts/vue_pipeline_status/status.js.es6 @@ -0,0 +1,38 @@ +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VueStatusPipeline = Vue.extend({ + components: { + 'vue-running-pipeline': gl.VueRunningPipeline, + 'vue-pending-pipeline': gl.VuePendingPipeline, + 'vue-failed-pipeline': gl.VueFailedPipeline, + }, + props: [ + 'pipeline', + 'pipelineurl', + ], + template: ` + + + + + + + + + `, + }); +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/gl_pagination.js.es6 b/app/assets/javascripts/vue_pipelines_index/gl_pagination.js.es6 index 84d908f8e52..d4b31649f9b 100644 --- a/app/assets/javascripts/vue_pipelines_index/gl_pagination.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/gl_pagination.js.es6 @@ -14,6 +14,10 @@ if (n - 1 === +this.pagenum) return 'active'; return ''; }, + prevstatus() { + if (+this.pagenum > 1) return ''; + return 'prev disabled'; + }, }, computed: { last() { @@ -29,33 +33,31 @@ if (this.pagenum === 1) return 1; return this.pagenum - 1; }, - next() { - if (this.pagenum === this.last) return `pipelines?p=${this.pagenum}`; - return `pipelines?p=${this.pagenum + 1}`; - }, }, template: `
      diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index 30f8806fdf2..b5c451ab221 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -35,10 +35,12 @@ shortsha(pipeline) { return pipeline.sha.slice(0, 8); }, - changepage(event, last) { - if (last) this.pagenum = +last; - if (!last) this.pagenum = +event.target.innerText; - // use p instead of page to avoid rails tyring to make an actual request + changepage(event, page = {}) { + if (page) this.pagenum = +event.target.innerText; + if (page.last) this.pagenum = +page.last; + if (page.where) this.pagenum = +page.next; + + // use p instead of page to avoid making an actual request window.history.pushState({}, null, `?p=${this.pagenum}`); clearInterval(this.intervalId); this.store.fetchDataLoop.call(this, Vue, this.pagenum); -- cgit v1.2.1 From 91a22eb6c537bea870bd14db81b36e6b19044b62 Mon Sep 17 00:00:00 2001 From: Regis Date: Sun, 6 Nov 2016 11:23:21 -0700 Subject: remove extra folder --- .../javascripts/vue_pipeline_status/failed.js.es6 | 24 -------------- .../javascripts/vue_pipeline_status/pending.js.es6 | 24 -------------- .../javascripts/vue_pipeline_status/running.js.es6 | 24 -------------- .../javascripts/vue_pipeline_status/status.js.es6 | 38 ---------------------- 4 files changed, 110 deletions(-) delete mode 100644 app/assets/javascripts/vue_pipeline_status/failed.js.es6 delete mode 100644 app/assets/javascripts/vue_pipeline_status/pending.js.es6 delete mode 100644 app/assets/javascripts/vue_pipeline_status/running.js.es6 delete mode 100644 app/assets/javascripts/vue_pipeline_status/status.js.es6 (limited to 'app') diff --git a/app/assets/javascripts/vue_pipeline_status/failed.js.es6 b/app/assets/javascripts/vue_pipeline_status/failed.js.es6 deleted file mode 100644 index 33050186fe5..00000000000 --- a/app/assets/javascripts/vue_pipeline_status/failed.js.es6 +++ /dev/null @@ -1,24 +0,0 @@ -/* global Vue, gl */ -/* eslint-disable no-param-reassign */ - -((gl) => { - gl.VueFailedPipeline = Vue.extend({ - components: { - 'vue-failed-icon': gl.VuePendingIcon, - }, - props: [ - 'pipeline', - 'pipelineurl', - ], - template: ` - - - - -  failed - - - - `, - }); -})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipeline_status/pending.js.es6 b/app/assets/javascripts/vue_pipeline_status/pending.js.es6 deleted file mode 100644 index bd2a1d0a496..00000000000 --- a/app/assets/javascripts/vue_pipeline_status/pending.js.es6 +++ /dev/null @@ -1,24 +0,0 @@ -/* global Vue, gl */ -/* eslint-disable no-param-reassign */ - -((gl) => { - gl.VuePendingPipeline = Vue.extend({ - components: { - 'vue-pending-icon': gl.VuePendingIcon, - }, - props: [ - 'pipeline', - 'pipelineurl', - ], - template: ` - - - - -  pending - - - - `, - }); -})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipeline_status/running.js.es6 b/app/assets/javascripts/vue_pipeline_status/running.js.es6 deleted file mode 100644 index af8480f4795..00000000000 --- a/app/assets/javascripts/vue_pipeline_status/running.js.es6 +++ /dev/null @@ -1,24 +0,0 @@ -/* global Vue, gl */ -/* eslint-disable no-param-reassign */ - -((gl) => { - gl.VueRunningPipeline = Vue.extend({ - components: { - 'vue-running-icon': gl.VueRunningIcon, - }, - props: [ - 'pipeline', - 'pipelineurl', - ], - template: ` - - - - -  running - - - - `, - }); -})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipeline_status/status.js.es6 b/app/assets/javascripts/vue_pipeline_status/status.js.es6 deleted file mode 100644 index 043468ea538..00000000000 --- a/app/assets/javascripts/vue_pipeline_status/status.js.es6 +++ /dev/null @@ -1,38 +0,0 @@ -/* global Vue, gl */ -/* eslint-disable no-param-reassign */ - -((gl) => { - gl.VueStatusPipeline = Vue.extend({ - components: { - 'vue-running-pipeline': gl.VueRunningPipeline, - 'vue-pending-pipeline': gl.VuePendingPipeline, - 'vue-failed-pipeline': gl.VueFailedPipeline, - }, - props: [ - 'pipeline', - 'pipelineurl', - ], - template: ` - - - - - - - - - `, - }); -})(window.gl || (window.gl = {})); -- cgit v1.2.1 From fd10ff30bbd4b24889fc0c79fbe35af95f9b5666 Mon Sep 17 00:00:00 2001 From: Regis Date: Sun, 6 Nov 2016 11:27:27 -0700 Subject: extract pagination into own folder and precompile in application.rb --- app/assets/javascripts/vue_pagination/index.js.es6 | 66 ++++++++++++++++++++++ .../vue_pipelines_index/gl_pagination.js.es6 | 66 ---------------------- .../javascripts/vue_pipelines_index/index.js.es6 | 1 - app/views/projects/pipelines/index.html.haml | 3 + 4 files changed, 69 insertions(+), 67 deletions(-) create mode 100644 app/assets/javascripts/vue_pagination/index.js.es6 delete mode 100644 app/assets/javascripts/vue_pipelines_index/gl_pagination.js.es6 (limited to 'app') diff --git a/app/assets/javascripts/vue_pagination/index.js.es6 b/app/assets/javascripts/vue_pagination/index.js.es6 new file mode 100644 index 00000000000..d4b31649f9b --- /dev/null +++ b/app/assets/javascripts/vue_pagination/index.js.es6 @@ -0,0 +1,66 @@ +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VueGlPagination = Vue.extend({ + props: [ + 'changepage', + 'pages', + 'count', + 'pagenum', + ], + methods: { + pagenumberstatus(n) { + if (n - 1 === +this.pagenum) return 'active'; + return ''; + }, + prevstatus() { + if (+this.pagenum > 1) return ''; + return 'prev disabled'; + }, + }, + computed: { + last() { + return Math.ceil(+this.count / 5); + }, + lastpage() { + return `pipelines?p=${this.last}`; + }, + upcount() { + return +this.last + 1; + }, + prev() { + if (this.pagenum === 1) return 1; + return this.pagenum - 1; + }, + }, + template: ` +
      +
        +
      • + Prev +
      • +
      • + {{(n - 1)}} +
      • + +
      • + +
      • + +
      • + Last » +
      • +
      +
      + `, + }); +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/gl_pagination.js.es6 b/app/assets/javascripts/vue_pipelines_index/gl_pagination.js.es6 deleted file mode 100644 index d4b31649f9b..00000000000 --- a/app/assets/javascripts/vue_pipelines_index/gl_pagination.js.es6 +++ /dev/null @@ -1,66 +0,0 @@ -/* global Vue, gl */ -/* eslint-disable no-param-reassign */ - -((gl) => { - gl.VueGlPagination = Vue.extend({ - props: [ - 'changepage', - 'pages', - 'count', - 'pagenum', - ], - methods: { - pagenumberstatus(n) { - if (n - 1 === +this.pagenum) return 'active'; - return ''; - }, - prevstatus() { - if (+this.pagenum > 1) return ''; - return 'prev disabled'; - }, - }, - computed: { - last() { - return Math.ceil(+this.count / 5); - }, - lastpage() { - return `pipelines?p=${this.last}`; - }, - upcount() { - return +this.last + 1; - }, - prev() { - if (this.pagenum === 1) return 1; - return this.pagenum - 1; - }, - }, - template: ` -
      -
        -
      • - Prev -
      • -
      • - {{(n - 1)}} -
      • - -
      • - -
      • - -
      • - Last » -
      • -
      -
      - `, - }); -})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/index.js.es6 b/app/assets/javascripts/vue_pipelines_index/index.js.es6 index 0ba043ef612..f7657879ac4 100644 --- a/app/assets/javascripts/vue_pipelines_index/index.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/index.js.es6 @@ -5,7 +5,6 @@ //= require ./store.js.es6 //= require ./pipeline_url.js.es6 -//= require ./gl_pagination.js.es6 //= require ./pipeline_head.js.es6 //= require ./stages.js.es6 //= require ./pipeline_actions.js.es6 diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index a09f23b2fde..6f70b239826 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -58,5 +58,8 @@ .vue-pipelines-index = page_specific_javascript_tag('vue_icons/index.js') +-# ^^ this component loads Vue so the rest don't +-# this will no longer be an issue once Vue2 is global += page_specific_javascript_tag('vue_pagination/index.js') = page_specific_javascript_tag('vue_pipelines_status/index.js') = page_specific_javascript_tag('vue_pipelines_index/index.js') -- cgit v1.2.1 From be146a4f0cfa26995748e6c086139cfcacfa613b Mon Sep 17 00:00:00 2001 From: Regis Date: Sun, 6 Nov 2016 13:35:29 -0700 Subject: remove svg api call - more progress on pagination --- app/assets/javascripts/vue_pagination/index.js.es6 | 45 +++++++++++++++------- .../javascripts/vue_pipelines_index/index.js.es6 | 2 +- .../vue_pipelines_index/pipelines.js.es6 | 4 +- .../javascripts/vue_pipelines_index/store.js.es6 | 9 ----- 4 files changed, 35 insertions(+), 25 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pagination/index.js.es6 b/app/assets/javascripts/vue_pagination/index.js.es6 index d4b31649f9b..2665b2bd2c5 100644 --- a/app/assets/javascripts/vue_pagination/index.js.es6 +++ b/app/assets/javascripts/vue_pagination/index.js.es6 @@ -3,14 +3,19 @@ ((gl) => { gl.VueGlPagination = Vue.extend({ + data() { + return { + nslice: +this.pagenum, + }; + }, props: [ 'changepage', - 'pages', 'count', 'pagenum', ], methods: { pagenumberstatus(n) { + console.log(n, this.nslice); if (n - 1 === +this.pagenum) return 'active'; return ''; }, @@ -20,35 +25,46 @@ }, }, computed: { + paginationsection() { + if (this.last < 6 && this.pagenum < 6) { + const pageArray = [...Array(6).keys()]; + pageArray.shift(); + return pageArray.slice(0, this.upcount); + } + const section = [...Array(this.upcount).keys()]; + section.shift(); + this.nslice = +this.pagenum; + return section.slice(+this.pagenum, +this.pagenum + 5); + }, last() { return Math.ceil(+this.count / 5); }, - lastpage() { - return `pipelines?p=${this.last}`; - }, upcount() { return +this.last + 1; }, - prev() { - if (this.pagenum === 1) return 1; - return this.pagenum - 1; + endspread() { + if (+this.pagenum < this.last && +this.pagenum > 5) return true; + return false + }, + begspread() { + if (+this.pagenum > 5 && +this.pagenum < this.last) return true; + return false }, }, template: `
      -
        -
      • +
          +
        • Prev
        • -
        • +
        • {{(n - 1)}}
        • -
        • +
        • +
        • + +
        • - Last » + Last »
      diff --git a/app/assets/javascripts/vue_pipelines_index/index.js.es6 b/app/assets/javascripts/vue_pipelines_index/index.js.es6 index f7657879ac4..1aea0820208 100644 --- a/app/assets/javascripts/vue_pipelines_index/index.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/index.js.es6 @@ -34,7 +34,7 @@
diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index b5c451ab221..3ab336f0e6d 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -37,8 +37,8 @@ }, changepage(event, page = {}) { if (page) this.pagenum = +event.target.innerText; - if (page.last) this.pagenum = +page.last; - if (page.where) this.pagenum = +page.next; + if (page.where) this.pagenum = +page.where; + if (page.where) this.pagenum = +page.where; // use p instead of page to avoid making an actual request window.history.pushState({}, null, `?p=${this.pagenum}`); diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index b4bdc27ede3..89982b11b31 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -23,14 +23,5 @@ goFetch(); }, 60000); } - - fetchSvg(type, icon) { - this.$http.get(`/shared/icons/${icon}`) - .then((response) => { - this[type] = JSON.parse(response.body); - }, () => new Flash( - 'Something went wrong on our end.' - )); - } }; })(window.gl || (window.gl = {})); -- cgit v1.2.1 From 286b96f02501db38535f8a1e5f9b8a15bfafe5a6 Mon Sep 17 00:00:00 2001 From: Regis Date: Sun, 6 Nov 2016 13:56:08 -0700 Subject: a lot more progress on pagination :) --- app/assets/javascripts/vue_pagination/index.js.es6 | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pagination/index.js.es6 b/app/assets/javascripts/vue_pagination/index.js.es6 index 2665b2bd2c5..a6a8dd93480 100644 --- a/app/assets/javascripts/vue_pagination/index.js.es6 +++ b/app/assets/javascripts/vue_pagination/index.js.es6 @@ -34,6 +34,7 @@ const section = [...Array(this.upcount).keys()]; section.shift(); this.nslice = +this.pagenum; + this.endcount = +this.pagenum + 5; return section.slice(+this.pagenum, +this.pagenum + 5); }, last() { @@ -44,17 +45,17 @@ }, endspread() { if (+this.pagenum < this.last && +this.pagenum > 5) return true; - return false + return false; }, begspread() { if (+this.pagenum > 5 && +this.pagenum < this.last) return true; - return false + return false; }, }, template: `
    -
  • +
  • Prev
  • @@ -67,15 +68,15 @@
  • -
  • -
  • +
  • Last »
-- cgit v1.2.1 From fa2f052ba78d4cdbc8d1800da25f5cc8041f655e Mon Sep 17 00:00:00 2001 From: Regis Date: Sun, 6 Nov 2016 14:00:36 -0700 Subject: formatting --- app/assets/javascripts/vue_pagination/index.js.es6 | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pagination/index.js.es6 b/app/assets/javascripts/vue_pagination/index.js.es6 index a6a8dd93480..73232b45b81 100644 --- a/app/assets/javascripts/vue_pagination/index.js.es6 +++ b/app/assets/javascripts/vue_pagination/index.js.es6 @@ -15,7 +15,6 @@ ], methods: { pagenumberstatus(n) { - console.log(n, this.nslice); if (n - 1 === +this.pagenum) return 'active'; return ''; }, @@ -68,7 +67,10 @@
  • -
  • -
  • +
  • Last »
  • -- cgit v1.2.1 From 26c69c5df8bf7800e16a2d12d207f2ae8779fb9e Mon Sep 17 00:00:00 2001 From: winniehell Date: Sat, 5 Nov 2016 12:28:48 +0100 Subject: Display error code for U2F errors (!7305) --- app/assets/javascripts/u2f/authenticate.js | 3 ++- app/assets/javascripts/u2f/error.js | 1 - app/assets/javascripts/u2f/register.js | 3 ++- app/views/u2f/_authenticate.html.haml | 2 +- app/views/u2f/_register.html.haml | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/u2f/authenticate.js b/app/assets/javascripts/u2f/authenticate.js index 35f2b1e2b25..6f0dbca96ca 100644 --- a/app/assets/javascripts/u2f/authenticate.js +++ b/app/assets/javascripts/u2f/authenticate.js @@ -85,7 +85,8 @@ U2FAuthenticate.prototype.renderError = function(error) { this.renderTemplate('error', { - error_message: error.message() + error_message: error.message(), + error_code: error.errorCode }); return this.container.find('#js-u2f-try-again').on('click', this.renderSetup); }; diff --git a/app/assets/javascripts/u2f/error.js b/app/assets/javascripts/u2f/error.js index aff605169e4..fab4165efe5 100644 --- a/app/assets/javascripts/u2f/error.js +++ b/app/assets/javascripts/u2f/error.js @@ -7,7 +7,6 @@ this.errorCode = errorCode; this.message = bind(this.message, this); this.httpsDisabled = window.location.protocol !== 'https:'; - console.error("U2F Error Code: " + this.errorCode); } U2FError.prototype.message = function() { diff --git a/app/assets/javascripts/u2f/register.js b/app/assets/javascripts/u2f/register.js index 22fbf9f3a91..3e0a2d53bd2 100644 --- a/app/assets/javascripts/u2f/register.js +++ b/app/assets/javascripts/u2f/register.js @@ -72,7 +72,8 @@ U2FRegister.prototype.renderError = function(error) { this.renderTemplate('error', { - error_message: error.message() + error_message: error.message(), + error_code: error.errorCode }); return this.container.find('#js-u2f-try-again').on('click', this.renderSetup); }; diff --git a/app/views/u2f/_authenticate.html.haml b/app/views/u2f/_authenticate.html.haml index 232ca26c1af..fa998c91f72 100644 --- a/app/views/u2f/_authenticate.html.haml +++ b/app/views/u2f/_authenticate.html.haml @@ -13,7 +13,7 @@ %script#js-authenticate-u2f-error{ type: "text/template" } %div - %p <%= error_message %> + %p <%= error_message %> (error code: <%= error_code %>) %a.btn.btn-warning#js-u2f-try-again Try again? %script#js-authenticate-u2f-authenticated{ type: "text/template" } diff --git a/app/views/u2f/_register.html.haml b/app/views/u2f/_register.html.haml index 8f7b42eb351..fcc33f04237 100644 --- a/app/views/u2f/_register.html.haml +++ b/app/views/u2f/_register.html.haml @@ -23,7 +23,7 @@ %script#js-register-u2f-error{ type: "text/template" } %div %p - %span <%= error_message %> + %span <%= error_message %> (error code: <%= error_code %>) %a.btn.btn-warning#js-u2f-try-again Try again? %script#js-register-u2f-registered{ type: "text/template" } -- cgit v1.2.1 From 18a71c47603d703de73c46fef4889887f685bebe Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 7 Nov 2016 23:44:11 +0800 Subject: Show commit status from latest pipeline Rather than compound status from all pipelines. Closes #20560 --- app/models/ci/pipeline.rb | 6 +++++- app/models/commit.rb | 16 +++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) (limited to 'app') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index d3432632899..3ab19938c0f 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -83,9 +83,13 @@ module Ci end end + scope :latest, -> { order(id: :desc) } + # ref can't be HEAD or SHA, can only be branch/tag name + scope :latest_for, ->(ref) { where(ref: ref).latest } + def self.latest_successful_for(ref) - where(ref: ref).order(id: :desc).success.first + latest_for(ref).success.first end def self.truncate_sha(sha) diff --git a/app/models/commit.rb b/app/models/commit.rb index 9e7fde9503d..2134ba2d75f 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -232,13 +232,15 @@ class Commit def status(ref = nil) @statuses ||= {} - if @statuses.key?(ref) - @statuses[ref] - elsif ref - @statuses[ref] = pipelines.where(ref: ref).status - else - @statuses[ref] = pipelines.status - end + return @statuses[ref] if @statuses.key?(ref) + + latest_pipeline = if ref + pipelines.latest_for(ref) + else + pipelines.latest + end.first + + @statuses[ref] = latest_pipeline.try(:status) end def revert_branch_name -- cgit v1.2.1 From 590d61a2de453b2359c81f7070caae09df6e788d Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 8 Nov 2016 02:33:04 +0800 Subject: Also show latest pipeline for ImageForBuildService --- app/services/ci/image_for_build_service.rb | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/services/ci/image_for_build_service.rb b/app/services/ci/image_for_build_service.rb index 75d847d5bee..17ce95073cb 100644 --- a/app/services/ci/image_for_build_service.rb +++ b/app/services/ci/image_for_build_service.rb @@ -1,11 +1,18 @@ module Ci class ImageForBuildService def execute(project, opts) - sha = opts[:sha] || ref_sha(project, opts[:ref]) + ref = opts[:ref] + sha = opts[:sha] || ref_sha(project, ref) pipelines = project.pipelines.where(sha: sha) - pipelines = pipelines.where(ref: opts[:ref]) if opts[:ref] - image_name = image_for_status(pipelines.status) + + latest_pipeline = if ref + pipelines.latest_for(ref) + else + pipelines.latest + end.first + + image_name = image_for_status(latest_pipeline.status) image_path = Rails.root.join('public/ci', image_name) OpenStruct.new(path: image_path, name: image_name) -- cgit v1.2.1 From f593abbc70ab02823cd99d2db11598b629cbb3a0 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 8 Nov 2016 03:44:25 +0800 Subject: There's not always a pipeline --- app/services/ci/image_for_build_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/services/ci/image_for_build_service.rb b/app/services/ci/image_for_build_service.rb index 17ce95073cb..026a727a8f9 100644 --- a/app/services/ci/image_for_build_service.rb +++ b/app/services/ci/image_for_build_service.rb @@ -12,7 +12,7 @@ module Ci pipelines.latest end.first - image_name = image_for_status(latest_pipeline.status) + image_name = image_for_status(latest_pipeline.try(:status)) image_path = Rails.root.join('public/ci', image_name) OpenStruct.new(path: image_path, name: image_name) -- cgit v1.2.1 From 31af345b476f0995888dc1e75bcabc95def2aba2 Mon Sep 17 00:00:00 2001 From: Regis Date: Mon, 7 Nov 2016 14:16:57 -0700 Subject: fix prev button being misplaced --- app/assets/javascripts/vue_pagination/index.js.es6 | 31 +++++++++++----------- .../javascripts/vue_pipelines_index/index.js.es6 | 2 +- 2 files changed, 17 insertions(+), 16 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pagination/index.js.es6 b/app/assets/javascripts/vue_pagination/index.js.es6 index 73232b45b81..88a2c5567a1 100644 --- a/app/assets/javascripts/vue_pagination/index.js.es6 +++ b/app/assets/javascripts/vue_pagination/index.js.es6 @@ -3,16 +3,16 @@ ((gl) => { gl.VueGlPagination = Vue.extend({ - data() { - return { - nslice: +this.pagenum, - }; - }, props: [ 'changepage', 'count', 'pagenum', ], + data() { + return { + nslice: +this.pagenum, + }; + }, methods: { pagenumberstatus(n) { if (n - 1 === +this.pagenum) return 'active'; @@ -24,17 +24,20 @@ }, }, computed: { + dynamicpage() { + const section = [...Array(this.upcount).keys()]; + section.shift(); + this.nslice = +this.pagenum; + this.endcount = +this.pagenum + 5; + return section.slice(+this.pagenum, +this.pagenum + 5); + }, paginationsection() { if (this.last < 6 && this.pagenum < 6) { const pageArray = [...Array(6).keys()]; pageArray.shift(); return pageArray.slice(0, this.upcount); } - const section = [...Array(this.upcount).keys()]; - section.shift(); - this.nslice = +this.pagenum; - this.endcount = +this.pagenum + 5; - return section.slice(+this.pagenum, +this.pagenum + 5); + return this.dynamicpage; }, last() { return Math.ceil(+this.count / 5); @@ -54,7 +57,7 @@ template: `
      -
    • +
    • Prev
    • @@ -71,16 +74,14 @@ class="next" v-if='(n === upcount || n === endcount) && pagenum !== last' > - - Next - + Next
    • Last »
    • diff --git a/app/assets/javascripts/vue_pipelines_index/index.js.es6 b/app/assets/javascripts/vue_pipelines_index/index.js.es6 index 1aea0820208..f7657879ac4 100644 --- a/app/assets/javascripts/vue_pipelines_index/index.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/index.js.es6 @@ -34,7 +34,7 @@
    -- cgit v1.2.1 From b0e6d0788625ae4a1e522c33496c06b4cdd53020 Mon Sep 17 00:00:00 2001 From: Regis Date: Mon, 7 Nov 2016 14:43:11 -0700 Subject: end dot logic complete --- app/assets/javascripts/vue_pagination/index.js.es6 | 26 +++++++++++++--------- .../javascripts/vue_pipelines_index/index.js.es6 | 2 +- 2 files changed, 16 insertions(+), 12 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pagination/index.js.es6 b/app/assets/javascripts/vue_pagination/index.js.es6 index 88a2c5567a1..71031c4d76d 100644 --- a/app/assets/javascripts/vue_pagination/index.js.es6 +++ b/app/assets/javascripts/vue_pagination/index.js.es6 @@ -29,7 +29,12 @@ section.shift(); this.nslice = +this.pagenum; this.endcount = +this.pagenum + 5; - return section.slice(+this.pagenum, +this.pagenum + 5); + if (+this.pagenum + 5 <= this.last) { + return section.slice(+this.pagenum, +this.pagenum + 5); + } + if (+this.pagenum + 5 > this.last) { + return section.slice(this.last - 5, this.last); + } }, paginationsection() { if (this.last < 6 && this.pagenum < 6) { @@ -46,7 +51,7 @@ return +this.last + 1; }, endspread() { - if (+this.pagenum < this.last && +this.pagenum > 5) return true; + if (+this.pagenum < this.last) return true; return false; }, begspread() { @@ -57,17 +62,19 @@ template: `
      -
    • +
    • Prev
    • +
    • + +
    • {{(n - 1)}}
    • - -
    • +
    • Next
    • -
    • - -
    -- cgit v1.2.1 From e95a2b156b181145c98a790edd924e90cca3f3ee Mon Sep 17 00:00:00 2001 From: Regis Date: Mon, 7 Nov 2016 23:56:02 -0700 Subject: remove use of spread operator - attempt render function --- app/assets/javascripts/vue_pagination/index.js.es6 | 36 +++++++++++++++++++--- .../vue_pipelines_index/pipelines.js.es6 | 1 - 2 files changed, 32 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pagination/index.js.es6 b/app/assets/javascripts/vue_pagination/index.js.es6 index 71031c4d76d..7703901e113 100644 --- a/app/assets/javascripts/vue_pagination/index.js.es6 +++ b/app/assets/javascripts/vue_pagination/index.js.es6 @@ -11,6 +11,7 @@ data() { return { nslice: +this.pagenum, + endcount: this.last, }; }, methods: { @@ -20,12 +21,15 @@ }, prevstatus() { if (+this.pagenum > 1) return ''; - return 'prev disabled'; + return 'disabled'; + }, + createSection(n) { + return Array.from(Array(n)).map((e, i) => i); }, }, computed: { dynamicpage() { - const section = [...Array(this.upcount).keys()]; + const section = this.createSection(this.upcount); section.shift(); this.nslice = +this.pagenum; this.endcount = +this.pagenum + 5; @@ -38,7 +42,7 @@ }, paginationsection() { if (this.last < 6 && this.pagenum < 6) { - const pageArray = [...Array(6).keys()]; + const pageArray = this.createSection(6); pageArray.shift(); return pageArray.slice(0, this.upcount); } @@ -81,7 +85,7 @@ class="next" v-if='(n === upcount || n === endcount) && pagenum !== last' > - Next + Next
  • `, + // render(createElement) { + // return createElement('div', { + // class: { + // 'gl-pagination': true, + // }, + // }, [createElement('ul', { + // class: { + // pagination: true, + // clearfix: true, + // }, + // }, this.paginationsection.map((e, i) => { + // if (!i) return createElement('li', [createElement('span', { + // class: { + // prev: this.prevstatus, + // }, + // }, 'Prev')]); + // if (i) { + // return createElement('li', + // [createElement('span', i)] + // ); + // } + // })), + // ]); + // }, }); })(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index 3ab336f0e6d..4ef9fca6474 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -40,7 +40,6 @@ if (page.where) this.pagenum = +page.where; if (page.where) this.pagenum = +page.where; - // use p instead of page to avoid making an actual request window.history.pushState({}, null, `?p=${this.pagenum}`); clearInterval(this.intervalId); this.store.fetchDataLoop.call(this, Vue, this.pagenum); -- cgit v1.2.1 From 6970c1f331e1f56424ff90fe43113d9f512bce95 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Wed, 2 Nov 2016 16:41:32 +0100 Subject: Allow to use Dockerfile templates --- app/assets/javascripts/api.js | 5 ++++ app/assets/javascripts/blob/blob_ci_yaml.js.es6 | 36 +++++++++++++++++++++++++ app/assets/javascripts/blob_edit/edit_blob.js | 3 +++ app/assets/stylesheets/pages/editor.scss | 6 +++-- app/helpers/blob_helper.rb | 4 +++ app/views/projects/blob/_editor.html.haml | 2 ++ 6 files changed, 54 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js index 1cab66e109e..291efd2e286 100644 --- a/app/assets/javascripts/api.js +++ b/app/assets/javascripts/api.js @@ -10,6 +10,7 @@ licensePath: "/api/:version/templates/licenses/:key", gitignorePath: "/api/:version/templates/gitignores/:key", gitlabCiYmlPath: "/api/:version/templates/gitlab_ci_ymls/:key", + dockerfilePath: "/api/:version/dockerfiles/:key", issuableTemplatePath: "/:namespace_path/:project_path/templates/:type/:key", group: function(group_id, callback) { var url = Api.buildUrl(Api.groupPath) @@ -119,6 +120,10 @@ return callback(file); }); }, + dockerfileYml: function(key, callback) { + var url = Api.buildUrl(Api.dockerfilePath).replace(':key', key); + $.get(url, callback); + }, issueTemplate: function(namespacePath, projectPath, key, type, callback) { var url = Api.buildUrl(Api.issuableTemplatePath) .replace(':key', key) diff --git a/app/assets/javascripts/blob/blob_ci_yaml.js.es6 b/app/assets/javascripts/blob/blob_ci_yaml.js.es6 index 37531aaec9b..62e686b8d9b 100644 --- a/app/assets/javascripts/blob/blob_ci_yaml.js.es6 +++ b/app/assets/javascripts/blob/blob_ci_yaml.js.es6 @@ -38,4 +38,40 @@ global.BlobCiYamlSelectors = BlobCiYamlSelectors; + class BlobDockerfileSelector extends gl.TemplateSelector { + requestFile(query) { + return Api.dockerfileYml(query.name, this.requestFileSuccess.bind(this)); + } + + requestFileSuccess(file) { + return super.requestFileSuccess(file); + } + } + + global.BlobDockerfileSelector = BlobDockerfileSelector; + + class BlobDockerfileSelectors { + constructor({ editor, $dropdowns } = {}) { + this.editor = editor; + this.$dropdowns = $dropdowns || $('.js-dockerfile-selector'); + this.initSelectors(); + } + + initSelectors() { + const editor = this.editor; + this.$dropdowns.each((i, dropdown) => { + const $dropdown = $(dropdown); + return new BlobDockerfileSelector({ + editor, + pattern: /(Dockerfile)/, + data: $dropdown.data('data'), + wrapper: $dropdown.closest('.js-dockerfile-selector-wrap'), + dropdown: $dropdown + }); + }); + } + } + + global.BlobDockerfileSelectors = BlobDockerfileSelectors; + })(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/blob_edit/edit_blob.js b/app/assets/javascripts/blob_edit/edit_blob.js index 60840560dd3..11dff7dfab4 100644 --- a/app/assets/javascripts/blob_edit/edit_blob.js +++ b/app/assets/javascripts/blob_edit/edit_blob.js @@ -33,6 +33,9 @@ new gl.BlobCiYamlSelectors({ editor: this.editor }); + new gl.BlobDockerfileSelectors({ + editor: this.editor + }); } EditBlob.prototype.initModePanesAndLinks = function() { diff --git a/app/assets/stylesheets/pages/editor.scss b/app/assets/stylesheets/pages/editor.scss index 778126bcfb7..ac968618c79 100644 --- a/app/assets/stylesheets/pages/editor.scss +++ b/app/assets/stylesheets/pages/editor.scss @@ -67,7 +67,8 @@ .soft-wrap-toggle, .license-selector, .gitignore-selector, - .gitlab-ci-yml-selector { + .gitlab-ci-yml-selector, + .dockerfile-selector { display: inline-block; vertical-align: top; font-family: $regular_font; @@ -97,7 +98,8 @@ .gitignore-selector, .license-selector, - .gitlab-ci-yml-selector { + .gitlab-ci-yml-selector, + .dockerfile-selector { .dropdown { line-height: 21px; } diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb index 07ff6fb9488..f31d4fb897d 100644 --- a/app/helpers/blob_helper.rb +++ b/app/helpers/blob_helper.rb @@ -191,6 +191,10 @@ module BlobHelper @gitlab_ci_ymls ||= Gitlab::Template::GitlabCiYmlTemplate.dropdown_names end + def dockerfile_names + @dockerfile_names ||= Gitlab::Template::DockerfileTemplate.dropdown_names + end + def blob_editor_paths { 'relative-url-root' => Rails.application.config.relative_url_root, diff --git a/app/views/projects/blob/_editor.html.haml b/app/views/projects/blob/_editor.html.haml index 4a6aa92e3f3..34dc96bcb64 100644 --- a/app/views/projects/blob/_editor.html.haml +++ b/app/views/projects/blob/_editor.html.haml @@ -21,6 +21,8 @@ = dropdown_tag("Choose a .gitignore template", options: { toggle_class: 'btn js-gitignore-selector', title: "Choose a template", filter: true, placeholder: "Filter", data: { data: gitignore_names } } ) .gitlab-ci-yml-selector.js-gitlab-ci-yml-selector-wrap.hidden = dropdown_tag("Choose a GitLab CI Yaml template", options: { toggle_class: 'btn js-gitlab-ci-yml-selector', title: "Choose a template", filter: true, placeholder: "Filter", data: { data: gitlab_ci_ymls } } ) + .gitlab-ci-yml-selector.js-dockerfile-selector-wrap.hidden + = dropdown_tag("Choose a Dockerfile template", options: { toggle_class: 'js-dockerfile-selector', title: "Choose a template", filter: true, placeholder: "Filter", data: { data: dockerfile_names } } ) = button_tag class: 'soft-wrap-toggle btn', type: 'button' do %span.no-wrap = custom_icon('icon_no_wrap') -- cgit v1.2.1 From dcd20236ec0f05b46702611f09e2af8094a383ae Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Tue, 8 Nov 2016 12:42:58 +0000 Subject: Refactored JS Added spec --- app/assets/javascripts/blob/blob_ci_yaml.js.es6 | 36 ---------------------- .../blob/blob_dockerfile_selector.js.es6 | 18 +++++++++++ .../blob/blob_dockerfile_selectors.js.es6 | 27 ++++++++++++++++ app/assets/javascripts/blob_edit/edit_blob.js | 6 ++-- app/views/projects/blob/_editor.html.haml | 4 +-- 5 files changed, 50 insertions(+), 41 deletions(-) create mode 100644 app/assets/javascripts/blob/blob_dockerfile_selector.js.es6 create mode 100644 app/assets/javascripts/blob/blob_dockerfile_selectors.js.es6 (limited to 'app') diff --git a/app/assets/javascripts/blob/blob_ci_yaml.js.es6 b/app/assets/javascripts/blob/blob_ci_yaml.js.es6 index 62e686b8d9b..37531aaec9b 100644 --- a/app/assets/javascripts/blob/blob_ci_yaml.js.es6 +++ b/app/assets/javascripts/blob/blob_ci_yaml.js.es6 @@ -38,40 +38,4 @@ global.BlobCiYamlSelectors = BlobCiYamlSelectors; - class BlobDockerfileSelector extends gl.TemplateSelector { - requestFile(query) { - return Api.dockerfileYml(query.name, this.requestFileSuccess.bind(this)); - } - - requestFileSuccess(file) { - return super.requestFileSuccess(file); - } - } - - global.BlobDockerfileSelector = BlobDockerfileSelector; - - class BlobDockerfileSelectors { - constructor({ editor, $dropdowns } = {}) { - this.editor = editor; - this.$dropdowns = $dropdowns || $('.js-dockerfile-selector'); - this.initSelectors(); - } - - initSelectors() { - const editor = this.editor; - this.$dropdowns.each((i, dropdown) => { - const $dropdown = $(dropdown); - return new BlobDockerfileSelector({ - editor, - pattern: /(Dockerfile)/, - data: $dropdown.data('data'), - wrapper: $dropdown.closest('.js-dockerfile-selector-wrap'), - dropdown: $dropdown - }); - }); - } - } - - global.BlobDockerfileSelectors = BlobDockerfileSelectors; - })(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/blob/blob_dockerfile_selector.js.es6 b/app/assets/javascripts/blob/blob_dockerfile_selector.js.es6 new file mode 100644 index 00000000000..bdf95017613 --- /dev/null +++ b/app/assets/javascripts/blob/blob_dockerfile_selector.js.es6 @@ -0,0 +1,18 @@ +/* global Api */ +/*= require blob/template_selector */ + +(() => { + const global = window.gl || (window.gl = {}); + + class BlobDockerfileSelector extends gl.TemplateSelector { + requestFile(query) { + return Api.dockerfileYml(query.name, this.requestFileSuccess.bind(this)); + } + + requestFileSuccess(file) { + return super.requestFileSuccess(file); + } + } + + global.BlobDockerfileSelector = BlobDockerfileSelector; +})(); diff --git a/app/assets/javascripts/blob/blob_dockerfile_selectors.js.es6 b/app/assets/javascripts/blob/blob_dockerfile_selectors.js.es6 new file mode 100644 index 00000000000..9cee79fa5d5 --- /dev/null +++ b/app/assets/javascripts/blob/blob_dockerfile_selectors.js.es6 @@ -0,0 +1,27 @@ +(() => { + const global = window.gl || (window.gl = {}); + + class BlobDockerfileSelectors { + constructor({ editor, $dropdowns } = {}) { + this.editor = editor; + this.$dropdowns = $dropdowns || $('.js-dockerfile-selector'); + this.initSelectors(); + } + + initSelectors() { + const editor = this.editor; + this.$dropdowns.each((i, dropdown) => { + const $dropdown = $(dropdown); + return new gl.BlobDockerfileSelector({ + editor, + pattern: /(Dockerfile)/, + data: $dropdown.data('data'), + wrapper: $dropdown.closest('.js-dockerfile-selector-wrap'), + dropdown: $dropdown, + }); + }); + } + } + + global.BlobDockerfileSelectors = BlobDockerfileSelectors; +})(); diff --git a/app/assets/javascripts/blob_edit/edit_blob.js b/app/assets/javascripts/blob_edit/edit_blob.js index 11dff7dfab4..74cc0af2486 100644 --- a/app/assets/javascripts/blob_edit/edit_blob.js +++ b/app/assets/javascripts/blob_edit/edit_blob.js @@ -33,9 +33,9 @@ new gl.BlobCiYamlSelectors({ editor: this.editor }); - new gl.BlobDockerfileSelectors({ - editor: this.editor - }); + new gl.BlobDockerfileSelectors({ + editor: this.editor + }); } EditBlob.prototype.initModePanesAndLinks = function() { diff --git a/app/views/projects/blob/_editor.html.haml b/app/views/projects/blob/_editor.html.haml index 34dc96bcb64..1d058daa094 100644 --- a/app/views/projects/blob/_editor.html.haml +++ b/app/views/projects/blob/_editor.html.haml @@ -21,8 +21,8 @@ = dropdown_tag("Choose a .gitignore template", options: { toggle_class: 'btn js-gitignore-selector', title: "Choose a template", filter: true, placeholder: "Filter", data: { data: gitignore_names } } ) .gitlab-ci-yml-selector.js-gitlab-ci-yml-selector-wrap.hidden = dropdown_tag("Choose a GitLab CI Yaml template", options: { toggle_class: 'btn js-gitlab-ci-yml-selector', title: "Choose a template", filter: true, placeholder: "Filter", data: { data: gitlab_ci_ymls } } ) - .gitlab-ci-yml-selector.js-dockerfile-selector-wrap.hidden - = dropdown_tag("Choose a Dockerfile template", options: { toggle_class: 'js-dockerfile-selector', title: "Choose a template", filter: true, placeholder: "Filter", data: { data: dockerfile_names } } ) + .dockerfile-selector.js-dockerfile-selector-wrap.hidden + = dropdown_tag("Choose a Dockerfile template", options: { toggle_class: 'btn js-dockerfile-selector', title: "Choose a template", filter: true, placeholder: "Filter", data: { data: dockerfile_names } } ) = button_tag class: 'soft-wrap-toggle btn', type: 'button' do %span.no-wrap = custom_icon('icon_no_wrap') -- cgit v1.2.1 From cdbbce17cb0f83895183d342fa27e0ee015f58bb Mon Sep 17 00:00:00 2001 From: Regis Date: Tue, 8 Nov 2016 12:23:29 -0700 Subject: cleanup --- app/assets/javascripts/vue_pagination/index.js.es6 | 115 ++++----------------- .../javascripts/vue_pipelines_index/index.js.es6 | 2 +- .../vue_pipelines_index/pipeline_head.js.es6 | 7 -- .../vue_pipelines_index/pipelines.js.es6 | 10 +- .../javascripts/vue_pipelines_index/store.js.es6 | 2 +- .../javascripts/vue_pipelines_status/failed.js.es6 | 2 +- 6 files changed, 27 insertions(+), 111 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pagination/index.js.es6 b/app/assets/javascripts/vue_pagination/index.js.es6 index 7703901e113..dce1c86ffa2 100644 --- a/app/assets/javascripts/vue_pagination/index.js.es6 +++ b/app/assets/javascripts/vue_pagination/index.js.es6 @@ -8,117 +8,38 @@ 'count', 'pagenum', ], - data() { - return { - nslice: +this.pagenum, - endcount: this.last, - }; - }, methods: { pagenumberstatus(n) { if (n - 1 === +this.pagenum) return 'active'; return ''; }, - prevstatus() { - if (+this.pagenum > 1) return ''; - return 'disabled'; - }, - createSection(n) { - return Array.from(Array(n)).map((e, i) => i); - }, + createSection(n) { return Array.from(Array(n)).map((e, i) => i); }, }, computed: { - dynamicpage() { - const section = this.createSection(this.upcount); - section.shift(); - this.nslice = +this.pagenum; - this.endcount = +this.pagenum + 5; - if (+this.pagenum + 5 <= this.last) { - return section.slice(+this.pagenum, +this.pagenum + 5); - } - if (+this.pagenum + 5 > this.last) { - return section.slice(this.last - 5, this.last); - } - }, - paginationsection() { - if (this.last < 6 && this.pagenum < 6) { - const pageArray = this.createSection(6); - pageArray.shift(); - return pageArray.slice(0, this.upcount); - } - return this.dynamicpage; - }, - last() { - return Math.ceil(+this.count / 5); - }, - upcount() { - return +this.last + 1; - }, - endspread() { - if (+this.pagenum < this.last) return true; - return false; - }, - begspread() { - if (+this.pagenum > 5 && +this.pagenum < this.last) return true; - return false; + last() { return Math.ceil(+this.count / 5); }, + getItems() { + const items = []; + const pages = this.createSection(+this.last + 1); + pages.shift(); + + if (+this.pagenum !== 1) items.push({ text: 'Prev' }); + + pages.forEach(i => items.push({ text: i })); + + if (+this.pagenum < this.last) items.push({ text: 'Next' }); + if (+this.pagenum !== this.last) items.push({ text: 'Last »' }); + + return items; }, }, template: `
    -
      -
    • - Prev -
    • -
    • - -
    • -
    • - {{(n - 1)}} -
    • -
    • - -
    • - -
    • - Last » +
        +
      • + {{item.text}}
    `, - // render(createElement) { - // return createElement('div', { - // class: { - // 'gl-pagination': true, - // }, - // }, [createElement('ul', { - // class: { - // pagination: true, - // clearfix: true, - // }, - // }, this.paginationsection.map((e, i) => { - // if (!i) return createElement('li', [createElement('span', { - // class: { - // prev: this.prevstatus, - // }, - // }, 'Prev')]); - // if (i) { - // return createElement('li', - // [createElement('span', i)] - // ); - // } - // })), - // ]); - // }, }); })(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/index.js.es6 b/app/assets/javascripts/vue_pipelines_index/index.js.es6 index 1aea0820208..f7657879ac4 100644 --- a/app/assets/javascripts/vue_pipelines_index/index.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/index.js.es6 @@ -34,7 +34,7 @@ diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_head.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_head.js.es6 index 2ead571aa9f..510e54f3a6f 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipeline_head.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipeline_head.js.es6 @@ -3,13 +3,6 @@ ((gl) => { gl.VuePipelineHead = Vue.extend({ - components: { - 'vue-running-icon': gl.VueRunningIcon, - }, - props: [ - 'pipeline', - 'pipelineurl', - ], template: ` diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index 4ef9fca6474..ecb07af9a32 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -35,10 +35,12 @@ shortsha(pipeline) { return pipeline.sha.slice(0, 8); }, - changepage(event, page = {}) { - if (page) this.pagenum = +event.target.innerText; - if (page.where) this.pagenum = +page.where; - if (page.where) this.pagenum = +page.where; + changepage(event, last) { + const text = event.target.innerText; + if (typeof +text === 'number') this.pagenum = +text; + if (text === 'Last »') this.pagenum = last; + if (text === 'Next') this.pagnum = +this.pagenum + 1; + if (text === 'Prev') this.pagenum = +this.pagenum - 1; window.history.pushState({}, null, `?p=${this.pagenum}`); clearInterval(this.intervalId); diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index 89982b11b31..d4b0c79f225 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -21,7 +21,7 @@ // eventually clearInterval(this.intervalId) this.intervalId = setInterval(() => { goFetch(); - }, 60000); + }, 3000); } }; })(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_status/failed.js.es6 b/app/assets/javascripts/vue_pipelines_status/failed.js.es6 index 92373e12c25..a877cfc688e 100644 --- a/app/assets/javascripts/vue_pipelines_status/failed.js.es6 +++ b/app/assets/javascripts/vue_pipelines_status/failed.js.es6 @@ -4,7 +4,7 @@ ((gl) => { gl.VueFailedScope = Vue.extend({ components: { - 'vue-failed-icon': gl.VuePendingIcon, + 'vue-failed-icon': gl.VueFailedIcon, }, props: [ 'scope', -- cgit v1.2.1 From 4dd82e1d49d5dc1958c2425d1d052645638c2274 Mon Sep 17 00:00:00 2001 From: Regis Date: Tue, 8 Nov 2016 12:31:41 -0700 Subject: fix changepage logic --- app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index ecb07af9a32..2c26b0a2bc7 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -37,9 +37,9 @@ }, changepage(event, last) { const text = event.target.innerText; - if (typeof +text === 'number') this.pagenum = +text; + if (typeof text === 'number') this.pagenum = +text; if (text === 'Last »') this.pagenum = last; - if (text === 'Next') this.pagnum = +this.pagenum + 1; + if (text === 'Next') this.pagenum = +this.pagenum + 1; if (text === 'Prev') this.pagenum = +this.pagenum - 1; window.history.pushState({}, null, `?p=${this.pagenum}`); -- cgit v1.2.1 From 39a8f1aaf4c05764045de5fcdacd52af2406c152 Mon Sep 17 00:00:00 2001 From: Regis Date: Tue, 8 Nov 2016 13:04:30 -0700 Subject: regex for number check --- app/assets/javascripts/vue_pagination/index.js.es6 | 17 +++++++++++------ .../javascripts/vue_pipelines_index/pipelines.js.es6 | 2 +- 2 files changed, 12 insertions(+), 7 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pagination/index.js.es6 b/app/assets/javascripts/vue_pagination/index.js.es6 index dce1c86ffa2..8dabfef3b95 100644 --- a/app/assets/javascripts/vue_pagination/index.js.es6 +++ b/app/assets/javascripts/vue_pagination/index.js.es6 @@ -9,9 +9,14 @@ 'pagenum', ], methods: { - pagenumberstatus(n) { - if (n - 1 === +this.pagenum) return 'active'; - return ''; + pagestatus(n) { + if (n - 1 === +this.pagenum) return true; + return false; + }, + prevstatus(index) { + if (index > 0) return false; + if (+this.pagenum < 2) return true; + return false; }, createSection(n) { return Array.from(Array(n)).map((e, i) => i); }, }, @@ -22,7 +27,7 @@ const pages = this.createSection(+this.last + 1); pages.shift(); - if (+this.pagenum !== 1) items.push({ text: 'Prev' }); + items.push({ text: 'Prev', class: this.prevstatus() }); pages.forEach(i => items.push({ text: i })); @@ -34,8 +39,8 @@ }, template: `
    -
    + Date: Thu, 10 Nov 2016 21:18:33 -0700 Subject: conditional action buttons - spans for pipeline tags --- .../vue_pipelines_index/pipeline_actions.js.es6 | 14 ++++++++++++-- .../javascripts/vue_pipelines_index/pipeline_url.js.es6 | 16 ++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 index 0b469e8ffb6..583069aea2a 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 @@ -24,7 +24,12 @@
    - + diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 index d0cbf99a344..9ebbe3ccf9e 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 @@ -22,6 +22,22 @@ by {{user}} + + latest + + + yaml invalid + `, }); -- cgit v1.2.1 From df1b15e327877066364271384975a8307d5f6c22 Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 10 Nov 2016 22:21:09 -0700 Subject: loading icon - rename component keys --- .../vue_pipelines_index/pipelines.js.es6 | 28 ++++++++++++++-------- .../javascripts/vue_pipelines_index/store.js.es6 | 2 +- 2 files changed, 19 insertions(+), 11 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index 7dcc319390e..421e4111187 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -4,15 +4,15 @@ ((gl) => { gl.VuePipeLines = Vue.extend({ components: { - 'running-pipeline': gl.VueRunningPipeline, - 'stages': gl.VueStages, - 'pipeline-actions': gl.VuePipelineActions, - 'branch-commit': gl.VueBranchCommit, - 'pipeline-url': gl.VuePipelineUrl, - 'pipeline-head': gl.VuePipelineHead, - 'gl-pagination': gl.VueGlPagination, - 'status-scope': gl.VueStatusScope, - 'time-ago': gl.VueTimeAgo, + runningPipeline: gl.VueRunningPipeline, + pipelineActions: gl.VuePipelineActions, + stages: gl.VueStages, + branchCommit: gl.VueBranchCommit, + pipelineUrl: gl.VuePipelineUrl, + pipelineHead: gl.VuePipelineHead, + glPagination: gl.VueGlPagination, + statusScope: gl.VueStatusScope, + timeAgo: gl.VueTimeAgo, }, data() { return { @@ -24,6 +24,7 @@ all: 0, running_or_pending: 0, }, + pageRequest: false, }; }, props: [ @@ -47,12 +48,16 @@ window.history.pushState({}, null, `?p=${this.pagenum}`); clearInterval(this.intervalId); + this.pageRequest = true; this.store.fetchDataLoop.call(this, Vue, this.pagenum, this.scope); }, }, template: `
    -
    +
    + +
    +
    @@ -67,6 +72,9 @@
    +
    + +
    { const res = JSON.parse(response.body); - debugger Vue.set(this, 'updatedAt', res.updated_at); Vue.set(this, 'pipelines', res.pipelines); Vue.set(this, 'count', res.count); + this.pageRequest = false; }, () => new Flash( 'Something went wrong on our end.' )); -- cgit v1.2.1 From 71ae01fefe62caf396640affb8ca618fe68db5a0 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 11 Nov 2016 21:44:33 +0800 Subject: Add more tests and fix write to project check --- app/models/deploy_key.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app') diff --git a/app/models/deploy_key.rb b/app/models/deploy_key.rb index 2c525d4cd7a..503398f5cca 100644 --- a/app/models/deploy_key.rb +++ b/app/models/deploy_key.rb @@ -20,4 +20,8 @@ class DeployKey < Key def destroyed_when_orphaned? self.private? end + + def can_push_to?(project) + can_push? && projects.include?(project) + end end -- cgit v1.2.1 From 31e34715bf62993a42ca7636edf1408891b0595b Mon Sep 17 00:00:00 2001 From: Regis Date: Fri, 11 Nov 2016 12:05:07 -0700 Subject: scoped polyfill for now --- .../javascripts/vue_pipelines_index/index.js.es6 | 1 + .../vue_pipelines_index/object_assign.js.es6 | 30 ++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 app/assets/javascripts/vue_pipelines_index/object_assign.js.es6 (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/index.js.es6 b/app/assets/javascripts/vue_pipelines_index/index.js.es6 index 3a7842f305b..ab53b12d3d0 100644 --- a/app/assets/javascripts/vue_pipelines_index/index.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/index.js.es6 @@ -3,6 +3,7 @@ //= require vue-resource +//= require ./object_assign.js.es6 //= require ./store.js.es6 //= require ./pipeline_url.js.es6 //= require ./pipeline_head.js.es6 diff --git a/app/assets/javascripts/vue_pipelines_index/object_assign.js.es6 b/app/assets/javascripts/vue_pipelines_index/object_assign.js.es6 new file mode 100644 index 00000000000..05a5a7da1c3 --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_index/object_assign.js.es6 @@ -0,0 +1,30 @@ +/* eslint-disable */ + +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ +(() => { + if (typeof Object.assign != 'function') { + (function () { + Object.assign = function (target) { + 'use strict'; + // We must check against these specific cases. + if (target === undefined || target === null) { + throw new TypeError('Cannot convert undefined or null to object'); + } + + var output = Object(target); + for (var index = 1; index < arguments.length; index++) { + var source = arguments[index]; + if (source !== undefined && source !== null) { + for (var nextKey in source) { + if (source.hasOwnProperty(nextKey)) { + output[nextKey] = source[nextKey]; + } + } + } + } + return output; + }; + })(); + } +})(); -- cgit v1.2.1 From b64ee664a69eaa0474a8befeb2379e948eb647cb Mon Sep 17 00:00:00 2001 From: Regis Date: Fri, 11 Nov 2016 12:25:10 -0700 Subject: add stuck icon --- app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 index 9ebbe3ccf9e..efeef974960 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 @@ -38,6 +38,12 @@ > yaml invalid + + stuck + `, }); -- cgit v1.2.1 From af4459e5314b8d7d054995e6cf244e91feacf78a Mon Sep 17 00:00:00 2001 From: Regis Date: Fri, 11 Nov 2016 12:35:57 -0700 Subject: update stage icons with created --- app/assets/javascripts/vue_icons/index.js.es6 | 9 +++++++++ .../javascripts/vue_pipelines_index/stage.js.es6 | 7 ++++++- .../vue_pipelines_status/created.js.es6 | 23 ++++++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 app/assets/javascripts/vue_pipelines_status/created.js.es6 (limited to 'app') diff --git a/app/assets/javascripts/vue_icons/index.js.es6 b/app/assets/javascripts/vue_icons/index.js.es6 index 413f9b45393..66b4a58a4c0 100644 --- a/app/assets/javascripts/vue_icons/index.js.es6 +++ b/app/assets/javascripts/vue_icons/index.js.es6 @@ -46,4 +46,13 @@ `, }); + + gl.VueCreatedIcon = Vue.extend({ + template: ` + + + + + `, + }); })(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 index f983226a4ce..8a77f213b7f 100644 --- a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 @@ -8,16 +8,20 @@ 'pending-icon': gl.VuePendingIcon, 'failed-icon': gl.VueFailedIcon, 'success-icon': gl.VueSuccessIcon, + 'created-icon': gl.VueCreatedIcon, }, props: ['stage'], computed: { buildStatus() { return `Build: ${this.stage.status}`; }, + tooltip() { + return `has-tooltip ci-status-icon-${this.stage.status}`; + }, }, template: ` @@ -25,6 +29,7 @@ + `, }); diff --git a/app/assets/javascripts/vue_pipelines_status/created.js.es6 b/app/assets/javascripts/vue_pipelines_status/created.js.es6 new file mode 100644 index 00000000000..b74566b7341 --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_status/created.js.es6 @@ -0,0 +1,23 @@ +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VueCreatedScope = Vue.extend({ + components: { + 'vue-created-icon': gl.VueCreatedIcon, + }, + props: [ + 'pipeline', + ], + template: ` + + + + +  failed + + + + `, + }); +})(window.gl || (window.gl = {})); -- cgit v1.2.1 From e5af16a3e097a6e7ea79c3120b2cc95c64b769ac Mon Sep 17 00:00:00 2001 From: Regis Date: Fri, 11 Nov 2016 12:37:24 -0700 Subject: add created to pipeline scope status --- app/assets/javascripts/vue_pipelines_status/status.js.es6 | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_status/status.js.es6 b/app/assets/javascripts/vue_pipelines_status/status.js.es6 index 3f8cb1164ec..394c6349b91 100644 --- a/app/assets/javascripts/vue_pipelines_status/status.js.es6 +++ b/app/assets/javascripts/vue_pipelines_status/status.js.es6 @@ -7,6 +7,7 @@ 'vue-running-scope': gl.VueRunningScope, 'vue-pending-scope': gl.VuePendingScope, 'vue-failed-scope': gl.VueFailedScope, + 'vue-created-scope': gl.VueCreatedScope, }, props: [ 'pipeline', @@ -28,6 +29,11 @@ :pipeline='pipeline' > + + `, }); -- cgit v1.2.1 From 35c8e533c05a68feacc52cf8b8e173ef6290c641 Mon Sep 17 00:00:00 2001 From: Regis Date: Fri, 11 Nov 2016 12:40:29 -0700 Subject: created component instead of failed --- app/assets/javascripts/vue_pipelines_status/status.js.es6 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_status/status.js.es6 b/app/assets/javascripts/vue_pipelines_status/status.js.es6 index 394c6349b91..0a722ba7ca5 100644 --- a/app/assets/javascripts/vue_pipelines_status/status.js.es6 +++ b/app/assets/javascripts/vue_pipelines_status/status.js.es6 @@ -29,11 +29,11 @@ :pipeline='pipeline' > - - + `, }); -- cgit v1.2.1 From 04a4520c2d389bae4358c9429aa22cf3a53ba9a2 Mon Sep 17 00:00:00 2001 From: Regis Date: Sat, 12 Nov 2016 01:57:23 -0700 Subject: fix cancel url - clearInterval on refresh and page close - fix branch url --- app/assets/javascripts/vue_pipelines_index/branch_commit.js.es6 | 2 +- app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 | 4 ++-- app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 | 4 ++-- app/assets/javascripts/vue_pipelines_index/store.js.es6 | 6 +++++- 4 files changed, 10 insertions(+), 6 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/branch_commit.js.es6 b/app/assets/javascripts/vue_pipelines_index/branch_commit.js.es6 index e1f404befa1..43bad6e36e7 100644 --- a/app/assets/javascripts/vue_pipelines_index/branch_commit.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/branch_commit.js.es6 @@ -20,7 +20,7 @@ {{pipeline.ref.name}} diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 index 583069aea2a..c86b49c15fa 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 @@ -80,7 +80,7 @@
    diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index 421e4111187..7872e7d4ac6 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -37,8 +37,8 @@ this.store.fetchDataLoop.call(this, Vue, this.pagenum, this.scope); }, methods: { - changepage(event, last) { - const text = event.target.innerText; + changepage(e, last) { + const text = e.target.innerText; if (text === '...') return; if (/^-?[\d.]+(?:e-?\d+)?$/.test(text)) this.pagenum = +text; if (text === 'Last >>') this.pagenum = last; diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index d00e30760a8..861df939451 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -53,8 +53,12 @@ goFetch(); this.intervalId = setInterval(() => { - goUpdate(); + if (this.updatedAt) goUpdate(); }, 3000); + + window.onbeforeunload = function removePipelineInterval() { + clearInterval(this.intervalId); + }; } }; })(window.gl || (window.gl = {})); -- cgit v1.2.1 From 7748282996d7754a342b5956b1a277a54a9b26f5 Mon Sep 17 00:00:00 2001 From: Regis Date: Sat, 12 Nov 2016 02:00:35 -0700 Subject: better comment [ci skip] --- app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 b/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 index 2fbfa486f88..159c7585580 100644 --- a/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 @@ -21,8 +21,8 @@ }, }, computed: { + // need started_at or created_at for finish and running finishdate() { - // need started_at or created_at here const date = new Date( new Date( this.pipeline.details.finished_at @@ -35,7 +35,6 @@ ); }, runningdate() { - // need started_at or created_at at here const date = new Date( new Date().getTime() - new Date(this.pipeline.started_at).getTime() ); -- cgit v1.2.1 From 6186ac2c3d0db6932993ac681cbed6f453499503 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Sat, 12 Nov 2016 10:05:57 +0100 Subject: Expose created_at and updated_at in pipeline entity --- app/serializers/pipeline_entity.rb | 2 ++ app/serializers/request_aware_entity.rb | 4 ---- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/serializers/pipeline_entity.rb b/app/serializers/pipeline_entity.rb index 24fe1602c2d..08346b4ed77 100644 --- a/app/serializers/pipeline_entity.rb +++ b/app/serializers/pipeline_entity.rb @@ -64,6 +64,8 @@ class PipelineEntity < Grape::Entity pipeline.project, pipeline.id) end + expose :created_at, :updated_at + def created_exposure? !incremental? || created? end diff --git a/app/serializers/request_aware_entity.rb b/app/serializers/request_aware_entity.rb index 7a096d9d5a8..e159d750cb7 100644 --- a/app/serializers/request_aware_entity.rb +++ b/app/serializers/request_aware_entity.rb @@ -9,10 +9,6 @@ module RequestAwareEntity @options.fetch(:request) end - def current_user - @options.fetch(:current_user) - end - def can?(object, action, subject) Ability.allowed?(object, action, subject) end -- cgit v1.2.1 From 0541bffa85cde86d4ce142b6fe2d3e1357b1acc5 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Sat, 12 Nov 2016 10:53:03 +0100 Subject: Expose commit author's gravatar if not gitlab user --- app/serializers/commit_entity.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app') diff --git a/app/serializers/commit_entity.rb b/app/serializers/commit_entity.rb index f7eba6fc1e3..121ca76a16f 100644 --- a/app/serializers/commit_entity.rb +++ b/app/serializers/commit_entity.rb @@ -3,6 +3,10 @@ class CommitEntity < API::Entities::RepoCommit expose :author, using: UserEntity + expose :author_gravatar_url do |commit| + GravatarService.new.execute(commit.author_email) + end + expose :commit_url do |commit| namespace_project_tree_url( request.project.namespace, -- cgit v1.2.1 From a3c93ee8ad2caae0d7ace8c4a0c796840209f20e Mon Sep 17 00:00:00 2001 From: Regis Date: Sat, 12 Nov 2016 03:21:00 -0700 Subject: waiting for api changes --- .../vue_pipelines_index/branch_commit.js.es6 | 8 ++++++-- .../javascripts/vue_pipelines_index/time_ago.js.es6 | 18 ++++++++---------- 2 files changed, 14 insertions(+), 12 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/branch_commit.js.es6 b/app/assets/javascripts/vue_pipelines_index/branch_commit.js.es6 index 43bad6e36e7..b594d08e96d 100644 --- a/app/assets/javascripts/vue_pipelines_index/branch_commit.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/branch_commit.js.es6 @@ -11,13 +11,17 @@ alt() { return `${this.pipeline.commit.author_name}'s avatar`; }, + avatarUrl() { + const author = this.pipeline.commit.author; + if (author) return author.avatar_url; + return this.pipeline.commit.author_gravatar_url; + }, }, template: `
    -
    - {{duration}} + {{duration()}}

    -

    +

    -- cgit v1.2.1 From 4f290de7c14131f9241834136ae4f0b7de0aa394 Mon Sep 17 00:00:00 2001 From: Regis Date: Mon, 14 Nov 2016 09:58:20 -0700 Subject: add cancelled icon --- app/assets/javascripts/vue_icons/index.js.es6 | 11 +++++++++++ .../javascripts/vue_pipelines_index/stage.js.es6 | 2 ++ .../vue_pipelines_status/canceled.js.es6 | 23 ++++++++++++++++++++++ .../javascripts/vue_pipelines_status/index.js.es6 | 1 + .../javascripts/vue_pipelines_status/status.js.es6 | 6 ++++++ 5 files changed, 43 insertions(+) create mode 100644 app/assets/javascripts/vue_pipelines_status/canceled.js.es6 (limited to 'app') diff --git a/app/assets/javascripts/vue_icons/index.js.es6 b/app/assets/javascripts/vue_icons/index.js.es6 index 66b4a58a4c0..b7da80a6377 100644 --- a/app/assets/javascripts/vue_icons/index.js.es6 +++ b/app/assets/javascripts/vue_icons/index.js.es6 @@ -55,4 +55,15 @@ `, }); + + gl.VueCanceledIcon = Vue.extend({ + template: ` + + + + + + + `, + }); })(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 index 8a77f213b7f..e5f9178a796 100644 --- a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 @@ -9,6 +9,7 @@ 'failed-icon': gl.VueFailedIcon, 'success-icon': gl.VueSuccessIcon, 'created-icon': gl.VueCreatedIcon, + 'canceled-icon': gl.VueCanceledIcon, }, props: ['stage'], computed: { @@ -30,6 +31,7 @@ +
    `, }); diff --git a/app/assets/javascripts/vue_pipelines_status/canceled.js.es6 b/app/assets/javascripts/vue_pipelines_status/canceled.js.es6 new file mode 100644 index 00000000000..ed677fea93c --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_status/canceled.js.es6 @@ -0,0 +1,23 @@ +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VueCanceledScope = Vue.extend({ + components: { + 'vue-canceled-icon': gl.VueCanceledIcon, + }, + props: [ + 'pipeline', + ], + template: ` + + + + +  cancelled + + + + `, + }); +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_status/index.js.es6 b/app/assets/javascripts/vue_pipelines_status/index.js.es6 index cea02b5d6af..ab2755eb323 100644 --- a/app/assets/javascripts/vue_pipelines_status/index.js.es6 +++ b/app/assets/javascripts/vue_pipelines_status/index.js.es6 @@ -1,4 +1,5 @@ //= require ./pending.js.es6 //= require ./failed.js.es6 //= require ./running.js.es6 +//= require ./canceled.js.es6 //= require ./status.js.es6 diff --git a/app/assets/javascripts/vue_pipelines_status/status.js.es6 b/app/assets/javascripts/vue_pipelines_status/status.js.es6 index 0a722ba7ca5..8732337c3ef 100644 --- a/app/assets/javascripts/vue_pipelines_status/status.js.es6 +++ b/app/assets/javascripts/vue_pipelines_status/status.js.es6 @@ -8,6 +8,7 @@ 'vue-pending-scope': gl.VuePendingScope, 'vue-failed-scope': gl.VueFailedScope, 'vue-created-scope': gl.VueCreatedScope, + 'vue-canceled-scope': gl.VueCanceledScope, }, props: [ 'pipeline', @@ -34,6 +35,11 @@ :pipeline='pipeline' > + + `, }); -- cgit v1.2.1 From 2d1effb11e74883ed16e3577fcdfc05d2692c12e Mon Sep 17 00:00:00 2001 From: Regis Date: Mon, 14 Nov 2016 10:08:14 -0700 Subject: change class name for css to take effect --- app/assets/javascripts/vue_pipelines_status/canceled.js.es6 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_status/canceled.js.es6 b/app/assets/javascripts/vue_pipelines_status/canceled.js.es6 index ed677fea93c..20ca8ad5ebb 100644 --- a/app/assets/javascripts/vue_pipelines_status/canceled.js.es6 +++ b/app/assets/javascripts/vue_pipelines_status/canceled.js.es6 @@ -12,9 +12,9 @@ template: ` - + -  cancelled +  canceled -- cgit v1.2.1 From 40a503650e319cefb285c63f8cbfc39f3422a837 Mon Sep 17 00:00:00 2001 From: Regis Date: Mon, 14 Nov 2016 12:43:08 -0700 Subject: more progress --- app/assets/javascripts/vue_icons/index.js.es6 | 21 ++++++++++++++++++++ .../vue_pipelines_index/pipeline_actions.js.es6 | 2 +- .../vue_pipelines_index/time_ago.js.es6 | 1 - .../javascripts/vue_pipelines_status/index.js.es6 | 2 ++ .../vue_pipelines_status/skipped.js.es6 | 23 ++++++++++++++++++++++ .../javascripts/vue_pipelines_status/status.js.es6 | 6 ++++++ .../vue_pipelines_status/unstable.js.es6 | 23 ++++++++++++++++++++++ 7 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 app/assets/javascripts/vue_pipelines_status/skipped.js.es6 create mode 100644 app/assets/javascripts/vue_pipelines_status/unstable.js.es6 (limited to 'app') diff --git a/app/assets/javascripts/vue_icons/index.js.es6 b/app/assets/javascripts/vue_icons/index.js.es6 index b7da80a6377..84a19348862 100644 --- a/app/assets/javascripts/vue_icons/index.js.es6 +++ b/app/assets/javascripts/vue_icons/index.js.es6 @@ -66,4 +66,25 @@ `, }); + + gl.VueSkippedIcon = Vue.extend({ + template: ` + + + + + + `, + }); + + gl.VueUnstableIcon = Vue.extend({ + template: ` + + + + + + { + gl.VueSkippedScope = Vue.extend({ + components: { + 'vue-skipped-icon': gl.VueSkippedIcon, + }, + props: [ + 'pipeline', + ], + template: ` + + + + +  skipped + + + + `, + }); +})(window.gl || (window.gl = {})); \ No newline at end of file diff --git a/app/assets/javascripts/vue_pipelines_status/status.js.es6 b/app/assets/javascripts/vue_pipelines_status/status.js.es6 index 8732337c3ef..dfef19e21da 100644 --- a/app/assets/javascripts/vue_pipelines_status/status.js.es6 +++ b/app/assets/javascripts/vue_pipelines_status/status.js.es6 @@ -9,6 +9,7 @@ 'vue-failed-scope': gl.VueFailedScope, 'vue-created-scope': gl.VueCreatedScope, 'vue-canceled-scope': gl.VueCanceledScope, + 'vue-unstable-scope': gl.VueUnstableScope, }, props: [ 'pipeline', @@ -40,6 +41,11 @@ :pipeline='pipeline' > + + `, }); diff --git a/app/assets/javascripts/vue_pipelines_status/unstable.js.es6 b/app/assets/javascripts/vue_pipelines_status/unstable.js.es6 new file mode 100644 index 00000000000..27fd29b9d80 --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_status/unstable.js.es6 @@ -0,0 +1,23 @@ +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VueUnstableScope = Vue.extend({ + components: { + 'vue-unstable-icon': gl.VueUnstableIcon, + }, + props: [ + 'pipeline', + ], + template: ` + + + + +  unstable + + + + `, + }); +})(window.gl || (window.gl = {})); -- cgit v1.2.1 From fa1a99a17388c3880e84385255566d776960cf4c Mon Sep 17 00:00:00 2001 From: Regis Date: Mon, 14 Nov 2016 12:44:50 -0700 Subject: rid of extra api calls --- .../javascripts/vue_pipelines_index/pipeline_actions.js.es6 | 9 --------- 1 file changed, 9 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 index d1519ec83f7..223fcce62d8 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 @@ -10,14 +10,6 @@ download(name) { return `Download ${name} artifacts`; }, - // retry(e) { - // e.preventDefault(); - // this.$http.post(this.pipeline.retry_url, { - // pipeline: { id: this.pipeline.id }, - // }) - // .then(() => {}) - // .catch(() => new Flash('Something went wrong on our end.')); - // }, }, template: ` @@ -78,7 +70,6 @@
    - Date: Tue, 15 Nov 2016 15:20:37 +0100 Subject: Fix broken pipeline rendering [ci skip] --- app/controllers/projects/pipelines_controller.rb | 2 +- app/models/ci/pipeline.rb | 10 ++++++---- app/views/projects/ci/pipelines/_pipeline.html.haml | 13 +++++-------- 3 files changed, 12 insertions(+), 13 deletions(-) (limited to 'app') diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb index 2d8641871da..3d095e2b690 100644 --- a/app/controllers/projects/pipelines_controller.rb +++ b/app/controllers/projects/pipelines_controller.rb @@ -20,7 +20,7 @@ class Projects::PipelinesController < Projects::ApplicationController pipelines: PipelineSerializer .new(project: @project, user: @current_user) .incremental(@pipelines, @last_updated), - updated_at: Time.now, + updated_at: Time.now.utc, count: { all: @pipelines_count, running_or_pending: @running_or_pending_count diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 37c2c86e3a3..db573fb6562 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -21,8 +21,6 @@ module Ci after_create :keep_around_commits, unless: :importing? - delegate :stages, to: :statuses - state_machine :status, initial: :created do event :enqueue do transition created: :pending @@ -102,15 +100,19 @@ module Ci where.not(duration: nil).sum(:duration) end - def stages + def stages_query statuses.group('stage').select(:stage) .order('max(stage_idx)') end + def stages + self.stages_query.pluck(:stage) + end + def stages_with_statuses status_sql = statuses.latest.where('stage=sg.stage').status_sql - stages_with_statuses = CommitStatus.from(self.stages, :sg). + stages_with_statuses = CommitStatus.from(self.stages_query, :sg). pluck('sg.stage', status_sql) stages_with_statuses.map do |stage| diff --git a/app/views/projects/ci/pipelines/_pipeline.html.haml b/app/views/projects/ci/pipelines/_pipeline.html.haml index 50817f28d78..41189724f65 100644 --- a/app/views/projects/ci/pipelines/_pipeline.html.haml +++ b/app/views/projects/ci/pipelines/_pipeline.html.haml @@ -41,16 +41,13 @@ - else Cant find HEAD commit for this branch - - stages_status = pipeline.statuses.latest.stages_status %td.stage-cell - - pipeline.statuses.latest.stages_status.each do |stage| - - name = stage.first - - status = stage.last - - tooltip = "#{name.titleize}: #{status || 'not found'}" - - if status + - pipeline.stages_with_statuses.each do |stage| + - if stage.status + - tooltip = "#{stage.name.titleize}: #{stage.status || 'not found'}" .stage-container - = link_to namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id, anchor: stage), class: "has-tooltip ci-status-icon-#{status}", title: tooltip do - = ci_icon_for_status(status) + = link_to namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id, anchor: stage.name), class: "has-tooltip ci-status-icon-#{stage.status}", title: tooltip do + = ci_icon_for_status(stage.status) %td - if pipeline.duration -- cgit v1.2.1 From 2b9a9e37dcb08af85f57508808243deec21eaa2f Mon Sep 17 00:00:00 2001 From: Regis Date: Tue, 15 Nov 2016 07:53:46 -0700 Subject: prep for testing - update all pipeline api response attributes --- .../javascripts/vue_pipelines_index/index.js.es6 | 2 +- .../vue_pipelines_index/pipeline_actions.js.es6 | 4 ++-- .../javascripts/vue_pipelines_index/store.js.es6 | 19 ++++++++++++++++++- 3 files changed, 21 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/index.js.es6 b/app/assets/javascripts/vue_pipelines_index/index.js.es6 index ab53b12d3d0..90c8b47062c 100644 --- a/app/assets/javascripts/vue_pipelines_index/index.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/index.js.es6 @@ -1,5 +1,5 @@ /* global Vue, VueResource, gl */ -/* eslint-disable no-bitwise*/ +/* eslint-disable no-bitwise, no-plusplus*/ //= require vue-resource diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 index 223fcce62d8..1e81862ec83 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 @@ -33,7 +33,7 @@ diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index d8058386898..c1c153b0604 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -35,7 +35,7 @@ gl.PipelineStore = class { fetchDataLoop(Vue, pageNum, url) { Vue.activeResources = 0; - const updateNumberOfPipelines = (total, running) => { + const updatePipelineNums = (total, running) => { document.querySelector('.js-totalbuilds-count').innerHTML = total; document.querySelector('.js-running-count').innerHTML = running; }; @@ -55,7 +55,7 @@ Vue.set(this, 'updatedAt', res.updated_at); Vue.set(this, 'pipelines', res.pipelines); Vue.set(this, 'count', res.count); - updateNumberOfPipelines(this.count.all, this.count.running_or_pending); + updatePipelineNums(this.count.all, this.count.running_or_pending); this.pageRequest = false; Vue.activeResources -= 1; }, () => new Flash( @@ -70,7 +70,7 @@ Vue.set(this, 'updatedAt', res.updated_at); Vue.set(this, 'pipelines', p.updatePipelines(res)); Vue.set(this, 'count', res.count); - updateNumberOfPipelines(this.count.all, this.count.running_or_pending); + updatePipelineNums(this.count.all, this.count.running_or_pending); Vue.activeResources -= 1; }, () => new Flash( 'Something went wrong on our end.' -- cgit v1.2.1 From fc5eb253dbd1fac0674c1a164847dabfd1229c9e Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 17 Nov 2016 12:06:45 -0700 Subject: refactor store --- app/assets/javascripts/vue_pipelines_index/store.js.es6 | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index c1c153b0604..8226aef9c05 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -34,7 +34,13 @@ gl.PipelineStore = class { fetchDataLoop(Vue, pageNum, url) { - Vue.activeResources = 0; + const setVueResources = () => { Vue.activeResources = 1; }; + const resetVueResources = () => { Vue.activeResources = 0; }; + const addToVueResources = () => { Vue.activeResources += 1; }; + const subtractFromVueResources = () => { Vue.activeResources -= 1; }; + + resetVueResources(); // set Vue.resources to 0 + const updatePipelineNums = (total, running) => { document.querySelector('.js-totalbuilds-count').innerHTML = total; document.querySelector('.js-running-count').innerHTML = running; @@ -42,9 +48,9 @@ const resourceChecker = () => { if (Vue.activeResources === 0) { - Vue.activeResources = 1; + setVueResources(); } else { - Vue.activeResources += 1; + addToVueResources(); } }; @@ -57,7 +63,7 @@ Vue.set(this, 'count', res.count); updatePipelineNums(this.count.all, this.count.running_or_pending); this.pageRequest = false; - Vue.activeResources -= 1; + subtractFromVueResources(); }, () => new Flash( 'Something went wrong on our end.' )); @@ -71,7 +77,7 @@ Vue.set(this, 'pipelines', p.updatePipelines(res)); Vue.set(this, 'count', res.count); updatePipelineNums(this.count.all, this.count.running_or_pending); - Vue.activeResources -= 1; + subtractFromVueResources(); }, () => new Flash( 'Something went wrong on our end.' )); -- cgit v1.2.1 From 8c1a01e05fd3c6e1621242aaf31a0ce2789ad546 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 18 Nov 2016 03:48:23 +0800 Subject: We never check user privilege if it's a deploy key --- app/models/user.rb | 4 ---- 1 file changed, 4 deletions(-) (limited to 'app') diff --git a/app/models/user.rb b/app/models/user.rb index 40130b8b25c..5a2b232c4ed 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -501,10 +501,6 @@ class User < ActiveRecord::Base several_namespaces? || admin end - def has_access_to?(project) - can?(:read_project, project) - end - def can?(action, subject) Ability.allowed?(self, action, subject) end -- cgit v1.2.1 From af0242b3d604cc14302f91f0dbe75af0048862d7 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 18 Nov 2016 03:56:35 +0800 Subject: We removed User#has_access_to? --- app/helpers/projects_helper.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 144ac7a0d02..77075e49b17 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -93,7 +93,9 @@ module ProjectsHelper if deploy_key.has_access_to?(@project) @project else - deploy_key.projects.find(¤t_user.method(:has_access_to?)) + deploy_key.projects.find do |project| + can?(current_user, :read_project, project) + end end end -- cgit v1.2.1 From 398be9cadd5c50c1de3d31facba7e62d54437f37 Mon Sep 17 00:00:00 2001 From: Regis Date: Fri, 18 Nov 2016 08:10:32 -0600 Subject: performance and diff updates --- app/assets/javascripts/vue_pipelines_index/store.js.es6 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index 8226aef9c05..053a068396f 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -7,7 +7,7 @@ this.pipelines = pipelines; this.updateClone = (update, newPipe) => { update.forEach((pipe) => { - if (pipe.id === newPipe.id) pipe = Object.assign(pipe, newPipe); + if (pipe.id === newPipe.id) pipe = Object.assign({}, pipe, newPipe); }); }; } @@ -20,7 +20,7 @@ } updatePipelines(apiResponse) { - const update = this.pipelines.map(e => e); + const update = this.pipelines.slice(0); apiResponse.pipelines.forEach((newPipe) => { if (newPipe.commit) { update.unshift(newPipe); -- cgit v1.2.1 From 061b4dd82a0736cf9b92d4633c3ef5af61a11cc3 Mon Sep 17 00:00:00 2001 From: Regis Date: Fri, 18 Nov 2016 11:33:51 -0600 Subject: much more performant pageSlicer - [ci skip] --- app/assets/javascripts/vue_pipelines_index/store.js.es6 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index 053a068396f..396114e05b6 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -13,10 +13,8 @@ } currentPageSlicer(update) { - const length = update.length; - if (this.pipelines.length === update.length) return update; if (update.length <= 30) return update; - return update.slice(0, (length - 1)); + return update.slice(0, 29); } updatePipelines(apiResponse) { -- cgit v1.2.1 From 758cdf54fe61ff7e62c9e3aac70819fb824a8b5c Mon Sep 17 00:00:00 2001 From: Regis Date: Fri, 18 Nov 2016 11:35:35 -0600 Subject: no this - define in constructor - [ci skip] --- app/assets/javascripts/vue_pipelines_index/store.js.es6 | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index 396114e05b6..ffe6292782a 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -10,11 +10,10 @@ if (pipe.id === newPipe.id) pipe = Object.assign({}, pipe, newPipe); }); }; - } - - currentPageSlicer(update) { - if (update.length <= 30) return update; - return update.slice(0, 29); + this.currentPageSlicer = (update) => { + if (update.length <= 30) return update; + return update.slice(0, 29); + }; } updatePipelines(apiResponse) { -- cgit v1.2.1 From d0a5428a3865f59814528fd950a1e00ccb65af3d Mon Sep 17 00:00:00 2001 From: Regis Date: Fri, 18 Nov 2016 16:26:49 -0600 Subject: constant variable hardcoding --- app/assets/javascripts/vue_pagination/index.js.es6 | 32 ++++++++++++++-------- .../javascripts/vue_pipelines_index/index.js.es6 | 2 +- .../vue_pipelines_index/pipelines.js.es6 | 18 ++++++++---- .../javascripts/vue_pipelines_index/store.js.es6 | 7 +++-- 4 files changed, 39 insertions(+), 20 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pagination/index.js.es6 b/app/assets/javascripts/vue_pagination/index.js.es6 index 5f844ae8923..4f83671e83d 100644 --- a/app/assets/javascripts/vue_pagination/index.js.es6 +++ b/app/assets/javascripts/vue_pagination/index.js.es6 @@ -2,6 +2,14 @@ /* eslint-disable no-param-reassign, no-plusplus */ ((gl) => { + const PAGINATION_SIZE = 30; + const PAGINATION_UI_BUTTON_LIMIT = 4; + const SPREAD = '...'; + const PREV = 'Prev'; + const NEXT = 'Next'; + const FIRST = '<< First'; + const LAST = 'Last >>'; + gl.VueGlPagination = Vue.extend({ props: [ 'changepage', @@ -10,40 +18,42 @@ ], computed: { last() { - return Math.ceil(+this.count / 30); + return Math.ceil(+this.count / PAGINATION_SIZE); }, getItems() { const total = +this.last; const page = +this.pagenum; const items = []; - if (page > 1) items.push({ title: '<< First', where: 1 }); + if (page > 1) items.push({ title: FIRST, where: 1 }); if (page > 1) { - items.push({ title: 'Prev', where: page - 1 }); + items.push({ title: PREV, where: page - 1 }); } else { - items.push({ title: 'Prev', where: page - 1, disabled: true }); + items.push({ title: PREV, where: page - 1, disabled: true }); } - if (page > 6) items.push({ title: '...', separator: true }); + if (page > 6) items.push({ title: SPREAD, separator: true }); - const start = Math.max(page - 4, 1); - const end = Math.min(page + 4, total); + const start = Math.max(page - PAGINATION_UI_BUTTON_LIMIT, 1); + const end = Math.min(page + PAGINATION_UI_BUTTON_LIMIT, total); for (let i = start; i <= end; i++) { const isActive = i === page; items.push({ title: i, active: isActive, where: i }); } - if (total - page > 4) items.push({ title: '...', separator: true }); + if (total - page > PAGINATION_UI_BUTTON_LIMIT) { + items.push({ title: SPREAD, separator: true }); + } if (page === total) { - items.push({ title: 'Next', where: page + 1, disabled: true }); + items.push({ title: NEXT, where: page + 1, disabled: true }); } else if (total - page >= 1) { - items.push({ title: 'Next', where: page + 1 }); + items.push({ title: NEXT, where: page + 1 }); } - if (total - page >= 1) items.push({ title: 'Last >>', where: total }); + if (total - page >= 1) items.push({ title: LAST, where: total }); return items; }, diff --git a/app/assets/javascripts/vue_pipelines_index/index.js.es6 b/app/assets/javascripts/vue_pipelines_index/index.js.es6 index 57afce34c2b..1584345098c 100644 --- a/app/assets/javascripts/vue_pipelines_index/index.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/index.js.es6 @@ -29,7 +29,7 @@ store: new gl.PipelineStore(), }, components: { - 'vue-pipelines': gl.VuePipeLines, + 'vue-pipelines': gl.VuePipelines, }, template: `
    diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index b86a4c6f81b..09c480457c4 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -2,7 +2,13 @@ /* eslint-disable no-param-reassign, no-bitwise*/ ((gl) => { - gl.VuePipeLines = Vue.extend({ + const SPREAD = '...'; + const PREV = 'Prev'; + const NEXT = 'Next'; + const FIRST = '<< First'; + const LAST = 'Last >>'; + + gl.VuePipelines = Vue.extend({ components: { runningPipeline: gl.VueRunningPipeline, pipelineActions: gl.VuePipelineActions, @@ -41,12 +47,12 @@ methods: { changepage(e, last) { const text = e.target.innerText; - if (text === '...') return; + if (text === SPREAD) return; if (/^-?[\d.]+(?:e-?\d+)?$/.test(text)) this.pagenum = +text; - if (text === 'Last >>') this.pagenum = last; - if (text === 'Next') this.pagenum = +this.pagenum + 1; - if (text === 'Prev') this.pagenum = +this.pagenum - 1; - if (text === '<< First') this.pagenum = 1; + if (text === LAST) this.pagenum = last; + if (text === NEXT) this.pagenum = +this.pagenum + 1; + if (text === PREV) this.pagenum = +this.pagenum - 1; + if (text === FIRST) this.pagenum = 1; window.history.pushState({}, null, `?p=${this.pagenum}`); clearInterval(this.intervalId); diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index ffe6292782a..ada99b67f26 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -2,6 +2,9 @@ /* eslint-disable no-param-reassign */ ((gl) => { + const PAGINATION_LIMIT = 31; + const SLICE_LIMIT = 29; + class PipelineUpdater { constructor(pipelines) { this.pipelines = pipelines; @@ -11,8 +14,8 @@ }); }; this.currentPageSlicer = (update) => { - if (update.length <= 30) return update; - return update.slice(0, 29); + if (update.length < PAGINATION_LIMIT) return update; + return update.slice(0, SLICE_LIMIT); }; } -- cgit v1.2.1 From ff4edf37f3d8e7742292db6d5e50ba6f599950ff Mon Sep 17 00:00:00 2001 From: Regis Date: Fri, 18 Nov 2016 16:33:41 -0600 Subject: this.count as only param for updatePipelineNums - [ci skip] --- app/assets/javascripts/vue_pipelines_index/store.js.es6 | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index ada99b67f26..0bf59823c11 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -41,8 +41,11 @@ resetVueResources(); // set Vue.resources to 0 - const updatePipelineNums = (total, running) => { - document.querySelector('.js-totalbuilds-count').innerHTML = total; + const updatePipelineNums = (count) => { + const { all } = count; + // cannot define non camel case, so not using destructuring for running + const running = count.running_or_pending; + document.querySelector('.js-totalbuilds-count').innerHTML = all; document.querySelector('.js-running-count').innerHTML = running; }; @@ -61,7 +64,7 @@ Vue.set(this, 'updatedAt', res.updated_at); Vue.set(this, 'pipelines', res.pipelines); Vue.set(this, 'count', res.count); - updatePipelineNums(this.count.all, this.count.running_or_pending); + updatePipelineNums(this.count); this.pageRequest = false; subtractFromVueResources(); }, () => new Flash( @@ -76,7 +79,7 @@ Vue.set(this, 'updatedAt', res.updated_at); Vue.set(this, 'pipelines', p.updatePipelines(res)); Vue.set(this, 'count', res.count); - updatePipelineNums(this.count.all, this.count.running_or_pending); + updatePipelineNums(this.count); subtractFromVueResources(); }, () => new Flash( 'Something went wrong on our end.' -- cgit v1.2.1 From 721f2d3788ae5e8374f357014bd9e20d62de0a81 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 21 Nov 2016 22:19:16 +0800 Subject: Still use compound pipeline status, but group by ref and sha so that it would show latest pipeline if ref and sha are both specified, otherwise still the same as before. --- app/models/ci/pipeline.rb | 16 +++++++++++++--- app/models/commit.rb | 8 +------- app/services/ci/image_for_build_service.rb | 11 ++--------- 3 files changed, 16 insertions(+), 19 deletions(-) (limited to 'app') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index cd7d8fd3af7..e566503bb18 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -89,13 +89,23 @@ module Ci end end - scope :latest, -> { order(id: :desc) } + scope :latest, -> do + max_id = unscope(:select).select("max(#{quoted_table_name}.id)") + + where(id: max_id.group(:ref, :sha)) + end # ref can't be HEAD or SHA, can only be branch/tag name - scope :latest_for, ->(ref) { where(ref: ref).latest } + scope :latest_for, ->(ref) do + if ref + where(ref: ref) + else + self + end.latest + end def self.latest_successful_for(ref) - latest_for(ref).success.first + where(ref: ref).order(id: :desc).success.first end def self.truncate_sha(sha) diff --git a/app/models/commit.rb b/app/models/commit.rb index 2134ba2d75f..b588b93b158 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -234,13 +234,7 @@ class Commit return @statuses[ref] if @statuses.key?(ref) - latest_pipeline = if ref - pipelines.latest_for(ref) - else - pipelines.latest - end.first - - @statuses[ref] = latest_pipeline.try(:status) + @statuses[ref] = pipelines.latest_for(ref).status end def revert_branch_name diff --git a/app/services/ci/image_for_build_service.rb b/app/services/ci/image_for_build_service.rb index 026a727a8f9..d5a07ef630b 100644 --- a/app/services/ci/image_for_build_service.rb +++ b/app/services/ci/image_for_build_service.rb @@ -3,18 +3,11 @@ module Ci def execute(project, opts) ref = opts[:ref] sha = opts[:sha] || ref_sha(project, ref) - pipelines = project.pipelines.where(sha: sha) - latest_pipeline = if ref - pipelines.latest_for(ref) - else - pipelines.latest - end.first - - image_name = image_for_status(latest_pipeline.try(:status)) - + image_name = image_for_status(pipelines.latest_for(ref).status) image_path = Rails.root.join('public/ci', image_name) + OpenStruct.new(path: image_path, name: image_name) end -- cgit v1.2.1 From dd6b16a111a6e6cce0be322be8ddba17a2a30534 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 21 Nov 2016 22:24:09 +0800 Subject: Use latest_for in latest_successful_for --- app/models/ci/pipeline.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index e566503bb18..95af8c72309 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -105,7 +105,7 @@ module Ci end def self.latest_successful_for(ref) - where(ref: ref).order(id: :desc).success.first + latest_for(ref).success.first end def self.truncate_sha(sha) -- cgit v1.2.1 From 66301ce274b42cefe76e343a3d545c8f12d847b2 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 22 Nov 2016 01:48:41 +0800 Subject: Filter against status first, otherwise we can't find the latest successful one if the last one is failed and we already exclude the others. --- app/models/ci/pipeline.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 95af8c72309..61d9316a5d3 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -105,7 +105,7 @@ module Ci end def self.latest_successful_for(ref) - latest_for(ref).success.first + success.latest_for(ref).first end def self.truncate_sha(sha) -- cgit v1.2.1 From 56cb4762d42f758ad6e4ec1874b7eed8e1c1f687 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 22 Aug 2016 16:02:48 -0300 Subject: Refactoring Bitbucket import controller to use the new OAuth2 client --- app/controllers/import/bitbucket_controller.rb | 77 ++++++++++++++------------ app/views/import/bitbucket/status.html.haml | 35 ++++++------ 2 files changed, 61 insertions(+), 51 deletions(-) (limited to 'app') diff --git a/app/controllers/import/bitbucket_controller.rb b/app/controllers/import/bitbucket_controller.rb index 6ea54744da8..ee30a24ab77 100644 --- a/app/controllers/import/bitbucket_controller.rb +++ b/app/controllers/import/bitbucket_controller.rb @@ -3,49 +3,54 @@ class Import::BitbucketController < Import::BaseController before_action :bitbucket_auth, except: :callback rescue_from OAuth::Error, with: :bitbucket_unauthorized - rescue_from Gitlab::BitbucketImport::Client::Unauthorized, with: :bitbucket_unauthorized + rescue_from Bitbucket::Error::Unauthorized, with: :bitbucket_unauthorized def callback - request_token = session.delete(:oauth_request_token) - raise "Session expired!" if request_token.nil? + response = client.auth_code.get_token(params[:code], redirect_uri: callback_import_bitbucket_url) - request_token.symbolize_keys! - - access_token = client.get_token(request_token, params[:oauth_verifier], callback_import_bitbucket_url) - - session[:bitbucket_access_token] = access_token.token - session[:bitbucket_access_token_secret] = access_token.secret + session[:bitbucket_token] = response.token + session[:bitbucket_expires_at] = response.expires_at + session[:bitbucket_expires_in] = response.expires_in + session[:bitbucket_refresh_token] = response.refresh_token redirect_to status_import_bitbucket_url end def status - @repos = client.projects - @incompatible_repos = client.incompatible_projects + client = Bitbucket::Client.new(credentials) + repos = client.repos + + @repos = repos.select(&:valid?) + @incompatible_repos = repos.reject(&:valid?) - @already_added_projects = current_user.created_projects.where(import_type: "bitbucket") + @already_added_projects = current_user.created_projects.where(import_type: 'bitbucket') already_added_projects_names = @already_added_projects.pluck(:import_source) - @repos.to_a.reject!{ |repo| already_added_projects_names.include? "#{repo["owner"]}/#{repo["slug"]}" } + @repos.to_a.reject! { |repo| already_added_projects_names.include?(repo.full_name) } end def jobs - jobs = current_user.created_projects.where(import_type: "bitbucket").to_json(only: [:id, :import_status]) - render json: jobs + render json: current_user.created_projects + .where(import_type: 'bitbucket') + .to_json(only: [:id, :import_status]) end def create + client = Bitbucket::Client.new(credentials) + @repo_id = params[:repo_id].to_s - repo = client.project(@repo_id.gsub('___', '/')) - @project_name = repo['slug'] - @target_namespace = find_or_create_namespace(repo['owner'], client.user['user']['username']) + name = @repo_id.to_s.gsub('___', '/') + repo = client.repo(name) + @project_name = repo.name - unless Gitlab::BitbucketImport::KeyAdder.new(repo, current_user, access_params).execute - render 'deploy_key' and return - end + repo_owner = repo.owner + repo_owner = current_user.username if repo_owner == client.user.username + @target_namespace = params[:new_namespace].presence || repo_owner + + namespace = find_or_create_namespace(target_namespace_name, repo_owner) if current_user.can?(:create_projects, @target_namespace) - @project = Gitlab::BitbucketImport::ProjectCreator.new(repo, @target_namespace, current_user, access_params).execute + @project = Gitlab::BitbucketImport::ProjectCreator.new(repo, namespace, current_user, credentials).execute else render 'unauthorized' end @@ -54,8 +59,15 @@ class Import::BitbucketController < Import::BaseController private def client - @client ||= Gitlab::BitbucketImport::Client.new(session[:bitbucket_access_token], - session[:bitbucket_access_token_secret]) + @client ||= OAuth2::Client.new(provider.app_id, provider.app_secret, options) + end + + def provider + Gitlab.config.omniauth.providers.find { |provider| provider.name == 'bitbucket' } + end + + def options + OmniAuth::Strategies::Bitbucket.default_options[:client_options].deep_symbolize_keys end def verify_bitbucket_import_enabled @@ -63,26 +75,23 @@ class Import::BitbucketController < Import::BaseController end def bitbucket_auth - if session[:bitbucket_access_token].blank? - go_to_bitbucket_for_permissions - end + go_to_bitbucket_for_permissions if session[:bitbucket_token].blank? end def go_to_bitbucket_for_permissions - request_token = client.request_token(callback_import_bitbucket_url) - session[:oauth_request_token] = request_token - - redirect_to client.authorize_url(request_token, callback_import_bitbucket_url) + redirect_to client.auth_code.authorize_url(redirect_uri: callback_import_bitbucket_url) end def bitbucket_unauthorized go_to_bitbucket_for_permissions end - def access_params + def credentials { - bitbucket_access_token: session[:bitbucket_access_token], - bitbucket_access_token_secret: session[:bitbucket_access_token_secret] + token: session[:bitbucket_token], + expires_at: session[:bitbucket_expires_at], + expires_in: session[:bitbucket_expires_in], + refresh_token: session[:bitbucket_refresh_token] } end end diff --git a/app/views/import/bitbucket/status.html.haml b/app/views/import/bitbucket/status.html.haml index f8b4b107513..e62ff5f61f6 100644 --- a/app/views/import/bitbucket/status.html.haml +++ b/app/views/import/bitbucket/status.html.haml @@ -1,5 +1,6 @@ -- page_title "Bitbucket import" -- header_title "Projects", root_path +- page_title 'Bitbucket import' +- header_title 'Projects', root_path + %h3.page-title %i.fa.fa-bitbucket Import projects from Bitbucket @@ -10,13 +11,13 @@ %hr %p - if @incompatible_repos.any? - = button_tag class: "btn btn-import btn-success js-import-all" do + = button_tag class: 'btn btn-import btn-success js-import-all' do Import all compatible projects - = icon("spinner spin", class: "loading-icon") + = icon('spinner spin', class: 'loading-icon') - else - = button_tag class: "btn btn-success js-import-all" do + = button_tag class: 'btn btn-success js-import-all' do Import all projects - = icon("spinner spin", class: "loading-icon") + = icon('spinner spin', class: 'loading-icon') .table-responsive %table.table.import-jobs @@ -32,7 +33,7 @@ - @already_added_projects.each do |project| %tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"} %td - = link_to project.import_source, "https://bitbucket.org/#{project.import_source}", target: "_blank" + = link_to project.import_source, 'https://bitbucket.org/#{project.import_source}', target: '_blank' %td = link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project] %td.job-status @@ -47,31 +48,31 @@ = project.human_import_status_name - @repos.each do |repo| - %tr{id: "repo_#{repo["owner"]}___#{repo["slug"]}"} + %tr{id: "repo_#{repo.owner}___#{repo.slug}"} %td - = link_to "#{repo["owner"]}/#{repo["slug"]}", "https://bitbucket.org/#{repo["owner"]}/#{repo["slug"]}", target: "_blank" + = link_to "#{repo.full_name}", "https://bitbucket.org/#{repo.full_name}", target: "_blank" %td.import-target - = import_project_target(repo['owner'], repo['slug']) + = "#{repo.full_name}" %td.import-actions.job-status - = button_tag class: "btn btn-import js-add-to-import" do + = button_tag class: 'btn btn-import js-add-to-import' do Import - = icon("spinner spin", class: "loading-icon") + = icon('spinner spin', class: 'loading-icon') - @incompatible_repos.each do |repo| - %tr{id: "repo_#{repo["owner"]}___#{repo["slug"]}"} + %tr{id: "repo_#{repo.owner}___#{repo.slug}"} %td - = link_to "#{repo["owner"]}/#{repo["slug"]}", "https://bitbucket.org/#{repo["owner"]}/#{repo["slug"]}", target: "_blank" + = link_to "#{repo.full_name}", "https://bitbucket.org/#{repo.full_name}", target: '_blank' %td.import-target %td.import-actions-job-status - = label_tag "Incompatible Project", nil, class: "label label-danger" + = label_tag 'Incompatible Project', nil, class: 'label label-danger' - if @incompatible_repos.any? %p One or more of your Bitbucket projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git. Please convert - = link_to "them to Git,", "https://www.atlassian.com/git/tutorials/migrating-overview" + = link_to 'them to Git,', 'https://www.atlassian.com/git/tutorials/migrating-overview' and go through the - = link_to "import flow", status_import_bitbucket_path, "data-no-turbolink" => "true" + = link_to 'import flow', status_import_bitbucket_path, 'data-no-turbolink' => 'true' again. .js-importer-status{ data: { jobs_import_path: "#{jobs_import_bitbucket_path}", import_path: "#{import_bitbucket_path}" } } -- cgit v1.2.1 From 267e27b0cd543e8eeaa04686ad4678c4f553c479 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 22 Aug 2016 16:05:44 -0300 Subject: Remove code to clone Bitbucket repositories using SSH --- app/controllers/application_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 517ad4f03f3..a6b0a4af503 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -254,7 +254,7 @@ class ApplicationController < ActionController::Base end def bitbucket_import_configured? - Gitlab::OAuth::Provider.enabled?(:bitbucket) && Gitlab::BitbucketImport.public_key.present? + Gitlab::OAuth::Provider.enabled?(:bitbucket) end def google_code_import_enabled? -- cgit v1.2.1 From a0959430516f57ad27df21447777ebb226890647 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Fri, 11 Nov 2016 14:00:33 -0800 Subject: Fix rebase failures with Bitbucket changes --- app/controllers/import/bitbucket_controller.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/controllers/import/bitbucket_controller.rb b/app/controllers/import/bitbucket_controller.rb index ee30a24ab77..5326dce4ebb 100644 --- a/app/controllers/import/bitbucket_controller.rb +++ b/app/controllers/import/bitbucket_controller.rb @@ -47,9 +47,9 @@ class Import::BitbucketController < Import::BaseController repo_owner = current_user.username if repo_owner == client.user.username @target_namespace = params[:new_namespace].presence || repo_owner - namespace = find_or_create_namespace(target_namespace_name, repo_owner) + namespace = find_or_create_namespace(@target_namespace, repo_owner) - if current_user.can?(:create_projects, @target_namespace) + if current_user.can?(:create_projects, namespace) @project = Gitlab::BitbucketImport::ProjectCreator.new(repo, namespace, current_user, credentials).execute else render 'unauthorized' -- cgit v1.2.1 From 478730bebd5c8a9505490d2b396ac3c866da1b09 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Fri, 11 Nov 2016 14:44:31 -0800 Subject: Support selection of different namespace and project destination --- app/controllers/import/bitbucket_controller.rb | 6 +++--- app/views/import/bitbucket/status.html.haml | 14 ++++++++++++-- 2 files changed, 15 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/controllers/import/bitbucket_controller.rb b/app/controllers/import/bitbucket_controller.rb index 5326dce4ebb..e7150cb8e95 100644 --- a/app/controllers/import/bitbucket_controller.rb +++ b/app/controllers/import/bitbucket_controller.rb @@ -39,9 +39,9 @@ class Import::BitbucketController < Import::BaseController client = Bitbucket::Client.new(credentials) @repo_id = params[:repo_id].to_s - name = @repo_id.to_s.gsub('___', '/') + name = @repo_id.gsub('___', '/') repo = client.repo(name) - @project_name = repo.name + @project_name = params[:new_name].presence || repo.name repo_owner = repo.owner repo_owner = current_user.username if repo_owner == client.user.username @@ -50,7 +50,7 @@ class Import::BitbucketController < Import::BaseController namespace = find_or_create_namespace(@target_namespace, repo_owner) if current_user.can?(:create_projects, namespace) - @project = Gitlab::BitbucketImport::ProjectCreator.new(repo, namespace, current_user, credentials).execute + @project = Gitlab::BitbucketImport::ProjectCreator.new(repo, @project_name, namespace, current_user, credentials).execute else render 'unauthorized' end diff --git a/app/views/import/bitbucket/status.html.haml b/app/views/import/bitbucket/status.html.haml index e62ff5f61f6..cc262e97ceb 100644 --- a/app/views/import/bitbucket/status.html.haml +++ b/app/views/import/bitbucket/status.html.haml @@ -15,7 +15,7 @@ Import all compatible projects = icon('spinner spin', class: 'loading-icon') - else - = button_tag class: 'btn btn-success js-import-all' do + = button_tag class: 'btn btn-import btn-success js-import-all' do Import all projects = icon('spinner spin', class: 'loading-icon') @@ -52,7 +52,17 @@ %td = link_to "#{repo.full_name}", "https://bitbucket.org/#{repo.full_name}", target: "_blank" %td.import-target - = "#{repo.full_name}" + %fieldset.row + .input-group + .project-path.input-group-btn + - if current_user.can_select_namespace? + - selected = params[:namespace_id] || :current_user + - opts = current_user.can_create_group? ? { extra_group: Group.new(name: repo.owner, path: repo.owner) } : {} + = select_tag :namespace_id, namespaces_options(selected, opts.merge({ display_path: true })), { class: 'select2 js-select-namespace', tabindex: 1 } + - else + = text_field_tag :path, current_user.namespace_path, class: "input-large form-control", tabindex: 1, disabled: true + %span.input-group-addon / + = text_field_tag :path, repo.name, class: "input-mini form-control", tabindex: 2, autofocus: true, required: true %td.import-actions.job-status = button_tag class: 'btn btn-import js-add-to-import' do Import -- cgit v1.2.1 From e2688feeb3075265fb926bbd68560b2046afa0c5 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Fri, 11 Nov 2016 15:44:52 -0800 Subject: Address initial review comments --- app/controllers/import/bitbucket_controller.rb | 13 ++++++------- app/views/import/bitbucket/status.html.haml | 6 +++--- 2 files changed, 9 insertions(+), 10 deletions(-) (limited to 'app') diff --git a/app/controllers/import/bitbucket_controller.rb b/app/controllers/import/bitbucket_controller.rb index e7150cb8e95..72c90f9daf2 100644 --- a/app/controllers/import/bitbucket_controller.rb +++ b/app/controllers/import/bitbucket_controller.rb @@ -17,11 +17,10 @@ class Import::BitbucketController < Import::BaseController end def status - client = Bitbucket::Client.new(credentials) - repos = client.repos + bitbucket_client = Bitbucket::Client.new(credentials) + repos = bitbucket_client.repos - @repos = repos.select(&:valid?) - @incompatible_repos = repos.reject(&:valid?) + @repos, @incompatible_repos = repos.partition { |repo| repo.valid? } @already_added_projects = current_user.created_projects.where(import_type: 'bitbucket') already_added_projects_names = @already_added_projects.pluck(:import_source) @@ -36,15 +35,15 @@ class Import::BitbucketController < Import::BaseController end def create - client = Bitbucket::Client.new(credentials) + bitbucket_client = Bitbucket::Client.new(credentials) @repo_id = params[:repo_id].to_s name = @repo_id.gsub('___', '/') - repo = client.repo(name) + repo = bitbucket_client.repo(name) @project_name = params[:new_name].presence || repo.name repo_owner = repo.owner - repo_owner = current_user.username if repo_owner == client.user.username + repo_owner = current_user.username if repo_owner == bitbucket_client.user.username @target_namespace = params[:new_namespace].presence || repo_owner namespace = find_or_create_namespace(@target_namespace, repo_owner) diff --git a/app/views/import/bitbucket/status.html.haml b/app/views/import/bitbucket/status.html.haml index cc262e97ceb..ac09b71ae89 100644 --- a/app/views/import/bitbucket/status.html.haml +++ b/app/views/import/bitbucket/status.html.haml @@ -33,7 +33,7 @@ - @already_added_projects.each do |project| %tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"} %td - = link_to project.import_source, 'https://bitbucket.org/#{project.import_source}', target: '_blank' + = link_to project.import_source, "https://bitbucket.org/#{project.import_source}", target: '_blank' %td = link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project] %td.job-status @@ -50,7 +50,7 @@ - @repos.each do |repo| %tr{id: "repo_#{repo.owner}___#{repo.slug}"} %td - = link_to "#{repo.full_name}", "https://bitbucket.org/#{repo.full_name}", target: "_blank" + = link_to repo.full_name, "https://bitbucket.org/#{repo.full_name}", target: "_blank" %td.import-target %fieldset.row .input-group @@ -70,7 +70,7 @@ - @incompatible_repos.each do |repo| %tr{id: "repo_#{repo.owner}___#{repo.slug}"} %td - = link_to "#{repo.full_name}", "https://bitbucket.org/#{repo.full_name}", target: '_blank' + = link_to repo.full_name, "https://bitbucket.org/#{repo.full_name}", target: '_blank' %td.import-target %td.import-actions-job-status = label_tag 'Incompatible Project', nil, class: 'label label-danger' -- cgit v1.2.1 From 7953480646b5b129868e4323502a28ce27328d8c Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sun, 20 Nov 2016 22:29:45 -0800 Subject: Fix remaining Bitbucket controller specs --- app/controllers/import/bitbucket_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/controllers/import/bitbucket_controller.rb b/app/controllers/import/bitbucket_controller.rb index 72c90f9daf2..9c97a97a5dd 100644 --- a/app/controllers/import/bitbucket_controller.rb +++ b/app/controllers/import/bitbucket_controller.rb @@ -46,7 +46,7 @@ class Import::BitbucketController < Import::BaseController repo_owner = current_user.username if repo_owner == bitbucket_client.user.username @target_namespace = params[:new_namespace].presence || repo_owner - namespace = find_or_create_namespace(@target_namespace, repo_owner) + namespace = find_or_create_namespace(@target_namespace, current_user) if current_user.can?(:create_projects, namespace) @project = Gitlab::BitbucketImport::ProjectCreator.new(repo, @project_name, namespace, current_user, credentials).execute -- cgit v1.2.1 From 28102ec28e1ef3d3203db3d05aa89ab3da234e70 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 22 Nov 2016 16:06:42 +0800 Subject: Allow admin to set keys with write access, and show write access information when showing the key. TODO: It's ugly right now, need help! --- app/controllers/admin/deploy_keys_controller.rb | 2 +- app/views/admin/deploy_keys/index.html.haml | 6 ++++++ app/views/admin/deploy_keys/new.html.haml | 8 ++++++++ app/views/projects/deploy_keys/_deploy_key.html.haml | 3 +++ 4 files changed, 18 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/controllers/admin/deploy_keys_controller.rb b/app/controllers/admin/deploy_keys_controller.rb index 6b146712940..4f6a7e9e2cb 100644 --- a/app/controllers/admin/deploy_keys_controller.rb +++ b/app/controllers/admin/deploy_keys_controller.rb @@ -39,6 +39,6 @@ class Admin::DeployKeysController < Admin::ApplicationController end def deploy_key_params - params.require(:deploy_key).permit(:key, :title) + params.require(:deploy_key).permit(:key, :title, :can_push) end end diff --git a/app/views/admin/deploy_keys/index.html.haml b/app/views/admin/deploy_keys/index.html.haml index 149593e7f46..dee611ae014 100644 --- a/app/views/admin/deploy_keys/index.html.haml +++ b/app/views/admin/deploy_keys/index.html.haml @@ -11,6 +11,7 @@ %tr %th Title %th Fingerprint + %th Write access %th Added at %th %tbody @@ -20,6 +21,11 @@ %strong= deploy_key.title %td %code.key-fingerprint= deploy_key.fingerprint + %td + - if deploy_key.can_push? + Yes + - else + No %td %span.cgray added #{time_ago_with_tooltip(deploy_key.created_at)} diff --git a/app/views/admin/deploy_keys/new.html.haml b/app/views/admin/deploy_keys/new.html.haml index 5c410a695bf..96055174ad0 100644 --- a/app/views/admin/deploy_keys/new.html.haml +++ b/app/views/admin/deploy_keys/new.html.haml @@ -16,6 +16,14 @@ Paste a machine public key here. Read more about how to generate it = link_to "here", help_page_path("ssh/README") = f.text_area :key, class: "form-control thin_area", rows: 5 + .form-group + .control-label + .col-sm-10 + = f.label :can_push do + = f.check_box :can_push + %strong Write access allowed? + %p.light.append-bottom-0 + Allow this key to push to repository as well? (Default only allows pull access.) .form-actions = f.submit 'Create', class: "btn-create btn" diff --git a/app/views/projects/deploy_keys/_deploy_key.html.haml b/app/views/projects/deploy_keys/_deploy_key.html.haml index 450aaeb367c..d360f1bab28 100644 --- a/app/views/projects/deploy_keys/_deploy_key.html.haml +++ b/app/views/projects/deploy_keys/_deploy_key.html.haml @@ -6,6 +6,9 @@ = deploy_key.title .description = deploy_key.fingerprint + - if deploy_key.can_push? + .can-write + Can write .deploy-key-content.prepend-left-default.deploy-key-projects - deploy_key.projects.each do |project| - if can?(current_user, :read_project, project) -- cgit v1.2.1 From cb35c5e1c9172a566e88ecc3be13fd35b6c3b8d0 Mon Sep 17 00:00:00 2001 From: Regis Date: Tue, 22 Nov 2016 13:36:45 -0600 Subject: stashing for now --- app/assets/javascripts/vue_pipelines_index/index.js.es6 | 2 ++ .../javascripts/vue_pipelines_index/pipelines.js.es6 | 17 +++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/index.js.es6 b/app/assets/javascripts/vue_pipelines_index/index.js.es6 index 1584345098c..2bd8d5d327f 100644 --- a/app/assets/javascripts/vue_pipelines_index/index.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/index.js.es6 @@ -1,6 +1,8 @@ /* global Vue, VueResource, gl */ /* eslint-disable no-bitwise, no-plusplus*/ +/*= require vue_common_component/commit */ + //= require vue-resource //= require ./object_assign.js.es6 diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index 09c480457c4..fd843844c7c 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -13,7 +13,7 @@ runningPipeline: gl.VueRunningPipeline, pipelineActions: gl.VuePipelineActions, stages: gl.VueStages, - branchCommit: gl.VueBranchCommit, + commit: gl.CommitComponent, pipelineUrl: gl.VuePipelineUrl, pipelineHead: gl.VuePipelineHead, glPagination: gl.VueGlPagination, @@ -59,6 +59,11 @@ this.pageRequest = true; this.store.fetchDataLoop.call(this, Vue, this.pagenum, this.scope); }, + author(pipeline) { + const author = pipeline.commit.author; + if (author) return author; + return ({}); + }, }, template: `
    @@ -72,7 +77,15 @@ - + + -- cgit v1.2.1 From 76ef4f02c36a3ca8f118e57d47f795000fa481f5 Mon Sep 17 00:00:00 2001 From: Regis Date: Tue, 22 Nov 2016 15:36:21 -0600 Subject: diff updates from API to DOM --- app/assets/javascripts/vue_pipelines_index/store.js.es6 | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index 0bf59823c11..16c4197dd66 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -8,27 +8,20 @@ class PipelineUpdater { constructor(pipelines) { this.pipelines = pipelines; - this.updateClone = (update, newPipe) => { - update.forEach((pipe) => { - if (pipe.id === newPipe.id) pipe = Object.assign({}, pipe, newPipe); - }); - }; - this.currentPageSlicer = (update) => { - if (update.length < PAGINATION_LIMIT) return update; - return update.slice(0, SLICE_LIMIT); - }; } updatePipelines(apiResponse) { const update = this.pipelines.slice(0); - apiResponse.pipelines.forEach((newPipe) => { + apiResponse.pipelines.forEach((newPipe, i) => { if (newPipe.commit) { update.unshift(newPipe); } else { - this.updateClone(update, newPipe); + const newMerge = Object.assign({}, update[i], newPipe); + update[i] = newMerge; } }); - return this.currentPageSlicer(update); + if (update.length < PAGINATION_LIMIT) return update; + return update.slice(0, SLICE_LIMIT); } } -- cgit v1.2.1 From d15a0b68643f09be4f8e61b45c479a200575c245 Mon Sep 17 00:00:00 2001 From: Regis Date: Tue, 22 Nov 2016 15:37:51 -0600 Subject: slight cleanup [ci skip] --- app/assets/javascripts/vue_pipelines_index/store.js.es6 | 1 - 1 file changed, 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index 16c4197dd66..836a6be9a40 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -36,7 +36,6 @@ const updatePipelineNums = (count) => { const { all } = count; - // cannot define non camel case, so not using destructuring for running const running = count.running_or_pending; document.querySelector('.js-totalbuilds-count').innerHTML = all; document.querySelector('.js-running-count').innerHTML = running; -- cgit v1.2.1 From ce2750e095ededa37087e2ba10f75ae7eb465584 Mon Sep 17 00:00:00 2001 From: Regis Date: Wed, 23 Nov 2016 10:52:21 -0600 Subject: refactor - rename - simple behavior for time_ago --- .../vue_pipelines_index/pipelines.js.es6 | 2 +- .../javascripts/vue_pipelines_index/store.js.es6 | 25 +++++++++++----------- .../vue_pipelines_index/time_ago.js.es6 | 17 +++++++++++---- 3 files changed, 27 insertions(+), 17 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index fd843844c7c..1c8e98f3865 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -78,7 +78,7 @@ { if (newPipe.commit) { - update.unshift(newPipe); + diffData.unshift(newPipe); } else { - const newMerge = Object.assign({}, update[i], newPipe); - update[i] = newMerge; + const newMerge = Object.assign({}, diffData[i], newPipe); + diffData[i] = newMerge; } }); - if (update.length < PAGINATION_LIMIT) return update; - return update.slice(0, SLICE_LIMIT); + if (diffData.length < PAGINATION_LIMIT) return diffData; + return diffData.slice(0, SLICE_LIMIT); } } @@ -36,6 +36,7 @@ const updatePipelineNums = (count) => { const { all } = count; + // cannot define non camel case, so not using destructuring for running const running = count.running_or_pending; document.querySelector('.js-totalbuilds-count').innerHTML = all; document.querySelector('.js-running-count').innerHTML = running; @@ -67,9 +68,9 @@ this.$http.get(`${url}?page=${pageNum}&updated_at=${this.updatedAt}`) .then((response) => { const res = JSON.parse(response.body); - const p = new PipelineUpdater(this.pipelines); + const p = new RealtimePaginationUpdater(this.pipelines); Vue.set(this, 'updatedAt', res.updated_at); - Vue.set(this, 'pipelines', p.updatePipelines(res)); + Vue.set(this, 'pipelines', p.updatePageDiff(res)); Vue.set(this, 'count', res.count); updatePipelineNums(this.count); subtractFromVueResources(); diff --git a/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 b/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 index 8eb25efe344..1d0da41ebbd 100644 --- a/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 @@ -5,6 +5,11 @@ props: [ 'pipeline', ], + computed: { + localTimeFinished() { + return gl.utils.formatDate(this.pipeline.details.finished_at); + }, + }, methods: { formatSection(section) { if (`${section}`.split('').length <= 1) return `0${section}`; @@ -58,13 +63,17 @@ }; }, duration() { - if (this.timeStopped()) return this.finishdate(); - return this.runningdate(); + // if (this.timeStopped()) return this.finishdate(); + // return this.runningdate(); + const { duration } = this.pipeline.details; + if (duration === 0) return '00:00:00'; + if (duration !== null) return duration; + return false; }, }, template: ` -

    +

    {{timeStopped().words}} -- cgit v1.2.1 From 8a2be66b04c1bd6368425d75239ebf0611a07f0f Mon Sep 17 00:00:00 2001 From: Regis Date: Wed, 23 Nov 2016 10:54:52 -0600 Subject: clean up on time_ago [ci skip] --- .../vue_pipelines_index/time_ago.js.es6 | 35 ---------------------- 1 file changed, 35 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 b/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 index 1d0da41ebbd..496065dbedc 100644 --- a/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 @@ -11,39 +11,6 @@ }, }, methods: { - formatSection(section) { - if (`${section}`.split('').length <= 1) return `0${section}`; - return `${section}`; - }, - hours(date) { - return this.formatSection(date.getHours()); - }, - minutes(date) { - return this.formatSection(date.getMinutes()); - }, - seconds(date) { - return this.formatSection(date.getSeconds()); - }, - finishdate() { - const date = new Date( - new Date( - this.pipeline.details.finished_at - ).getTime() - new Date( - this.pipeline.created_at - ).getTime() - ); - return ( - `${this.hours(date)}:${this.minutes(date)}:${this.seconds(date)}` - ); - }, - runningdate() { - const date = new Date( - new Date().getTime() - new Date(this.pipeline.created_at).getTime() - ); - return ( - `${this.hours(date)}:${this.minutes(date)}:${this.seconds(date)}` - ); - }, timeStopped() { const options = { weekday: 'long', @@ -63,8 +30,6 @@ }; }, duration() { - // if (this.timeStopped()) return this.finishdate(); - // return this.runningdate(); const { duration } = this.pipeline.details; if (duration === 0) return '00:00:00'; if (duration !== null) return duration; -- cgit v1.2.1 From 6192ea53fad0ea04e356e5a79a5a0e5359ba46ce Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 24 Nov 2016 16:50:37 +0800 Subject: Rename latest_for to latest, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7333/diffs#note_18819292 --- app/models/ci/pipeline.rb | 12 ++++-------- app/models/commit.rb | 2 +- app/services/ci/image_for_build_service.rb | 2 +- 3 files changed, 6 insertions(+), 10 deletions(-) (limited to 'app') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 61d9316a5d3..d1ce43570ac 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -89,23 +89,19 @@ module Ci end end - scope :latest, -> do + # ref can't be HEAD or SHA, can only be branch/tag name + scope :latest, ->(ref = nil) do max_id = unscope(:select).select("max(#{quoted_table_name}.id)") - where(id: max_id.group(:ref, :sha)) - end - - # ref can't be HEAD or SHA, can only be branch/tag name - scope :latest_for, ->(ref) do if ref where(ref: ref) else self - end.latest + end.where(id: max_id.group(:ref, :sha)) end def self.latest_successful_for(ref) - success.latest_for(ref).first + success.latest(ref).first end def self.truncate_sha(sha) diff --git a/app/models/commit.rb b/app/models/commit.rb index b588b93b158..946bfc4712c 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -234,7 +234,7 @@ class Commit return @statuses[ref] if @statuses.key?(ref) - @statuses[ref] = pipelines.latest_for(ref).status + @statuses[ref] = pipelines.latest(ref).status end def revert_branch_name diff --git a/app/services/ci/image_for_build_service.rb b/app/services/ci/image_for_build_service.rb index d5a07ef630b..1eeb0e2363a 100644 --- a/app/services/ci/image_for_build_service.rb +++ b/app/services/ci/image_for_build_service.rb @@ -5,7 +5,7 @@ module Ci sha = opts[:sha] || ref_sha(project, ref) pipelines = project.pipelines.where(sha: sha) - image_name = image_for_status(pipelines.latest_for(ref).status) + image_name = image_for_status(pipelines.latest(ref).status) image_path = Rails.root.join('public/ci', image_name) OpenStruct.new(path: image_path, name: image_name) -- cgit v1.2.1 From 8856d5a869939f8c5fdba827eb1c02d68bd6b162 Mon Sep 17 00:00:00 2001 From: Regis Date: Tue, 29 Nov 2016 09:43:08 -0600 Subject: turn off diff updates - wrap commit comp in td --- .../vue_pipelines_index/pipelines.js.es6 | 22 ++++++++++++---------- .../javascripts/vue_pipelines_index/store.js.es6 | 20 ++++++++++---------- 2 files changed, 22 insertions(+), 20 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index 1c8e98f3865..006e38505e2 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -55,7 +55,7 @@ if (text === FIRST) this.pagenum = 1; window.history.pushState({}, null, `?p=${this.pagenum}`); - clearInterval(this.intervalId); + // clearInterval(this.intervalId); this.pageRequest = true; this.store.fetchDataLoop.call(this, Vue, this.pagenum, this.scope); }, @@ -77,15 +77,17 @@
    - - + + + + diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index c5eca3c1289..a46bdc47491 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -81,17 +81,17 @@ resourceChecker(); goFetch(); - this.intervalId = setInterval(() => { - if (this.updatedAt) { - resourceChecker(); - if (Vue.activeResources > 1) return; - goUpdate(); - } - }, 3000); + // this.intervalId = setInterval(() => { + // if (this.updatedAt) { + // resourceChecker(); + // if (Vue.activeResources > 1) return; + // goUpdate(); + // } + // }, 3000); - window.onbeforeunload = function removePipelineInterval() { - clearInterval(this.intervalId); - }; + // window.onbeforeunload = function removePipelineInterval() { + // clearInterval(this.intervalId); + // }; } }; })(window.gl || (window.gl = {})); -- cgit v1.2.1 From 1f50b3fed927bca38335bcd77b9ea69e82a0d2c1 Mon Sep 17 00:00:00 2001 From: Regis Date: Tue, 29 Nov 2016 19:19:03 -0600 Subject: render valid user props for pipeline user --- app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 index 94c51ad77fa..e11f68bbd36 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 @@ -11,7 +11,8 @@ ], computed: { user() { - if (!this.pipeline.user === null) return true; + // debugger + if (this.pipeline.user) return true; return false; }, }, @@ -23,14 +24,14 @@
    by Date: Tue, 29 Nov 2016 19:19:22 -0600 Subject: rid off debugger comment [ci skip] --- app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 | 1 - 1 file changed, 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 index e11f68bbd36..d9602b4209d 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 @@ -11,7 +11,6 @@ ], computed: { user() { - // debugger if (this.pipeline.user) return true; return false; }, -- cgit v1.2.1 From 649d1eb23073543ceed995124c1cb67aabb8bfc2 Mon Sep 17 00:00:00 2001 From: Regis Date: Tue, 29 Nov 2016 20:44:00 -0600 Subject: new line for skipped - use logic gate for REALTIME true or false --- .../vue_pipelines_index/pipelines.js.es6 | 3 ++- .../javascripts/vue_pipelines_index/store.js.es6 | 23 ++++++++++++---------- .../vue_pipelines_status/skipped.js.es6 | 2 +- 3 files changed, 16 insertions(+), 12 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index 006e38505e2..477d59ad2c3 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -2,6 +2,7 @@ /* eslint-disable no-param-reassign, no-bitwise*/ ((gl) => { + const REALTIME = false; const SPREAD = '...'; const PREV = 'Prev'; const NEXT = 'Next'; @@ -55,7 +56,7 @@ if (text === FIRST) this.pagenum = 1; window.history.pushState({}, null, `?p=${this.pagenum}`); - // clearInterval(this.intervalId); + if (REALTIME) clearInterval(this.intervalId); this.pageRequest = true; this.store.fetchDataLoop.call(this, Vue, this.pagenum, this.scope); }, diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index a46bdc47491..3ec627d24d0 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -2,6 +2,7 @@ /* eslint-disable no-param-reassign */ ((gl) => { + const REALTIME = false; const PAGINATION_LIMIT = 31; const SLICE_LIMIT = 29; @@ -81,17 +82,19 @@ resourceChecker(); goFetch(); - // this.intervalId = setInterval(() => { - // if (this.updatedAt) { - // resourceChecker(); - // if (Vue.activeResources > 1) return; - // goUpdate(); - // } - // }, 3000); + if (REALTIME) { + this.intervalId = setInterval(() => { + if (this.updatedAt) { + resourceChecker(); + if (Vue.activeResources > 1) return; + goUpdate(); + } + }, 3000); - // window.onbeforeunload = function removePipelineInterval() { - // clearInterval(this.intervalId); - // }; + window.onbeforeunload = function removePipelineInterval() { + clearInterval(this.intervalId); + }; + } } }; })(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_status/skipped.js.es6 b/app/assets/javascripts/vue_pipelines_status/skipped.js.es6 index 92d53c4a87e..da904010607 100644 --- a/app/assets/javascripts/vue_pipelines_status/skipped.js.es6 +++ b/app/assets/javascripts/vue_pipelines_status/skipped.js.es6 @@ -20,4 +20,4 @@ `, }); -})(window.gl || (window.gl = {})); \ No newline at end of file +})(window.gl || (window.gl = {})); -- cgit v1.2.1 From d11a298cd5ff9888f15e14efe2313f1445051618 Mon Sep 17 00:00:00 2001 From: Regis Date: Wed, 30 Nov 2016 02:23:51 -0600 Subject: on focus - blur - and page closed -- intervals are taken care of for time ago and realtime --- .../vue_pipelines_index/pipelines.js.es6 | 10 +++++- .../javascripts/vue_pipelines_index/store.js.es6 | 35 ++++++++++++++----- .../vue_pipelines_index/time_ago.js.es6 | 40 +++++++++++++++++----- 3 files changed, 67 insertions(+), 18 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index 477d59ad2c3..b4cdc5080a6 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -24,6 +24,7 @@ data() { return { pipelines: [], + allTimeIntervals: [], intervalId: '', updatedAt: '', pagenum: 1, @@ -65,6 +66,9 @@ if (author) return author; return ({}); }, + addTimeInterval(id, that) { + this.allTimeIntervals.push({ id: id, component: that }); + }, }, template: `

    @@ -90,7 +94,11 @@ - + + diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index 3ec627d24d0..359eab3f6c8 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -2,7 +2,7 @@ /* eslint-disable no-param-reassign */ ((gl) => { - const REALTIME = false; + const REALTIME = true; const PAGINATION_LIMIT = 31; const SLICE_LIMIT = 29; @@ -33,11 +33,10 @@ const addToVueResources = () => { Vue.activeResources += 1; }; const subtractFromVueResources = () => { Vue.activeResources -= 1; }; - resetVueResources(); // set Vue.resources to 0 + resetVueResources(); const updatePipelineNums = (count) => { const { all } = count; - // cannot define non camel case, so not using destructuring for running const running = count.running_or_pending; document.querySelector('.js-totalbuilds-count').innerHTML = all; document.querySelector('.js-running-count').innerHTML = running; @@ -82,7 +81,7 @@ resourceChecker(); goFetch(); - if (REALTIME) { + const poller = () => { this.intervalId = setInterval(() => { if (this.updatedAt) { resourceChecker(); @@ -90,11 +89,31 @@ goUpdate(); } }, 3000); + }; + + if (REALTIME) poller(); + + const removePipelineInterval = () => { + this.allTimeIntervals.forEach(e => clearInterval(e.id)); + if (REALTIME) clearInterval(this.intervalId); + }; + + const startIntervalLoops = () => { + this.allTimeIntervals.forEach(e => e.component.startInterval()); + if (REALTIME) poller(); + }; - window.onbeforeunload = function removePipelineInterval() { - clearInterval(this.intervalId); - }; - } + window.onbeforeunload = function onClose() { + removePipelineInterval(); + }; + + window.onblur = function remove() { + removePipelineInterval(); + }; + + window.onfocus = function start() { + startIntervalLoops(); + }; } }; })(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 b/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 index 496065dbedc..505b1ee3490 100644 --- a/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 @@ -1,17 +1,35 @@ /* global Vue, gl */ /* eslint-disable no-param-reassign */ ((gl) => { + const REALTIME = false; + gl.VueTimeAgo = Vue.extend({ + data() { + return { + timeInterval: '', + currentTime: new Date(), + }; + }, props: [ 'pipeline', + 'addTimeInterval', ], + created() { + if (!REALTIME) { + this.timeInterval = setInterval(() => { + this.currentTime = new Date(); + }, 1000); + + this.addTimeInterval(this.timeInterval, this); + } + }, computed: { localTimeFinished() { return gl.utils.formatDate(this.pipeline.details.finished_at); }, - }, - methods: { timeStopped() { + const changeTime = this.currentTime; + const options = { weekday: 'long', year: 'numeric', @@ -23,18 +41,22 @@ const finished = this.pipeline.details.finished_at; - if (!finished) return false; - - return { - words: gl.utils.getTimeago().format(finished), - }; + if (!finished && changeTime) return false; + return ({ words: gl.utils.getTimeago().format(finished) }); }, + }, + methods: { duration() { const { duration } = this.pipeline.details; if (duration === 0) return '00:00:00'; if (duration !== null) return duration; return false; }, + startInterval() { + this.timeInterval = setInterval(() => { + this.currentTime = new Date(); + }, 1000); + }, }, template: ` @@ -51,7 +73,7 @@ {{duration()}}

    -

    +

    -- cgit v1.2.1 From 874a7e8d20dfead42ae957ea8746b20a1446dcea Mon Sep 17 00:00:00 2001 From: Regis Date: Wed, 30 Nov 2016 02:27:05 -0600 Subject: turned off REALTIME - time ago blur and focus still good --- app/assets/javascripts/vue_pipelines_index/store.js.es6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index 359eab3f6c8..6d023a45b21 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -2,7 +2,7 @@ /* eslint-disable no-param-reassign */ ((gl) => { - const REALTIME = true; + const REALTIME = false; const PAGINATION_LIMIT = 31; const SLICE_LIMIT = 29; -- cgit v1.2.1 From fd9adc78824500928465d82c691fdd76e290672d Mon Sep 17 00:00:00 2001 From: Regis Date: Wed, 30 Nov 2016 02:30:03 -0600 Subject: eslint calm [ci skip] --- app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index b4cdc5080a6..6ef335ab398 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -67,7 +67,7 @@ return ({}); }, addTimeInterval(id, that) { - this.allTimeIntervals.push({ id: id, component: that }); + this.allTimeIntervals.push({ id, component: that }); }, }, template: ` -- cgit v1.2.1 From 81ae6c7d0a38bb66289c5d83239255ce5cdfcea5 Mon Sep 17 00:00:00 2001 From: Regis Date: Wed, 30 Nov 2016 09:29:31 -0700 Subject: fire timeago interval no matter what --- app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 b/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 index 505b1ee3490..c078e9459f0 100644 --- a/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 @@ -1,8 +1,6 @@ /* global Vue, gl */ /* eslint-disable no-param-reassign */ ((gl) => { - const REALTIME = false; - gl.VueTimeAgo = Vue.extend({ data() { return { @@ -15,13 +13,11 @@ 'addTimeInterval', ], created() { - if (!REALTIME) { - this.timeInterval = setInterval(() => { - this.currentTime = new Date(); - }, 1000); + this.timeInterval = setInterval(() => { + this.currentTime = new Date(); + }, 1000); - this.addTimeInterval(this.timeInterval, this); - } + this.addTimeInterval(this.timeInterval, this); }, computed: { localTimeFinished() { -- cgit v1.2.1 From 6eb3728490cbf33ea3e401653a5da0ab290c6f52 Mon Sep 17 00:00:00 2001 From: Regis Date: Wed, 30 Nov 2016 09:30:06 -0700 Subject: format - [ci skip] --- app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 | 4 ---- 1 file changed, 4 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 b/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 index c078e9459f0..de6eec9bc5b 100644 --- a/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 @@ -25,18 +25,14 @@ }, timeStopped() { const changeTime = this.currentTime; - const options = { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric', }; - options.timeZoneName = 'short'; - const finished = this.pipeline.details.finished_at; - if (!finished && changeTime) return false; return ({ words: gl.utils.getTimeago().format(finished) }); }, -- cgit v1.2.1 From 3c2cb28e84aa231d09bb8e5958b61eb2ef056eb2 Mon Sep 17 00:00:00 2001 From: Dimitrie Hoekstra Date: Thu, 1 Dec 2016 13:32:05 +0100 Subject: Added lighter count badge background-color for on white backgrounds --- app/assets/stylesheets/framework/nav.scss | 6 +++++- app/assets/stylesheets/pages/environments.scss | 2 +- app/assets/stylesheets/pages/pipelines.scss | 2 +- app/views/layouts/nav/_admin.html.haml | 2 +- app/views/layouts/nav/_group.html.haml | 4 ++-- app/views/layouts/nav/_project.html.haml | 4 ++-- 6 files changed, 12 insertions(+), 8 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index 1839ffa0976..40b696774a4 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -75,10 +75,14 @@ .badge { font-weight: normal; - background-color: #eee; + background-color: #f3f3f3; color: $btn-transparent-color; vertical-align: baseline; } + + .badge-dark { + background-color: #eee; + } } &.sub-nav { diff --git a/app/assets/stylesheets/pages/environments.scss b/app/assets/stylesheets/pages/environments.scss index 4b382e8adaf..658aec5e609 100644 --- a/app/assets/stylesheets/pages/environments.scss +++ b/app/assets/stylesheets/pages/environments.scss @@ -116,7 +116,7 @@ .badge { font-weight: normal; - background-color: $gray-darker; + background-color: #f3f3f3; color: $gl-placeholder-color; vertical-align: baseline; } diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 0027d2caf22..651e82b7b45 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -507,7 +507,7 @@ } .badge { - background-color: $gray-darker; + background-color: #f3f3f3; color: $gl-text-color-light; font-weight: normal; margin-left: $btn-xs-side-margin; diff --git a/app/views/layouts/nav/_admin.html.haml b/app/views/layouts/nav/_admin.html.haml index ac04f57e217..b69114c96cc 100644 --- a/app/views/layouts/nav/_admin.html.haml +++ b/app/views/layouts/nav/_admin.html.haml @@ -31,7 +31,7 @@ = link_to admin_abuse_reports_path, title: "Abuse Reports" do %span Abuse Reports - %span.badge.count= number_with_delimiter(AbuseReport.count(:all)) + %span.badge.badge-dark.count= number_with_delimiter(AbuseReport.count(:all)) - if askimet_enabled? = nav_link(controller: :spam_logs) do diff --git a/app/views/layouts/nav/_group.html.haml b/app/views/layouts/nav/_group.html.haml index f7edb47b666..c866767a2be 100644 --- a/app/views/layouts/nav/_group.html.haml +++ b/app/views/layouts/nav/_group.html.haml @@ -26,13 +26,13 @@ %span Issues - issues = IssuesFinder.new(current_user, group_id: @group.id, state: 'opened').execute - %span.badge.count= number_with_delimiter(issues.count) + %span.badge.badge-dark.count= number_with_delimiter(issues.count) = nav_link(path: 'groups#merge_requests') do = link_to merge_requests_group_path(@group), title: 'Merge Requests' do %span Merge Requests - merge_requests = MergeRequestsFinder.new(current_user, group_id: @group.id, state: 'opened').execute - %span.badge.count= number_with_delimiter(merge_requests.count) + %span.badge.badge-dark.count= number_with_delimiter(merge_requests.count) = nav_link(controller: [:group_members]) do = link_to group_group_members_path(@group), title: 'Members' do %span diff --git a/app/views/layouts/nav/_project.html.haml b/app/views/layouts/nav/_project.html.haml index 701bcd3ab71..a67a63adba8 100644 --- a/app/views/layouts/nav/_project.html.haml +++ b/app/views/layouts/nav/_project.html.haml @@ -70,14 +70,14 @@ %span Issues - if @project.default_issues_tracker? - %span.badge.count.issue_counter= number_with_delimiter(IssuesFinder.new(current_user, project_id: @project.id).execute.opened.count) + %span.badge.badge-dark.count.issue_counter= number_with_delimiter(IssuesFinder.new(current_user, project_id: @project.id).execute.opened.count) - if project_nav_tab? :merge_requests = nav_link(controller: :merge_requests) do = link_to namespace_project_merge_requests_path(@project.namespace, @project), title: 'Merge Requests', class: 'shortcuts-merge_requests' do %span Merge Requests - %span.badge.count.merge_counter= number_with_delimiter(@project.merge_requests.opened.count) + %span.badge.badge-dark.count.merge_counter= number_with_delimiter(@project.merge_requests.opened.count) - if project_nav_tab? :wiki = nav_link(controller: :wikis) do -- cgit v1.2.1 From 2791226c6b59db62b76bf4f5c4f4f945e9760eaa Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 1 Dec 2016 11:59:00 +0100 Subject: Remove support from incremental pipeline updates --- app/controllers/projects/pipelines_controller.rb | 3 +- app/serializers/pipeline_entity.rb | 38 +++++------------------- app/serializers/pipeline_serializer.rb | 5 ---- 3 files changed, 8 insertions(+), 38 deletions(-) (limited to 'app') diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb index 3d095e2b690..b1d82e952bd 100644 --- a/app/controllers/projects/pipelines_controller.rb +++ b/app/controllers/projects/pipelines_controller.rb @@ -11,7 +11,6 @@ class Projects::PipelinesController < Projects::ApplicationController @running_or_pending_count = PipelinesFinder.new(project).execute(scope: 'running').count @pipelines_count = PipelinesFinder.new(project).execute.count - @last_updated = params[:updated_at] respond_to do |format| format.html @@ -19,7 +18,7 @@ class Projects::PipelinesController < Projects::ApplicationController render json: { pipelines: PipelineSerializer .new(project: @project, user: @current_user) - .incremental(@pipelines, @last_updated), + .represent(@pipelines), updated_at: Time.now.utc, count: { all: @pipelines_count, diff --git a/app/serializers/pipeline_entity.rb b/app/serializers/pipeline_entity.rb index 08346b4ed77..cf99e628d5f 100644 --- a/app/serializers/pipeline_entity.rb +++ b/app/serializers/pipeline_entity.rb @@ -2,7 +2,7 @@ class PipelineEntity < Grape::Entity include RequestAwareEntity expose :id - expose :user, if: proc { created_exposure? }, using: UserEntity + expose :user, using: UserEntity expose :url do |pipeline| namespace_project_pipeline_path( @@ -11,7 +11,7 @@ class PipelineEntity < Grape::Entity pipeline) end - expose :details, if: proc { updated_exposure? } do + expose :details do expose :status expose :duration expose :finished_at @@ -20,7 +20,7 @@ class PipelineEntity < Grape::Entity expose :manual_actions, using: PipelineActionEntity end - expose :flags, if: proc { created_exposure? } do + expose :flags do expose :latest?, as: :latest expose :triggered?, as: :triggered @@ -33,7 +33,7 @@ class PipelineEntity < Grape::Entity end end - expose :ref, if: proc { updated_exposure? } do + expose :ref do expose :name do |pipeline| pipeline.ref end @@ -48,16 +48,16 @@ class PipelineEntity < Grape::Entity expose :tag? end - expose :commit, if: proc { created_exposure? }, using: CommitEntity + expose :commit, using: CommitEntity - expose :retry_url, if: proc { updated_exposure? } do |pipeline| + expose :retry_url do |pipeline| can?(request.user, :update_pipeline, pipeline.project) && pipeline.retryable? && retry_namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id) end - expose :cancel_url, if: proc { updated_exposure? } do |pipeline| + expose :cancel_url do |pipeline| can?(request.user, :update_pipeline, pipeline.project) && pipeline.cancelable? && cancel_namespace_project_pipeline_path(pipeline.project.namespace, @@ -65,28 +65,4 @@ class PipelineEntity < Grape::Entity end expose :created_at, :updated_at - - def created_exposure? - !incremental? || created? - end - - def updated_exposure? - !incremental? || updated? - end - - def incremental? - options[:incremental] && last_updated - end - - def last_updated - options.fetch(:last_updated) - end - - def updated? - @object.updated_at > last_updated - end - - def created? - @object.created_at > last_updated - end end diff --git a/app/serializers/pipeline_serializer.rb b/app/serializers/pipeline_serializer.rb index 8d3182d9766..f7abbec7d45 100644 --- a/app/serializers/pipeline_serializer.rb +++ b/app/serializers/pipeline_serializer.rb @@ -1,8 +1,3 @@ class PipelineSerializer < BaseSerializer entity PipelineEntity - - def incremental(resource, last_updated) - represent(resource, incremental: true, - last_updated: last_updated) - end end -- cgit v1.2.1 From 3acee982037b1328df29dc867c83b83746f33e44 Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 1 Dec 2016 15:02:26 -0700 Subject: update styling for loading icon --- app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 | 4 ++-- app/assets/stylesheets/pages/pipelines.scss | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index 6ef335ab398..61af9799ca4 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -72,7 +72,7 @@ }, template: `
    -
    +
    @@ -104,7 +104,7 @@
    -
    +
    Date: Thu, 1 Dec 2016 16:07:30 -0700 Subject: get commit component to render needed info - work on SVG loading next --- .../vue_pipelines_index/pipelines.js.es6 | 16 +++++-- .../javascripts/vue_pipelines_index/store.js.es6 | 54 +--------------------- 2 files changed, 13 insertions(+), 57 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index 61af9799ca4..e02c7dc528e 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -62,9 +62,17 @@ this.store.fetchDataLoop.call(this, Vue, this.pagenum, this.scope); }, author(pipeline) { - const author = pipeline.commit.author; + const { commit } = pipeline; + const author = commit.author; if (author) return author; - return ({}); + + const nonUser = { + avatar_url: commit.author_gravatar_url, + web_url: `mailto:${commit.author_email}`, + username: commit.author_name, + }; + + return nonUser; }, addTimeInterval(id, that) { this.allTimeIntervals.push({ id, component: that }); @@ -85,7 +93,7 @@
    { - const REALTIME = false; - const PAGINATION_LIMIT = 31; - const SLICE_LIMIT = 29; - - class RealtimePaginationUpdater { - constructor(pageData) { - this.pageData = pageData; - } - - updatePageDiff(apiResponse) { - const diffData = this.pageData.slice(0); - apiResponse.pipelines.forEach((newPipe, i) => { - if (newPipe.commit) { - diffData.unshift(newPipe); - } else { - const newMerge = Object.assign({}, diffData[i], newPipe); - diffData[i] = newMerge; - } - }); - if (diffData.length < PAGINATION_LIMIT) return diffData; - return diffData.slice(0, SLICE_LIMIT); - } - } - gl.PipelineStore = class { fetchDataLoop(Vue, pageNum, url) { const setVueResources = () => { Vue.activeResources = 1; }; @@ -61,46 +37,18 @@ this.pageRequest = false; subtractFromVueResources(); }, () => new Flash( - 'Something went wrong on our end.' - )); - - const goUpdate = () => - this.$http.get(`${url}?page=${pageNum}&updated_at=${this.updatedAt}`) - .then((response) => { - const res = JSON.parse(response.body); - const p = new RealtimePaginationUpdater(this.pipelines); - Vue.set(this, 'updatedAt', res.updated_at); - Vue.set(this, 'pipelines', p.updatePageDiff(res)); - Vue.set(this, 'count', res.count); - updatePipelineNums(this.count); - subtractFromVueResources(); - }, () => new Flash( - 'Something went wrong on our end.' + 'Something went wrong on our end.', )); resourceChecker(); goFetch(); - const poller = () => { - this.intervalId = setInterval(() => { - if (this.updatedAt) { - resourceChecker(); - if (Vue.activeResources > 1) return; - goUpdate(); - } - }, 3000); - }; - - if (REALTIME) poller(); - const removePipelineInterval = () => { this.allTimeIntervals.forEach(e => clearInterval(e.id)); - if (REALTIME) clearInterval(this.intervalId); }; const startIntervalLoops = () => { this.allTimeIntervals.forEach(e => e.component.startInterval()); - if (REALTIME) poller(); }; window.onbeforeunload = function onClose() { -- cgit v1.2.1 From 1e7f91f2d611b80e7537a56aefc3e31452eaf273 Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 1 Dec 2016 16:23:47 -0700 Subject: remove 30% width for commit column --- app/assets/stylesheets/pages/pipelines.scss | 2 -- 1 file changed, 2 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 3b8d2268437..0002c57cb13 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -33,8 +33,6 @@ } .branch-commit { - width: 30%; - .branch-name { max-width: 195px; } -- cgit v1.2.1 From af5de82c67bd1867e69438b71f67f43d026e4edf Mon Sep 17 00:00:00 2001 From: Dimitrie Hoekstra Date: Fri, 2 Dec 2016 00:41:22 +0100 Subject: created framework for badges, solving duplicate code --- app/assets/stylesheets/framework.scss | 1 + app/assets/stylesheets/framework/badges.scss | 10 ++++++++++ app/assets/stylesheets/framework/nav.scss | 11 ----------- app/assets/stylesheets/framework/variables.scss | 7 +++++++ app/assets/stylesheets/pages/environments.scss | 7 ------- app/assets/stylesheets/pages/pipelines.scss | 3 --- 6 files changed, 18 insertions(+), 21 deletions(-) create mode 100644 app/assets/stylesheets/framework/badges.scss (limited to 'app') diff --git a/app/assets/stylesheets/framework.scss b/app/assets/stylesheets/framework.scss index 7c7f991dd87..c26fea8d5b2 100644 --- a/app/assets/stylesheets/framework.scss +++ b/app/assets/stylesheets/framework.scss @@ -9,6 +9,7 @@ @import "framework/avatar.scss"; @import "framework/blocks.scss"; @import "framework/buttons.scss"; +@import "framework/badges.scss"; @import "framework/calendar.scss"; @import "framework/callout.scss"; @import "framework/common.scss"; diff --git a/app/assets/stylesheets/framework/badges.scss b/app/assets/stylesheets/framework/badges.scss new file mode 100644 index 00000000000..89e1c7890d8 --- /dev/null +++ b/app/assets/stylesheets/framework/badges.scss @@ -0,0 +1,10 @@ +.badge { + font-weight: normal; + background-color: $badge-bg; + color: $badge-color; + vertical-align: baseline; +} + +.badge-dark { + background-color: $badge-bg-dark; +} diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index 40b696774a4..477582f9e3f 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -72,17 +72,6 @@ color: $black; font-weight: 600; } - - .badge { - font-weight: normal; - background-color: #f3f3f3; - color: $btn-transparent-color; - vertical-align: baseline; - } - - .badge-dark { - background-color: #eee; - } } &.sub-nav { diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 8a9c279d124..651e58d0bb4 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -247,6 +247,13 @@ $btn-placeholder-gray: #c7c7c7; $btn-white-active: #848484; $btn-gray-hover: #eee; +/* +* Badges +*/ +$badge-bg: #f3f3f3; +$badge-bg-dark: #eee; +$badge-color: $btn-transparent-color; + /* * Award emoji */ diff --git a/app/assets/stylesheets/pages/environments.scss b/app/assets/stylesheets/pages/environments.scss index 658aec5e609..387d2818495 100644 --- a/app/assets/stylesheets/pages/environments.scss +++ b/app/assets/stylesheets/pages/environments.scss @@ -113,13 +113,6 @@ .folder-name { cursor: pointer; - - .badge { - font-weight: normal; - background-color: #f3f3f3; - color: $gl-placeholder-color; - vertical-align: baseline; - } } } diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 651e82b7b45..90e933cbd61 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -507,9 +507,6 @@ } .badge { - background-color: #f3f3f3; - color: $gl-text-color-light; - font-weight: normal; margin-left: $btn-xs-side-margin; } } -- cgit v1.2.1 From c55ba05228c719bf1e05818fb91200b3d60da990 Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 1 Dec 2016 18:08:34 -0700 Subject: add svg to pipeline index haml - prep for commit comp change - [ci skip] --- app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 | 13 +++++++++++-- app/views/projects/pipelines/index.html.haml | 2 ++ 2 files changed, 13 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index e02c7dc528e..2e126434ea5 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -74,6 +74,15 @@ return nonUser; }, + ref(pipeline) { + const { ref } = pipeline; + const commitRef = { + name: ref.name, + tag: ref['tag?'], + ref_url: ref.url, + }; + return commitRef; + }, addTimeInterval(id, that) { this.allTimeIntervals.push({ id, component: that }); }, @@ -92,10 +101,10 @@ diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index 3185f1573c6..4025a6859f2 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -53,6 +53,8 @@ = render @pipelines, commit_sha: true, stage: true, allow_retry: true = paginate @pipelines, theme: 'gitlab' - else + .commit-icon-svg.hidden + = custom_icon("icon_commit") .vue-pipelines-index = page_specific_javascript_tag('vue_icons/index.js') -- cgit v1.2.1 From fb5f7733f14b701f6e22a54bc8b4c08330bc036f Mon Sep 17 00:00:00 2001 From: DJ Mountney Date: Sun, 2 Oct 2016 15:30:44 -0700 Subject: Allow users to seed the initial runner registration token using an environment variable This is useful for when runner is bundled with gitlab, like in a kubernetes stack, and we want the runner to be able to register with gitlab as soon as they both come up. --- app/models/concerns/token_authenticatable.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app') diff --git a/app/models/concerns/token_authenticatable.rb b/app/models/concerns/token_authenticatable.rb index 04d30f46210..1ca7f91dc03 100644 --- a/app/models/concerns/token_authenticatable.rb +++ b/app/models/concerns/token_authenticatable.rb @@ -39,6 +39,10 @@ module TokenAuthenticatable current_token.blank? ? write_new_token(token_field) : current_token end + define_method("set_#{token_field}") do |token| + write_attribute(token_field, token) if token + end + define_method("ensure_#{token_field}!") do send("reset_#{token_field}!") if read_attribute(token_field).blank? read_attribute(token_field) -- cgit v1.2.1 From 86016960811e90ceecdd0353753107943cdea1d8 Mon Sep 17 00:00:00 2001 From: Pier Paolo Ramon Date: Fri, 2 Dec 2016 13:28:35 +0000 Subject: Minor white-space source formatting --- app/assets/stylesheets/pages/boards.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/boards.scss b/app/assets/stylesheets/pages/boards.scss index 82f36f24867..c55cecd57c8 100644 --- a/app/assets/stylesheets/pages/boards.scss +++ b/app/assets/stylesheets/pages/boards.scss @@ -31,7 +31,7 @@ .dropdown-content { max-height: 150px; - } + } } .issue-board-dropdown-content { -- cgit v1.2.1 From e19d4ce269b77f48a00547971ad3796affea9005 Mon Sep 17 00:00:00 2001 From: Pier Paolo Ramon Date: Fri, 2 Dec 2016 13:33:39 +0000 Subject: Extend the list header top border to the edge of the box With border board lists (those created from labels) the top border created bad visual artifacts with the .board-inner gray border. With this change the colored border overflows the padding-box of .board-inner and extends to the edges. It works very well with most colors, excepts for very light ones (such as `#ff0` yellow for instance). --- app/assets/stylesheets/pages/boards.scss | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'app') diff --git a/app/assets/stylesheets/pages/boards.scss b/app/assets/stylesheets/pages/boards.scss index c55cecd57c8..bff84b36eec 100644 --- a/app/assets/stylesheets/pages/boards.scss +++ b/app/assets/stylesheets/pages/boards.scss @@ -109,6 +109,12 @@ &.has-border { border-top: 3px solid; + margin-top: -1px; + margin-right: -1px; + margin-left: -1px; + padding-top: 1px; + padding-right: 1px; + padding-left: 1px; .board-title { padding-top: ($gl-padding - 3px); -- cgit v1.2.1 From a96499cf3cc8189e9f4e7f450b175b5a0ab001af Mon Sep 17 00:00:00 2001 From: Regis Date: Fri, 2 Dec 2016 10:18:23 -0700 Subject: reduce heavy references --- app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 | 4 ++-- app/assets/javascripts/vue_pipelines_index/store.js.es6 | 2 +- app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index 2e126434ea5..9c27cb60615 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -83,8 +83,8 @@ }; return commitRef; }, - addTimeInterval(id, that) { - this.allTimeIntervals.push({ id, component: that }); + addTimeInterval(id, start) { + this.allTimeIntervals.push({ id, start }); }, }, template: ` diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index 2dc1fd571f1..5f07617a602 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -48,7 +48,7 @@ }; const startIntervalLoops = () => { - this.allTimeIntervals.forEach(e => e.component.startInterval()); + this.allTimeIntervals.forEach(e => e.start()); }; window.onbeforeunload = function onClose() { diff --git a/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 b/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 index de6eec9bc5b..8aae777e9f1 100644 --- a/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 @@ -17,7 +17,7 @@ this.currentTime = new Date(); }, 1000); - this.addTimeInterval(this.timeInterval, this); + this.addTimeInterval(this.timeInterval, this.startInterval); }, computed: { localTimeFinished() { -- cgit v1.2.1 From 18b559c9be5cf903569f01ae878ed71415b8a1a8 Mon Sep 17 00:00:00 2001 From: Regis Date: Fri, 2 Dec 2016 11:42:26 -0700 Subject: deal with preventing DDOS --- .../javascripts/vue_pipelines_index/store.js.es6 | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index 5f07617a602..ca537a9c20d 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -43,7 +43,7 @@ resourceChecker(); goFetch(); - const removePipelineInterval = () => { + const removePipelineIntervals = () => { this.allTimeIntervals.forEach(e => clearInterval(e.id)); }; @@ -51,17 +51,18 @@ this.allTimeIntervals.forEach(e => e.start()); }; - window.onbeforeunload = function onClose() { - removePipelineInterval(); + const removeAll = () => { + removePipelineIntervals(); + window.removeEventListener('beforeunload', () => {}); + window.removeEventListener('focus', () => {}); + window.removeEventListener('blur', () => {}); + document.removeEventListener('page:fetch', () => {}); }; - window.onblur = function remove() { - removePipelineInterval(); - }; - - window.onfocus = function start() { - startIntervalLoops(); - }; + window.addEventListener('beforeunload', removePipelineIntervals); + window.addEventListener('focus', startIntervalLoops); + window.addEventListener('blur', removePipelineIntervals); + document.addEventListener('page:fetch', removeAll); } }; })(window.gl || (window.gl = {})); -- cgit v1.2.1 From 004a9c6bccb840b97616d25c0ff24a8de62ff496 Mon Sep 17 00:00:00 2001 From: Regis Date: Fri, 2 Dec 2016 11:52:20 -0700 Subject: change to new prop for commit component - [ci skip] --- app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index 9c27cb60615..656ac0a25f1 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -101,10 +101,10 @@ -- cgit v1.2.1 From d6061b739b7f27d9b7ee9f6ff1e7a635c7bac0b3 Mon Sep 17 00:00:00 2001 From: Regis Date: Fri, 2 Dec 2016 15:05:01 -0700 Subject: much simpler time logic - clean up - [ci skip] --- .../vue_pipelines_index/pipelines.js.es6 | 6 ++-- .../javascripts/vue_pipelines_index/store.js.es6 | 33 ++++++++++++++-------- .../vue_pipelines_index/time_ago.js.es6 | 15 ++-------- 3 files changed, 26 insertions(+), 28 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index 656ac0a25f1..bba9a82e6ec 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -2,7 +2,6 @@ /* eslint-disable no-param-reassign, no-bitwise*/ ((gl) => { - const REALTIME = false; const SPREAD = '...'; const PREV = 'Prev'; const NEXT = 'Next'; @@ -24,7 +23,7 @@ data() { return { pipelines: [], - allTimeIntervals: [], + timeLoopInterval: '', intervalId: '', updatedAt: '', pagenum: 1, @@ -57,7 +56,7 @@ if (text === FIRST) this.pagenum = 1; window.history.pushState({}, null, `?p=${this.pagenum}`); - if (REALTIME) clearInterval(this.intervalId); + clearInterval(this.timeLoopInterval); this.pageRequest = true; this.store.fetchDataLoop.call(this, Vue, this.pagenum, this.scope); }, @@ -113,7 +112,6 @@ diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index ca537a9c20d..1a473c51521 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -1,5 +1,5 @@ /* global gl, Flash */ -/* eslint-disable no-param-reassign */ +/* eslint-disable no-param-reassign, no-underscore-dangle */ ((gl) => { gl.PipelineStore = class { @@ -43,25 +43,36 @@ resourceChecker(); goFetch(); - const removePipelineIntervals = () => { - this.allTimeIntervals.forEach(e => clearInterval(e.id)); + const startTimeLoops = () => { + this.timeLoopInterval = setInterval(() => { + console.log('TIME LOOP'); + this.$children + .filter(e => e.$options._componentTag === 'time-ago') + .forEach(e => e.changeTime()); + }, 1000); + }; + + startTimeLoops(); + + const removeTimeIntervals = () => { + clearInterval(this.timeLoopInterval); }; const startIntervalLoops = () => { - this.allTimeIntervals.forEach(e => e.start()); + startTimeLoops(); }; const removeAll = () => { - removePipelineIntervals(); - window.removeEventListener('beforeunload', () => {}); - window.removeEventListener('focus', () => {}); - window.removeEventListener('blur', () => {}); - document.removeEventListener('page:fetch', () => {}); + removeTimeIntervals(); + window.removeEventListener('beforeunload', removeTimeIntervals); + window.removeEventListener('focus', startIntervalLoops); + window.removeEventListener('blur', removeTimeIntervals); + document.removeEventListener('page:fetch', removeTimeIntervals); }; - window.addEventListener('beforeunload', removePipelineIntervals); + window.addEventListener('beforeunload', removeTimeIntervals); window.addEventListener('focus', startIntervalLoops); - window.addEventListener('blur', removePipelineIntervals); + window.addEventListener('blur', removeTimeIntervals); document.addEventListener('page:fetch', removeAll); } }; diff --git a/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 b/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 index 8aae777e9f1..33a1744fa82 100644 --- a/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 @@ -4,21 +4,12 @@ gl.VueTimeAgo = Vue.extend({ data() { return { - timeInterval: '', currentTime: new Date(), }; }, props: [ 'pipeline', - 'addTimeInterval', ], - created() { - this.timeInterval = setInterval(() => { - this.currentTime = new Date(); - }, 1000); - - this.addTimeInterval(this.timeInterval, this.startInterval); - }, computed: { localTimeFinished() { return gl.utils.formatDate(this.pipeline.details.finished_at); @@ -44,10 +35,8 @@ if (duration !== null) return duration; return false; }, - startInterval() { - this.timeInterval = setInterval(() => { - this.currentTime = new Date(); - }, 1000); + changeTime() { + this.currentTime = new Date(); }, }, template: ` -- cgit v1.2.1 From cd111ffabd36c44ec2fd9c52d5c35e7cdc936c67 Mon Sep 17 00:00:00 2001 From: Regis Date: Fri, 2 Dec 2016 15:10:31 -0700 Subject: anon callbacks since intervals removed in function prior - [ci skip] --- app/assets/javascripts/vue_pipelines_index/store.js.es6 | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index 1a473c51521..79bf56b5f69 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -45,7 +45,6 @@ const startTimeLoops = () => { this.timeLoopInterval = setInterval(() => { - console.log('TIME LOOP'); this.$children .filter(e => e.$options._componentTag === 'time-ago') .forEach(e => e.changeTime()); @@ -64,10 +63,10 @@ const removeAll = () => { removeTimeIntervals(); - window.removeEventListener('beforeunload', removeTimeIntervals); - window.removeEventListener('focus', startIntervalLoops); - window.removeEventListener('blur', removeTimeIntervals); - document.removeEventListener('page:fetch', removeTimeIntervals); + window.removeEventListener('beforeunload', () => {}); + window.removeEventListener('focus', () => {}); + window.removeEventListener('blur', () => {}); + document.removeEventListener('page:fetch', () => {}); }; window.addEventListener('beforeunload', removeTimeIntervals); -- cgit v1.2.1 From c5664761778a5f530ee7a738f25da3c6742e3ab2 Mon Sep 17 00:00:00 2001 From: BM5k Date: Fri, 2 Dec 2016 18:05:02 -0700 Subject: rename charcoal theme variables for consistency --- app/assets/stylesheets/framework/gitlab-theme.scss | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/gitlab-theme.scss b/app/assets/stylesheets/framework/gitlab-theme.scss index 5cd242af91d..642d1d15c14 100644 --- a/app/assets/stylesheets/framework/gitlab-theme.scss +++ b/app/assets/stylesheets/framework/gitlab-theme.scss @@ -84,10 +84,10 @@ } } -$theme-charcoal: #3d454d; -$theme-charcoal-light: #485157; -$theme-charcoal-dark: #383f45; -$theme-charcoal-text: #b9bbbe; +$theme-charcoal-light: #b9bbbe; +$theme-charcoal: #485157; +$theme-charcoal-dark: #3d454d; +$theme-charcoal-darker: #383f45; $theme-blue-light: #becde9; $theme-blue: #2980b9; @@ -120,7 +120,7 @@ body { } &.ui_charcoal { - @include gitlab-theme($theme-charcoal-text, $theme-charcoal-light, $theme-charcoal, $theme-charcoal-dark); + @include gitlab-theme($theme-charcoal-light, $theme-charcoal, $theme-charcoal-dark, $theme-charcoal-darker); } &.ui_graphite { -- cgit v1.2.1 From 2c76665274362d463158918105465c59eccfbaa7 Mon Sep 17 00:00:00 2001 From: Ryan Harris Date: Sun, 4 Dec 2016 16:30:06 -0500 Subject: Cursor now changes to a pointer when mousing over stages on Cycle Analytics page --- app/assets/stylesheets/pages/cycle_analytics.scss | 1 + 1 file changed, 1 insertion(+) (limited to 'app') diff --git a/app/assets/stylesheets/pages/cycle_analytics.scss b/app/assets/stylesheets/pages/cycle_analytics.scss index e7a2c91003f..7c558445674 100644 --- a/app/assets/stylesheets/pages/cycle_analytics.scss +++ b/app/assets/stylesheets/pages/cycle_analytics.scss @@ -247,6 +247,7 @@ &.stage-name { width: 70%; + cursor: pointer; } &.stage-median { -- cgit v1.2.1 From 312c504f618513a87d817cad74c059506fac7a49 Mon Sep 17 00:00:00 2001 From: Regis Date: Mon, 5 Dec 2016 13:17:23 -0700 Subject: can render all tabs for pipelines - remove uneeded properties - [ci skip] --- .../javascripts/vue_pipelines_index/index.js.es6 | 46 +++++++++++----------- .../vue_pipelines_index/pipelines.js.es6 | 30 +++++++++++--- .../javascripts/vue_pipelines_index/store.js.es6 | 5 +-- app/views/projects/pipelines/index.html.haml | 13 ------ 4 files changed, 50 insertions(+), 44 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/index.js.es6 b/app/assets/javascripts/vue_pipelines_index/index.js.es6 index 2bd8d5d327f..1e4ee8875fb 100644 --- a/app/assets/javascripts/vue_pipelines_index/index.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/index.js.es6 @@ -17,30 +17,32 @@ //= require ./pipelines.js.es6 (() => { - const url = window.location.href; - if (~url.indexOf('scope') && !~url.indexOf('scope=pipelines')) return null; - const project = document.querySelector('.pipelines'); + const entry = document.querySelector('.vue-pipelines-index'); Vue.use(VueResource); - return new Vue({ - el: '.vue-pipelines-index', - data: { - scope: project.dataset.url, - store: new gl.PipelineStore(), - }, - components: { - 'vue-pipelines': gl.VuePipelines, - }, - template: ` -
    - - -
    - `, - }); + if (entry) { + return new Vue({ + el: entry, + data: { + scope: project.dataset.url, + store: new gl.PipelineStore(), + }, + components: { + 'vue-pipelines': gl.VuePipelines, + }, + template: ` +
    + + +
    + `, + }); + } + + return null; })(); diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index bba9a82e6ec..1fd3a2a4d99 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -8,6 +8,16 @@ const FIRST = '<< First'; const LAST = 'Last >>'; + const getParameterByName = (name) => { + const url = window.location.href; + name = name.replace(/[[\]]/g, '\\$&'); + const regex = new RegExp(`[?&]${name}(=([^&#]*)|&|#|$)`); + const results = regex.exec(url); + if (!results) return null; + if (!results[2]) return ''; + return decodeURIComponent(results[2].replace(/\+/g, ' ')); + }; + gl.VuePipelines = Vue.extend({ components: { runningPipeline: gl.VueRunningPipeline, @@ -25,8 +35,8 @@ pipelines: [], timeLoopInterval: '', intervalId: '', - updatedAt: '', pagenum: 1, + apiScope: 'all', count: { all: 0, running_or_pending: 0, @@ -39,11 +49,19 @@ 'store', ], created() { - const url = window.location.toString(); - if (~url.indexOf('?') && !~url.indexOf('scope=pipelines')) { - this.pagenum = url.split('?')[1].split('=')[1]; - } - this.store.fetchDataLoop.call(this, Vue, this.pagenum, this.scope); + const pagenum = getParameterByName('p'); + const scope = getParameterByName('scope'); + + if (pagenum) this.pagenum = pagenum; + if (scope) this.apiScope = scope; + + this.store.fetchDataLoop.call( + this, + Vue, + this.pagenum, + this.scope, + this.apiScope, + ); }, methods: { changepage(e, last) { diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index 79bf56b5f69..93e4a640012 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -3,7 +3,7 @@ ((gl) => { gl.PipelineStore = class { - fetchDataLoop(Vue, pageNum, url) { + fetchDataLoop(Vue, pageNum, url, apiScope) { const setVueResources = () => { Vue.activeResources = 1; }; const resetVueResources = () => { Vue.activeResources = 0; }; const addToVueResources = () => { Vue.activeResources += 1; }; @@ -27,10 +27,9 @@ }; const goFetch = () => - this.$http.get(`${url}?page=${pageNum}`) + this.$http.get(`${url}?scope=${apiScope}&page=${pageNum}`) .then((response) => { const res = JSON.parse(response.body); - Vue.set(this, 'updatedAt', res.updated_at); Vue.set(this, 'pipelines', res.pipelines); Vue.set(this, 'count', res.count); updatePipelineNums(this.count); diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index 4025a6859f2..10f1a88b65d 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -39,19 +39,6 @@ - if @pipelines.blank? %div .nothing-here-block No pipelines to show - - elsif @scope == 'branches' || @scope == 'tags' || @scope == 'running' - .table-holder - %table.table.ci-table - %thead - %th Status - %th Pipeline - %th Commit - %th Stages - %th - %th.hidden-xs - - = render @pipelines, commit_sha: true, stage: true, allow_retry: true - = paginate @pipelines, theme: 'gitlab' - else .commit-icon-svg.hidden = custom_icon("icon_commit") -- cgit v1.2.1 From 2a459e7e40443e3bd3f3ea7e1136cdfaf2a82545 Mon Sep 17 00:00:00 2001 From: Ryan Harris Date: Mon, 5 Dec 2016 16:46:18 -0500 Subject: Changed cursor for stage-nav-item instead of just stage-name --- app/assets/stylesheets/pages/cycle_analytics.scss | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/cycle_analytics.scss b/app/assets/stylesheets/pages/cycle_analytics.scss index 7c558445674..ce708106490 100644 --- a/app/assets/stylesheets/pages/cycle_analytics.scss +++ b/app/assets/stylesheets/pages/cycle_analytics.scss @@ -215,7 +215,7 @@ border-bottom: 1px solid transparent; border-right: 1px solid $border-color; background-color: $gray-light; - cursor: default; + cursor: pointer; &.active { background-color: transparent; @@ -247,7 +247,6 @@ &.stage-name { width: 70%; - cursor: pointer; } &.stage-median { -- cgit v1.2.1 From a0055435438e956b09bb92b6bbf618fbf005e46c Mon Sep 17 00:00:00 2001 From: Regis Date: Mon, 5 Dec 2016 15:52:02 -0700 Subject: tried css only approach didn't work for now - adding all icons to stages --- app/assets/javascripts/vue_icons/index.js.es6 | 55 ++++------------------ .../javascripts/vue_pipelines_index/stage.js.es6 | 4 ++ 2 files changed, 13 insertions(+), 46 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_icons/index.js.es6 b/app/assets/javascripts/vue_icons/index.js.es6 index 84a19348862..6ddf8592cbe 100644 --- a/app/assets/javascripts/vue_icons/index.js.es6 +++ b/app/assets/javascripts/vue_icons/index.js.es6 @@ -5,86 +5,49 @@ ((gl) => { gl.VueRunningIcon = Vue.extend({ template: ` - - - - - - + `, }); gl.VuePendingIcon = Vue.extend({ template: ` - - - - - - + `, }); gl.VueSuccessIcon = Vue.extend({ template: ` - - - - - - + `, }); gl.VueFailedIcon = Vue.extend({ template: ` - - - - - - + `, }); gl.VueCreatedIcon = Vue.extend({ template: ` - - - - + `, }); gl.VueCanceledIcon = Vue.extend({ template: ` - - - - - - + `, }); gl.VueSkippedIcon = Vue.extend({ template: ` - - - - - + `, }); - gl.VueUnstableIcon = Vue.extend({ + gl.VueWarningIcon = Vue.extend({ template: ` - - - - - - `, }); })(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 index e5f9178a796..38b993d4b51 100644 --- a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 @@ -10,6 +10,8 @@ 'success-icon': gl.VueSuccessIcon, 'created-icon': gl.VueCreatedIcon, 'canceled-icon': gl.VueCanceledIcon, + 'warning-icon': gl.VueWarningIcon, + 'skipped-icon': gl.VueSkippedIcon, }, props: ['stage'], computed: { @@ -32,6 +34,8 @@ + + `, }); -- cgit v1.2.1 From cc198c1f94520e756ac08ddb4c8bef6a75962cda Mon Sep 17 00:00:00 2001 From: Regis Date: Mon, 5 Dec 2016 16:01:49 -0700 Subject: change unstable to warning [ci skip] --- .../vue_pipelines_status/unstable.js.es6 | 23 ---------------------- .../vue_pipelines_status/warning.js.es6 | 23 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 23 deletions(-) delete mode 100644 app/assets/javascripts/vue_pipelines_status/unstable.js.es6 create mode 100644 app/assets/javascripts/vue_pipelines_status/warning.js.es6 (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_status/unstable.js.es6 b/app/assets/javascripts/vue_pipelines_status/unstable.js.es6 deleted file mode 100644 index 27fd29b9d80..00000000000 --- a/app/assets/javascripts/vue_pipelines_status/unstable.js.es6 +++ /dev/null @@ -1,23 +0,0 @@ -/* global Vue, gl */ -/* eslint-disable no-param-reassign */ - -((gl) => { - gl.VueUnstableScope = Vue.extend({ - components: { - 'vue-unstable-icon': gl.VueUnstableIcon, - }, - props: [ - 'pipeline', - ], - template: ` - - - - -  unstable - - - - `, - }); -})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_status/warning.js.es6 b/app/assets/javascripts/vue_pipelines_status/warning.js.es6 new file mode 100644 index 00000000000..1a8b70d82f1 --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_status/warning.js.es6 @@ -0,0 +1,23 @@ +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VueWarningScope = Vue.extend({ + components: { + 'vue-warning-icon': gl.VueWarningIcon, + }, + props: [ + 'pipeline', + ], + template: ` + + + + +  warning + + + + `, + }); +})(window.gl || (window.gl = {})); -- cgit v1.2.1 From bdd6b841b0369fcadbcd375905c37476415fa100 Mon Sep 17 00:00:00 2001 From: Regis Date: Mon, 5 Dec 2016 16:20:34 -0700 Subject: require correct file [ci skip] --- app/assets/javascripts/vue_pipelines_status/index.js.es6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_status/index.js.es6 b/app/assets/javascripts/vue_pipelines_status/index.js.es6 index 712ac2644e5..c48b4adb661 100644 --- a/app/assets/javascripts/vue_pipelines_status/index.js.es6 +++ b/app/assets/javascripts/vue_pipelines_status/index.js.es6 @@ -3,5 +3,5 @@ //= require ./running.js.es6 //= require ./canceled.js.es6 //= require ./status.js.es6 -//= require ./unstable.js.es6 +//= require ./warning.js.es6 //= require ./skipped.js.es6 -- cgit v1.2.1 From a62e5219a56e24cefef09b4466cbe42882098220 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 6 Dec 2016 13:20:46 +0100 Subject: Fix exception related to pipeline stages in view --- app/views/projects/pipelines/_with_tabs.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/projects/pipelines/_with_tabs.html.haml b/app/views/projects/pipelines/_with_tabs.html.haml index 3464e155a1b..ac139797a89 100644 --- a/app/views/projects/pipelines/_with_tabs.html.haml +++ b/app/views/projects/pipelines/_with_tabs.html.haml @@ -50,5 +50,5 @@ - if pipeline.project.build_coverage_enabled? %th Coverage %th - - pipeline.statuses.relevant.stages.each do |stage| + - pipeline.stages.each do |stage| = render 'projects/commit/ci_stage', stage: stage, statuses: pipeline.statuses.relevant.where(stage: stage) -- cgit v1.2.1 From 62b3b28b0b1522ff57e76b1a68fb2c77e0930abe Mon Sep 17 00:00:00 2001 From: Regis Date: Tue, 6 Dec 2016 09:03:45 -0700 Subject: remove all files related to Vue SVG rendering - use dynamic svg loading --- app/assets/javascripts/vue_icons/index.js.es6 | 53 ---------------------- .../javascripts/vue_pipelines_index/index.js.es6 | 1 + .../javascripts/vue_pipelines_index/stage.js.es6 | 25 +++------- .../javascripts/vue_pipelines_index/status.js.es6 | 34 ++++++++++++++ .../vue_pipelines_status/canceled.js.es6 | 23 ---------- .../vue_pipelines_status/created.js.es6 | 23 ---------- .../javascripts/vue_pipelines_status/failed.js.es6 | 23 ---------- .../javascripts/vue_pipelines_status/index.js.es6 | 7 --- .../vue_pipelines_status/pending.js.es6 | 23 ---------- .../vue_pipelines_status/running.js.es6 | 23 ---------- .../vue_pipelines_status/skipped.js.es6 | 23 ---------- .../javascripts/vue_pipelines_status/status.js.es6 | 52 --------------------- .../vue_pipelines_status/warning.js.es6 | 23 ---------- app/views/projects/pipelines/index.html.haml | 18 +++++++- 14 files changed, 58 insertions(+), 293 deletions(-) delete mode 100644 app/assets/javascripts/vue_icons/index.js.es6 create mode 100644 app/assets/javascripts/vue_pipelines_index/status.js.es6 delete mode 100644 app/assets/javascripts/vue_pipelines_status/canceled.js.es6 delete mode 100644 app/assets/javascripts/vue_pipelines_status/created.js.es6 delete mode 100644 app/assets/javascripts/vue_pipelines_status/failed.js.es6 delete mode 100644 app/assets/javascripts/vue_pipelines_status/index.js.es6 delete mode 100644 app/assets/javascripts/vue_pipelines_status/pending.js.es6 delete mode 100644 app/assets/javascripts/vue_pipelines_status/running.js.es6 delete mode 100644 app/assets/javascripts/vue_pipelines_status/skipped.js.es6 delete mode 100644 app/assets/javascripts/vue_pipelines_status/status.js.es6 delete mode 100644 app/assets/javascripts/vue_pipelines_status/warning.js.es6 (limited to 'app') diff --git a/app/assets/javascripts/vue_icons/index.js.es6 b/app/assets/javascripts/vue_icons/index.js.es6 deleted file mode 100644 index 6ddf8592cbe..00000000000 --- a/app/assets/javascripts/vue_icons/index.js.es6 +++ /dev/null @@ -1,53 +0,0 @@ -//= require vue -/* global Vue, gl */ -/* eslint-disable no-param-reassign */ - -((gl) => { - gl.VueRunningIcon = Vue.extend({ - template: ` - - `, - }); - - gl.VuePendingIcon = Vue.extend({ - template: ` - - `, - }); - - gl.VueSuccessIcon = Vue.extend({ - template: ` - - `, - }); - - gl.VueFailedIcon = Vue.extend({ - template: ` - - `, - }); - - gl.VueCreatedIcon = Vue.extend({ - template: ` - - `, - }); - - gl.VueCanceledIcon = Vue.extend({ - template: ` - - `, - }); - - gl.VueSkippedIcon = Vue.extend({ - template: ` - - `, - }); - - gl.VueWarningIcon = Vue.extend({ - template: ` - - `, - }); -})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/index.js.es6 b/app/assets/javascripts/vue_pipelines_index/index.js.es6 index 1e4ee8875fb..c454d8672b3 100644 --- a/app/assets/javascripts/vue_pipelines_index/index.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/index.js.es6 @@ -6,6 +6,7 @@ //= require vue-resource //= require ./object_assign.js.es6 +//= require ./status.js.es6 //= require ./store.js.es6 //= require ./pipeline_url.js.es6 //= require ./pipeline_head.js.es6 diff --git a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 index 38b993d4b51..d8e3f1c3dcd 100644 --- a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 @@ -3,16 +3,6 @@ ((gl) => { gl.VueStage = Vue.extend({ - components: { - 'running-icon': gl.VueRunningIcon, - 'pending-icon': gl.VuePendingIcon, - 'failed-icon': gl.VueFailedIcon, - 'success-icon': gl.VueSuccessIcon, - 'created-icon': gl.VueCreatedIcon, - 'canceled-icon': gl.VueCanceledIcon, - 'warning-icon': gl.VueWarningIcon, - 'skipped-icon': gl.VueSkippedIcon, - }, props: ['stage'], computed: { buildStatus() { @@ -21,21 +11,20 @@ tooltip() { return `has-tooltip ci-status-icon-${this.stage.status}`; }, + svg() { + return document + .querySelector( + `.${this.stage.status}-icon-svg.hidden`, + ).innerHTML; + }, }, template: ` - - - - - - - - `, }); diff --git a/app/assets/javascripts/vue_pipelines_index/status.js.es6 b/app/assets/javascripts/vue_pipelines_index/status.js.es6 new file mode 100644 index 00000000000..bbdc357035f --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_index/status.js.es6 @@ -0,0 +1,34 @@ +/* global Vue, gl */ +/* eslint-disable no-param-reassign */ + +((gl) => { + gl.VueStatusScope = Vue.extend({ + props: [ + 'pipeline', + ], + computed: { + cssClasses() { + const cssObject = {}; + cssObject['ci-status'] = true; + cssObject[`ci-${this.pipeline.details.status}`] = true; + return cssObject; + }, + svg() { + return document + .querySelector( + `.${this.pipeline.details.status}-icon-svg.hidden`, + ).innerHTML; + }, + }, + template: ` + + + + +  {{pipeline.details.status}} + + + + `, + }); +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_status/canceled.js.es6 b/app/assets/javascripts/vue_pipelines_status/canceled.js.es6 deleted file mode 100644 index 20ca8ad5ebb..00000000000 --- a/app/assets/javascripts/vue_pipelines_status/canceled.js.es6 +++ /dev/null @@ -1,23 +0,0 @@ -/* global Vue, gl */ -/* eslint-disable no-param-reassign */ - -((gl) => { - gl.VueCanceledScope = Vue.extend({ - components: { - 'vue-canceled-icon': gl.VueCanceledIcon, - }, - props: [ - 'pipeline', - ], - template: ` - - - - -  canceled - - - - `, - }); -})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_status/created.js.es6 b/app/assets/javascripts/vue_pipelines_status/created.js.es6 deleted file mode 100644 index b74566b7341..00000000000 --- a/app/assets/javascripts/vue_pipelines_status/created.js.es6 +++ /dev/null @@ -1,23 +0,0 @@ -/* global Vue, gl */ -/* eslint-disable no-param-reassign */ - -((gl) => { - gl.VueCreatedScope = Vue.extend({ - components: { - 'vue-created-icon': gl.VueCreatedIcon, - }, - props: [ - 'pipeline', - ], - template: ` - - - - -  failed - - - - `, - }); -})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_status/failed.js.es6 b/app/assets/javascripts/vue_pipelines_status/failed.js.es6 deleted file mode 100644 index 0988e2c04ab..00000000000 --- a/app/assets/javascripts/vue_pipelines_status/failed.js.es6 +++ /dev/null @@ -1,23 +0,0 @@ -/* global Vue, gl */ -/* eslint-disable no-param-reassign */ - -((gl) => { - gl.VueFailedScope = Vue.extend({ - components: { - 'vue-failed-icon': gl.VueFailedIcon, - }, - props: [ - 'pipeline', - ], - template: ` - - - - -  failed - - - - `, - }); -})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_status/index.js.es6 b/app/assets/javascripts/vue_pipelines_status/index.js.es6 deleted file mode 100644 index c48b4adb661..00000000000 --- a/app/assets/javascripts/vue_pipelines_status/index.js.es6 +++ /dev/null @@ -1,7 +0,0 @@ -//= require ./pending.js.es6 -//= require ./failed.js.es6 -//= require ./running.js.es6 -//= require ./canceled.js.es6 -//= require ./status.js.es6 -//= require ./warning.js.es6 -//= require ./skipped.js.es6 diff --git a/app/assets/javascripts/vue_pipelines_status/pending.js.es6 b/app/assets/javascripts/vue_pipelines_status/pending.js.es6 deleted file mode 100644 index 579c6f71a2e..00000000000 --- a/app/assets/javascripts/vue_pipelines_status/pending.js.es6 +++ /dev/null @@ -1,23 +0,0 @@ -/* global Vue, gl */ -/* eslint-disable no-param-reassign */ - -((gl) => { - gl.VuePendingScope = Vue.extend({ - components: { - 'vue-pending-icon': gl.VuePendingIcon, - }, - props: [ - 'pipeline', - ], - template: ` - - - - -  pending - - - - `, - }); -})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_status/running.js.es6 b/app/assets/javascripts/vue_pipelines_status/running.js.es6 deleted file mode 100644 index 57274422b15..00000000000 --- a/app/assets/javascripts/vue_pipelines_status/running.js.es6 +++ /dev/null @@ -1,23 +0,0 @@ -/* global Vue, gl */ -/* eslint-disable no-param-reassign */ - -((gl) => { - gl.VueRunningScope = Vue.extend({ - components: { - 'vue-running-icon': gl.VueRunningIcon, - }, - props: [ - 'pipeline', - ], - template: ` - - - - -  running - - - - `, - }); -})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_status/skipped.js.es6 b/app/assets/javascripts/vue_pipelines_status/skipped.js.es6 deleted file mode 100644 index da904010607..00000000000 --- a/app/assets/javascripts/vue_pipelines_status/skipped.js.es6 +++ /dev/null @@ -1,23 +0,0 @@ -/* global Vue, gl */ -/* eslint-disable no-param-reassign */ - -((gl) => { - gl.VueSkippedScope = Vue.extend({ - components: { - 'vue-skipped-icon': gl.VueSkippedIcon, - }, - props: [ - 'pipeline', - ], - template: ` - - - - -  skipped - - - - `, - }); -})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_status/status.js.es6 b/app/assets/javascripts/vue_pipelines_status/status.js.es6 deleted file mode 100644 index dfef19e21da..00000000000 --- a/app/assets/javascripts/vue_pipelines_status/status.js.es6 +++ /dev/null @@ -1,52 +0,0 @@ -/* global Vue, gl */ -/* eslint-disable no-param-reassign */ - -((gl) => { - gl.VueStatusScope = Vue.extend({ - components: { - 'vue-running-scope': gl.VueRunningScope, - 'vue-pending-scope': gl.VuePendingScope, - 'vue-failed-scope': gl.VueFailedScope, - 'vue-created-scope': gl.VueCreatedScope, - 'vue-canceled-scope': gl.VueCanceledScope, - 'vue-unstable-scope': gl.VueUnstableScope, - }, - props: [ - 'pipeline', - ], - template: ` - - - - - - - - - - - - - - - `, - }); -})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_status/warning.js.es6 b/app/assets/javascripts/vue_pipelines_status/warning.js.es6 deleted file mode 100644 index 1a8b70d82f1..00000000000 --- a/app/assets/javascripts/vue_pipelines_status/warning.js.es6 +++ /dev/null @@ -1,23 +0,0 @@ -/* global Vue, gl */ -/* eslint-disable no-param-reassign */ - -((gl) => { - gl.VueWarningScope = Vue.extend({ - components: { - 'vue-warning-icon': gl.VueWarningIcon, - }, - props: [ - 'pipeline', - ], - template: ` - - - - -  warning - - - - `, - }); -})(window.gl || (window.gl = {})); diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index 10f1a88b65d..132c21fea00 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -42,9 +42,23 @@ - else .commit-icon-svg.hidden = custom_icon("icon_commit") + .canceled-icon-svg.hidden + = custom_icon("icon_status_canceled") + .running-icon-svg.hidden + = custom_icon("icon_status_running") + .skipped-icon-svg.hidden + = custom_icon("icon_status_skipped") + .created-icon-svg.hidden + = custom_icon("icon_status_created") + .pending-icon-svg.hidden + = custom_icon("icon_status_pending") + .success-icon-svg.hidden + = custom_icon("icon_status_success") + .failed-icon-svg.hidden + = custom_icon("icon_status_failed") + .warning-icon-svg.hidden + = custom_icon("icon_status_warning") .vue-pipelines-index -= page_specific_javascript_tag('vue_icons/index.js') = page_specific_javascript_tag('vue_pagination/index.js') -= page_specific_javascript_tag('vue_pipelines_status/index.js') = page_specific_javascript_tag('vue_pipelines_index/index.js') -- cgit v1.2.1 From 20b5f5af275a2b482baa0d2ff26e806517586c79 Mon Sep 17 00:00:00 2001 From: BM5k Date: Fri, 2 Dec 2016 18:06:30 -0700 Subject: rename graphite theme variables for consistency --- app/assets/stylesheets/framework/gitlab-theme.scss | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/gitlab-theme.scss b/app/assets/stylesheets/framework/gitlab-theme.scss index 642d1d15c14..a8789ad9bf7 100644 --- a/app/assets/stylesheets/framework/gitlab-theme.scss +++ b/app/assets/stylesheets/framework/gitlab-theme.scss @@ -94,10 +94,10 @@ $theme-blue: #2980b9; $theme-blue-dark: #1970a9; $theme-blue-darker: #096099; -$theme-graphite-lighter: #ccc; -$theme-graphite-light: #777; -$theme-graphite: #666; -$theme-graphite-dark: #555; +$theme-graphite-light: #ccc; +$theme-graphite: #777; +$theme-graphite-dark: #666; +$theme-graphite-darker: #555; $theme-gray-light: #979797; $theme-gray: #373737; @@ -124,7 +124,7 @@ body { } &.ui_graphite { - @include gitlab-theme($theme-graphite-lighter, $theme-graphite-light, $theme-graphite, $theme-graphite-dark); + @include gitlab-theme($theme-graphite-light, $theme-graphite, $theme-graphite-dark, $theme-graphite-darker); } &.ui_gray { -- cgit v1.2.1 From 6cb6f58a6259c91f79489b7f5a71f413d0e0d81c Mon Sep 17 00:00:00 2001 From: BM5k Date: Fri, 2 Dec 2016 18:44:06 -0700 Subject: rename theme to match actual colors --- app/assets/stylesheets/framework/gitlab-theme.scss | 12 ++++++------ app/assets/stylesheets/pages/profiles/preferences.scss | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/gitlab-theme.scss b/app/assets/stylesheets/framework/gitlab-theme.scss index a8789ad9bf7..1b52a6a8e71 100644 --- a/app/assets/stylesheets/framework/gitlab-theme.scss +++ b/app/assets/stylesheets/framework/gitlab-theme.scss @@ -99,10 +99,10 @@ $theme-graphite: #777; $theme-graphite-dark: #666; $theme-graphite-darker: #555; -$theme-gray-light: #979797; -$theme-gray: #373737; -$theme-gray-dark: #272727; -$theme-gray-darker: #222; +$theme-black-light: #979797; +$theme-black: #373737; +$theme-black-dark: #272727; +$theme-black-darker: #222; $theme-green-light: #adc; $theme-green: #019875; @@ -127,8 +127,8 @@ body { @include gitlab-theme($theme-graphite-light, $theme-graphite, $theme-graphite-dark, $theme-graphite-darker); } - &.ui_gray { - @include gitlab-theme($theme-gray-light, $theme-gray, $theme-gray-dark, $theme-gray-darker); + &.ui_black { + @include gitlab-theme($theme-black-light, $theme-black, $theme-black-dark, $theme-black-darker); } &.ui_green { diff --git a/app/assets/stylesheets/pages/profiles/preferences.scss b/app/assets/stylesheets/pages/profiles/preferences.scss index f8da0983b77..100ace41f2a 100644 --- a/app/assets/stylesheets/pages/profiles/preferences.scss +++ b/app/assets/stylesheets/pages/profiles/preferences.scss @@ -22,8 +22,8 @@ background: $theme-graphite; } - &.ui_gray { - background: $theme-gray; + &.ui_black { + background: $theme-black; } &.ui_green { -- cgit v1.2.1 From e9e498fdc75e257bf97ba6e02c9196fe662d49e1 Mon Sep 17 00:00:00 2001 From: Regis Date: Tue, 6 Dec 2016 13:08:37 -0700 Subject: no need for running icon comp --- app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 index d9602b4209d..99ecdf3fed0 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 @@ -3,9 +3,6 @@ ((gl) => { gl.VuePipelineUrl = Vue.extend({ - components: { - 'vue-running-icon': gl.VueRunningIcon, - }, props: [ 'pipeline', ], @@ -56,7 +53,7 @@ yaml invalid stuck -- cgit v1.2.1 From 840ee74ef65eba0d9704b6a8ed4535b38c8d2675 Mon Sep 17 00:00:00 2001 From: Regis Date: Tue, 6 Dec 2016 22:33:27 -0700 Subject: remove unused components and polyfill - use interceptor for vue resource --- .../vue_pipelines_index/branch_commit.js.es6 | 64 ---------------------- .../javascripts/vue_pipelines_index/index.js.es6 | 3 +- .../vue_pipelines_index/interceptor.js.es6 | 8 +++ .../vue_pipelines_index/object_assign.js.es6 | 30 ---------- .../javascripts/vue_pipelines_index/store.js.es6 | 17 ------ 5 files changed, 9 insertions(+), 113 deletions(-) delete mode 100644 app/assets/javascripts/vue_pipelines_index/branch_commit.js.es6 create mode 100644 app/assets/javascripts/vue_pipelines_index/interceptor.js.es6 delete mode 100644 app/assets/javascripts/vue_pipelines_index/object_assign.js.es6 (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/branch_commit.js.es6 b/app/assets/javascripts/vue_pipelines_index/branch_commit.js.es6 deleted file mode 100644 index 6bebbd221fe..00000000000 --- a/app/assets/javascripts/vue_pipelines_index/branch_commit.js.es6 +++ /dev/null @@ -1,64 +0,0 @@ -/* global Vue, gl */ -/* eslint-disable no-param-reassign */ - -((gl) => { - gl.VueBranchCommit = Vue.extend({ - props: ['pipeline'], - computed: { - mailto() { - return `mailto:${this.pipeline.commit.author_email}`; - }, - alt() { - return `${this.pipeline.commit.author_name}'s avatar`; - }, - avatarUrl() { - const author = this.pipeline.commit.author; - if (author) return author.avatar_url; - return this.pipeline.commit.author_gravatar_url; - }, - }, - template: ` - -
    - -
    - - {{pipeline.ref.name}} - -
    - - - -
    - - {{pipeline.commit.short_id}} - -

    - - - - - - {{pipeline.commit.title}} - -

    - - `, - }); -})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/index.js.es6 b/app/assets/javascripts/vue_pipelines_index/index.js.es6 index c454d8672b3..25f5c796a60 100644 --- a/app/assets/javascripts/vue_pipelines_index/index.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/index.js.es6 @@ -5,7 +5,7 @@ //= require vue-resource -//= require ./object_assign.js.es6 +//= require ./interceptor.js.es6 //= require ./status.js.es6 //= require ./store.js.es6 //= require ./pipeline_url.js.es6 @@ -13,7 +13,6 @@ //= require ./stage.js.es6 //= require ./stages.js.es6 //= require ./pipeline_actions.js.es6 -//= require ./branch_commit.js.es6 //= require ./time_ago.js.es6 //= require ./pipelines.js.es6 diff --git a/app/assets/javascripts/vue_pipelines_index/interceptor.js.es6 b/app/assets/javascripts/vue_pipelines_index/interceptor.js.es6 new file mode 100644 index 00000000000..80f137ca12e --- /dev/null +++ b/app/assets/javascripts/vue_pipelines_index/interceptor.js.es6 @@ -0,0 +1,8 @@ +/* eslint-disable */ +Vue.http.interceptors.push((request, next) => { + Vue.activeResources = Vue.activeResources ? Vue.activeResources + 1 : 1; + + next(function (response) { + Vue.activeResources--; + }); +}); diff --git a/app/assets/javascripts/vue_pipelines_index/object_assign.js.es6 b/app/assets/javascripts/vue_pipelines_index/object_assign.js.es6 deleted file mode 100644 index 05a5a7da1c3..00000000000 --- a/app/assets/javascripts/vue_pipelines_index/object_assign.js.es6 +++ /dev/null @@ -1,30 +0,0 @@ -/* eslint-disable */ - -/* global Vue, gl */ -/* eslint-disable no-param-reassign */ -(() => { - if (typeof Object.assign != 'function') { - (function () { - Object.assign = function (target) { - 'use strict'; - // We must check against these specific cases. - if (target === undefined || target === null) { - throw new TypeError('Cannot convert undefined or null to object'); - } - - var output = Object(target); - for (var index = 1; index < arguments.length; index++) { - var source = arguments[index]; - if (source !== undefined && source !== null) { - for (var nextKey in source) { - if (source.hasOwnProperty(nextKey)) { - output[nextKey] = source[nextKey]; - } - } - } - } - return output; - }; - })(); - } -})(); diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index 93e4a640012..49b77454314 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -4,13 +4,6 @@ ((gl) => { gl.PipelineStore = class { fetchDataLoop(Vue, pageNum, url, apiScope) { - const setVueResources = () => { Vue.activeResources = 1; }; - const resetVueResources = () => { Vue.activeResources = 0; }; - const addToVueResources = () => { Vue.activeResources += 1; }; - const subtractFromVueResources = () => { Vue.activeResources -= 1; }; - - resetVueResources(); - const updatePipelineNums = (count) => { const { all } = count; const running = count.running_or_pending; @@ -18,14 +11,6 @@ document.querySelector('.js-running-count').innerHTML = running; }; - const resourceChecker = () => { - if (Vue.activeResources === 0) { - setVueResources(); - } else { - addToVueResources(); - } - }; - const goFetch = () => this.$http.get(`${url}?scope=${apiScope}&page=${pageNum}`) .then((response) => { @@ -34,12 +19,10 @@ Vue.set(this, 'count', res.count); updatePipelineNums(this.count); this.pageRequest = false; - subtractFromVueResources(); }, () => new Flash( 'Something went wrong on our end.', )); - resourceChecker(); goFetch(); const startTimeLoops = () => { -- cgit v1.2.1 From b12d6541835024eb74384551b84bf0e74747d0c3 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Wed, 7 Dec 2016 14:00:06 +0200 Subject: BitBuckpet importer. Refactoring. Iteration 2 --- app/controllers/import/bitbucket_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/controllers/import/bitbucket_controller.rb b/app/controllers/import/bitbucket_controller.rb index 9c97a97a5dd..12716d60e7d 100644 --- a/app/controllers/import/bitbucket_controller.rb +++ b/app/controllers/import/bitbucket_controller.rb @@ -62,7 +62,7 @@ class Import::BitbucketController < Import::BaseController end def provider - Gitlab.config.omniauth.providers.find { |provider| provider.name == 'bitbucket' } + Gitlab::OAuth::Provider.config_for('bitbucket') end def options -- cgit v1.2.1 From f55fcef3dbadf5f3003e0a51633e30e05b47c51d Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 7 Dec 2016 15:22:01 +0100 Subject: Add prototype of pipelines serializer with pagination --- app/controllers/projects/pipelines_controller.rb | 1 + app/serializers/pipeline_serializer.rb | 34 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+) (limited to 'app') diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb index 4edafaa5950..7179f3b22ea 100644 --- a/app/controllers/projects/pipelines_controller.rb +++ b/app/controllers/projects/pipelines_controller.rb @@ -18,6 +18,7 @@ class Projects::PipelinesController < Projects::ApplicationController render json: { pipelines: PipelineSerializer .new(project: @project, user: @current_user) + .with_pagination(request, response) .represent(@pipelines), updated_at: Time.now.utc, count: { diff --git a/app/serializers/pipeline_serializer.rb b/app/serializers/pipeline_serializer.rb index f7abbec7d45..c4ca5c40dba 100644 --- a/app/serializers/pipeline_serializer.rb +++ b/app/serializers/pipeline_serializer.rb @@ -1,3 +1,37 @@ class PipelineSerializer < BaseSerializer entity PipelineEntity + include API::Helpers::Pagination + Struct.new('Pagination', :request, :response) + + def with_pagination(request, response) + tap { @pagination = Struct::Pagination.new(request, response) } + end + + def paginate? + defined?(@pagination) + end + + def represent(resource, opts = {}) + if paginate? + super(paginate(resource), opts) + else + super(resource, opts) + end + end + + private + + # Methods needed by `API::Helpers::Pagination` + # + def params + @pagination.request.query_parameters + end + + def request + @pagination.request + end + + def header(header, value) + @pagination.response.headers[header] = value + end end -- cgit v1.2.1 From e4efb135e810046b1f4283db4dfe1b386ef15bad Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 7 Dec 2016 16:46:37 +0100 Subject: Add status entity prototype and expose in pipeline --- app/serializers/pipeline_entity.rb | 2 +- app/serializers/status_entity.rb | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 app/serializers/status_entity.rb (limited to 'app') diff --git a/app/serializers/pipeline_entity.rb b/app/serializers/pipeline_entity.rb index cf99e628d5f..a07abb4bec0 100644 --- a/app/serializers/pipeline_entity.rb +++ b/app/serializers/pipeline_entity.rb @@ -12,7 +12,7 @@ class PipelineEntity < Grape::Entity end expose :details do - expose :status + expose :detailed_status, as: :status, using: StatusEntity expose :duration expose :finished_at expose :stages_with_statuses, as: :stages, using: PipelineStageEntity diff --git a/app/serializers/status_entity.rb b/app/serializers/status_entity.rb new file mode 100644 index 00000000000..ae14dd57f61 --- /dev/null +++ b/app/serializers/status_entity.rb @@ -0,0 +1,8 @@ +class StatusEntity < Grape::Entity + include RequestAwareEntity + + expose :icon, :text, :label, :title + + expose :has_details?, as: :has_details + expose :details_path +end -- cgit v1.2.1 From e86c5570fbfd1d5276eb67b16303599fc747a7a0 Mon Sep 17 00:00:00 2001 From: Regis Date: Wed, 7 Dec 2016 09:51:51 -0700 Subject: fix status for svg's on status column --- app/assets/javascripts/vue_pipelines_index/status.js.es6 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/status.js.es6 b/app/assets/javascripts/vue_pipelines_index/status.js.es6 index bbdc357035f..ed65841e6a7 100644 --- a/app/assets/javascripts/vue_pipelines_index/status.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/status.js.es6 @@ -10,13 +10,13 @@ cssClasses() { const cssObject = {}; cssObject['ci-status'] = true; - cssObject[`ci-${this.pipeline.details.status}`] = true; + cssObject[`ci-${this.pipeline.details.status.text}`] = true; return cssObject; }, svg() { return document .querySelector( - `.${this.pipeline.details.status}-icon-svg.hidden`, + `.${this.pipeline.details.status.text}-icon-svg.hidden`, ).innerHTML; }, }, @@ -25,7 +25,7 @@ -  {{pipeline.details.status}} +  {{pipeline.details.status.text}} -- cgit v1.2.1 From c9b6392452f586eafc08605b71f6c696a5ca12d7 Mon Sep 17 00:00:00 2001 From: Regis Date: Wed, 7 Dec 2016 10:05:39 -0700 Subject: conform to status object for svg icon names --- app/assets/javascripts/vue_pipelines_index/stage.js.es6 | 2 +- app/assets/javascripts/vue_pipelines_index/status.js.es6 | 6 ++---- app/views/projects/pipelines/index.html.haml | 16 ++++++++-------- 3 files changed, 11 insertions(+), 13 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 index d8e3f1c3dcd..b313317b0bb 100644 --- a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 @@ -14,7 +14,7 @@ svg() { return document .querySelector( - `.${this.stage.status}-icon-svg.hidden`, + `.icon_status_${this.stage.status}`, ).innerHTML; }, }, diff --git a/app/assets/javascripts/vue_pipelines_index/status.js.es6 b/app/assets/javascripts/vue_pipelines_index/status.js.es6 index ed65841e6a7..2f362d0c69e 100644 --- a/app/assets/javascripts/vue_pipelines_index/status.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/status.js.es6 @@ -15,14 +15,12 @@ }, svg() { return document - .querySelector( - `.${this.pipeline.details.status.text}-icon-svg.hidden`, - ).innerHTML; + .querySelector(`.${this.pipeline.details.status.icon}`).innerHTML; }, }, template: ` - +  {{pipeline.details.status.text}} diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index 132c21fea00..fd1baa6195b 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -42,21 +42,21 @@ - else .commit-icon-svg.hidden = custom_icon("icon_commit") - .canceled-icon-svg.hidden + .icon_status_canceled.hidden = custom_icon("icon_status_canceled") - .running-icon-svg.hidden + .icon_status_running.hidden = custom_icon("icon_status_running") - .skipped-icon-svg.hidden + .icon_status_skipped.hidden = custom_icon("icon_status_skipped") - .created-icon-svg.hidden + .icon_status_created.hidden = custom_icon("icon_status_created") - .pending-icon-svg.hidden + .icon_status_pending.hidden = custom_icon("icon_status_pending") - .success-icon-svg.hidden + .icon_status_success.hidden = custom_icon("icon_status_success") - .failed-icon-svg.hidden + .icon_status_failed.hidden = custom_icon("icon_status_failed") - .warning-icon-svg.hidden + .icon_status_warning.hidden = custom_icon("icon_status_warning") .vue-pipelines-index -- cgit v1.2.1 From 64b66c9a8327b9309f6bad6402a36a795f957fd1 Mon Sep 17 00:00:00 2001 From: Regis Date: Wed, 7 Dec 2016 13:35:26 -0700 Subject: use API values for pagination --- app/assets/javascripts/vue_pagination/index.js.es6 | 31 +++++++++++----------- .../vue_pipelines_index/pipelines.js.es6 | 14 +++++----- .../javascripts/vue_pipelines_index/store.js.es6 | 15 +++++++++++ 3 files changed, 39 insertions(+), 21 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pagination/index.js.es6 b/app/assets/javascripts/vue_pagination/index.js.es6 index 4f83671e83d..961f7101fb1 100644 --- a/app/assets/javascripts/vue_pagination/index.js.es6 +++ b/app/assets/javascripts/vue_pagination/index.js.es6 @@ -2,7 +2,6 @@ /* eslint-disable no-param-reassign, no-plusplus */ ((gl) => { - const PAGINATION_SIZE = 30; const PAGINATION_UI_BUTTON_LIMIT = 4; const SPREAD = '...'; const PREV = 'Prev'; @@ -13,24 +12,26 @@ gl.VueGlPagination = Vue.extend({ props: [ 'changepage', - 'count', - 'pagenum', + 'pageInfo', ], computed: { - last() { - return Math.ceil(+this.count / PAGINATION_SIZE); + prev() { + return this.pageInfo.previousPage; + }, + next() { + return this.pageInfo.nextPage; }, getItems() { - const total = +this.last; - const page = +this.pagenum; + const total = this.pageInfo.totalPages; + const page = this.pageInfo.page; const items = []; - if (page > 1) items.push({ title: FIRST, where: 1 }); + if (page > 1) items.push({ title: FIRST }); if (page > 1) { - items.push({ title: PREV, where: page - 1 }); + items.push({ title: PREV }); } else { - items.push({ title: PREV, where: page - 1, disabled: true }); + items.push({ title: PREV, disabled: true }); } if (page > 6) items.push({ title: SPREAD, separator: true }); @@ -40,7 +41,7 @@ for (let i = start; i <= end; i++) { const isActive = i === page; - items.push({ title: i, active: isActive, where: i }); + items.push({ title: i, active: isActive }); } if (total - page > PAGINATION_UI_BUTTON_LIMIT) { @@ -48,12 +49,12 @@ } if (page === total) { - items.push({ title: NEXT, where: page + 1, disabled: true }); + items.push({ title: NEXT, disabled: true }); } else if (total - page >= 1) { - items.push({ title: NEXT, where: page + 1 }); + items.push({ title: NEXT }); } - if (total - page >= 1) items.push({ title: LAST, where: total }); + if (total - page >= 1) items.push({ title: LAST }); return items; }, @@ -69,7 +70,7 @@ }' > {{item.title}} diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index 1fd3a2a4d99..3f35c07b628 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -35,8 +35,8 @@ pipelines: [], timeLoopInterval: '', intervalId: '', - pagenum: 1, apiScope: 'all', + pageInfo: {}, count: { all: 0, running_or_pending: 0, @@ -64,13 +64,14 @@ ); }, methods: { - changepage(e, last) { + changepage(e) { const text = e.target.innerText; + const { totalPages, nextPage, previousPage } = this.pageInfo; if (text === SPREAD) return; if (/^-?[\d.]+(?:e-?\d+)?$/.test(text)) this.pagenum = +text; - if (text === LAST) this.pagenum = last; - if (text === NEXT) this.pagenum = +this.pagenum + 1; - if (text === PREV) this.pagenum = +this.pagenum - 1; + if (text === LAST) this.pagenum = totalPages; + if (text === NEXT) this.pagenum = nextPage; + if (text === PREV) this.pagenum = previousPage; if (text === FIRST) this.pagenum = 1; window.history.pushState({}, null, `?p=${this.pagenum}`); @@ -141,10 +142,11 @@
    diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index 49b77454314..7d8316d6d20 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -2,6 +2,17 @@ /* eslint-disable no-param-reassign, no-underscore-dangle */ ((gl) => { + const pageValues = (headers) => { + const values = {}; + values.perPage = +headers['X-Per-Page']; + values.page = +headers['X-Page']; + values.total = +headers['X-Total']; + values.totalPages = +headers['X-Total-Pages']; + values.nextPage = +headers['X-Next-Page']; + values.previousPage = +headers['X-Prev-Page']; + return values; + }; + gl.PipelineStore = class { fetchDataLoop(Vue, pageNum, url, apiScope) { const updatePipelineNums = (count) => { @@ -14,9 +25,13 @@ const goFetch = () => this.$http.get(`${url}?scope=${apiScope}&page=${pageNum}`) .then((response) => { + const pageInfo = pageValues(response.headers); + Vue.set(this, 'pageInfo', pageInfo); + const res = JSON.parse(response.body); Vue.set(this, 'pipelines', res.pipelines); Vue.set(this, 'count', res.count); + updatePipelineNums(this.count); this.pageRequest = false; }, () => new Flash( -- cgit v1.2.1 From 813be933969956acd1ce401dce90a4c552a6f9d3 Mon Sep 17 00:00:00 2001 From: Regis Date: Wed, 7 Dec 2016 15:20:30 -0700 Subject: default to page 1 if url is clean --- app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 | 1 + 1 file changed, 1 insertion(+) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index 3f35c07b628..9f7e71dbee9 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -37,6 +37,7 @@ intervalId: '', apiScope: 'all', pageInfo: {}, + pagenum: 1, count: { all: 0, running_or_pending: 0, -- cgit v1.2.1 From c3c9122d1e6aa532ad213394c4758653d4cf3874 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Mon, 5 Dec 2016 17:04:36 +0000 Subject: Adds new hover state Fixes the line that connects the dots Adds style for the badge Add new style for status text Fix badge style Adjust font weight --- app/assets/stylesheets/framework/variables.scss | 7 +++++ app/assets/stylesheets/pages/pipelines.scss | 34 ++++++++++++++++------ .../commit/_pipeline_status_group.html.haml | 2 +- 3 files changed, 33 insertions(+), 10 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 18716813c48..0591801d259 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -571,3 +571,10 @@ $body-text-shadow: rgba(255,255,255,0.01); */ $ui-dev-kit-example-color: #bbb; $ui-dev-kit-example-border: #ddd; + +/* +Pipeline Graph +*/ +$stage-hover-bg: #eaf3fc; +$stage-hover-border: #d1e7fc; +$stage-bagde-text: #d4d4d4; diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 08062b85504..cc8d4dd9544 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -363,15 +363,22 @@ .build { border: 1px solid $border-color; + border-radius: 30px; background-color: $white-light; + color: $gl-text-color; position: relative; padding: 7px 10px 8px; - border-radius: 30px; width: 186px; margin-bottom: 10px; &:hover { - background-color: $gray-lighter; + background-color: $stage-hover-bg; + border: 1px solid $stage-hover-border; + + .ci-status-text, + .dropdown-counter-bagde { + color: $gl-text-color; + } } &.playable { @@ -411,14 +418,14 @@ } .ci-status-text { - width: 135px; + max-width: 110px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; - vertical-align: middle; + vertical-align: bottom; display: inline-block; position: relative; - top: -1px; + font-weight: 100; } a { @@ -435,7 +442,7 @@ flex-grow: 1; .ci-status-text { - max-width: 112px; + max-width: 110px; width: auto; } } @@ -480,7 +487,7 @@ } .ci-status-text { - width: 112px; + width: 110px; } .arrow { @@ -520,9 +527,18 @@ } } + .dropdown-counter-bagde { + float: right; + color: $stage-bagde-text; + font-weight: 100; + font-size: 13px; + margin-top: 1px; + margin-right: 2px; + } + svg { vertical-align: middle; - margin-right: 5px; + margin-right: 3px; } // Connect first build in each stage with right horizontal line @@ -531,7 +547,7 @@ content: ''; position: absolute; top: 48%; - right: -48px; + right: -49px; border-top: 2px solid $border-color; width: 48px; height: 1px; diff --git a/app/views/projects/commit/_pipeline_status_group.html.haml b/app/views/projects/commit/_pipeline_status_group.html.haml index 2b26ad9d6fa..1e91e249fe9 100644 --- a/app/views/projects/commit/_pipeline_status_group.html.haml +++ b/app/views/projects/commit/_pipeline_status_group.html.haml @@ -4,7 +4,7 @@ = ci_icon_for_status(group_status) %span.ci-status-text = name - %span.badge= subject.size + %span.dropdown-counter-bagde= subject.size .dropdown-menu.grouped-pipeline-dropdown .arrow %ul -- cgit v1.2.1 From f9c103c2f314a2f9edbdfb93a26ace597d62e7e6 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Tue, 6 Dec 2016 11:56:50 +0000 Subject: Fix tooltip to show the all name CSS - Changes to look like newest mockups - Simplifies nested elements - Divides nodes from lines Remove is playable from left side Remove nested elements in scss Improve dropdown Focus state Fix scss linter Remove not used css Fix typo --- app/assets/stylesheets/pages/pipelines.scss | 498 ++++++++++----------- .../projects/ci/builds/_build_pipeline.html.haml | 6 +- .../commit/_pipeline_status_group.html.haml | 2 +- 3 files changed, 231 insertions(+), 275 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index cc8d4dd9544..cd7df7beda8 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -287,15 +287,40 @@ } // Pipeline visualization +.pipeline-actions { + border-bottom: none; +} -.toggle-pipeline-btn { - background-color: $gray-dark; +.tab-pane { + &.pipelines { + .ci-table { + min-width: 900px; + } - &.graph-collapsed { - background-color: $white-light; + .content-list.pipelines { + overflow: auto; + } + + .stage { + max-width: 100px; + width: 100px; + } + + .pipeline-actions { + min-width: initial; + } + } + + &.builds { + .ci-table { + tr { + height: 71px; + } + } } } +// Pipeline graph .pipeline-graph { width: 100%; background-color: $background-color; @@ -304,52 +329,120 @@ white-space: nowrap; transition: max-height 0.3s, padding 0.3s; - &.graph-collapsed { - max-height: 0; - padding: 0 16px; - } -} - -.pipeline-visualization { - position: relative; - ul { padding: 0; } -} -.stage-column { - display: inline-block; - vertical-align: top; + a { + text-decoration: none; + color: $gl-text-color-light; + } - &:not(:last-child) { - margin-right: 44px; + svg { + vertical-align: middle; + margin-right: 3px; } - &.left-margin { - &:not(:first-child) { - margin-left: 44px; + .stage-column { + display: inline-block; + vertical-align: top; - .left-connector { - &::before { - content: ''; - position: absolute; - top: 48%; - left: -48px; - border-top: 2px solid $border-color; - width: 48px; - height: 1px; + &:not(:last-child) { + margin-right: 44px; + } + + &.left-margin { + &:not(:first-child) { + margin-left: 44px; + + .left-connector { + &::before { + content: ''; + position: absolute; + top: 48%; + left: -48px; + border-top: 2px solid $border-color; + width: 48px; + height: 1px; + } } } } - } - &.no-margin { - margin: 0; - } + &.no-margin { + margin: 0; + } - li { - list-style: none; + li { + list-style: none; + } + + &:last-child { + .build { + // Remove right connecting horizontal line from first build in last stage + &:first-child { + &::after { + border: none; + } + } + // Remove right curved connectors from all builds in last stage + &:not(:first-child) { + &::after { + border: none; + } + } + // Remove opposite curve + .curve { + &::before { + display: none; + } + } + } + } + + &:first-child { + .build { + // Remove left curved connectors from all builds in first stage + &:not(:first-child) { + &::before { + border: none; + } + } + // Remove opposite curve + .curve { + &::after { + display: none; + } + } + } + } + + // Curve first child connecting lines in opposite direction + .curve { + display: none; + + &::before, + &::after { + content: ''; + width: 21px; + height: 25px; + position: absolute; + top: -31px; + border-top: 2px solid $border-color; + } + + &::after { + left: -44px; + border-right: 2px solid $border-color; + border-radius: 0 20px; + } + + &::before { + right: -44px; + border-left: 2px solid $border-color; + border-radius: 20px 0 0; + } + } } .stage-name { @@ -365,24 +458,12 @@ border: 1px solid $border-color; border-radius: 30px; background-color: $white-light; - color: $gl-text-color; position: relative; - padding: 7px 10px 8px; + padding: 8px 10px 9px; width: 186px; margin-bottom: 10px; - &:hover { - background-color: $stage-hover-bg; - border: 1px solid $stage-hover-border; - - .ci-status-text, - .dropdown-counter-bagde { - color: $gl-text-color; - } - } - &.playable { - svg { height: 13px; width: 20px; @@ -395,150 +476,56 @@ } } - .build-content { - display: -ms-flexbox; - display: -webkit-flex; - display: flex; - width: 164px; - - .ci-status-icon { - svg { - height: 20px; - width: 20px; - } - } - - .tooltip { - white-space: nowrap; - - .tooltip-inner { - overflow: hidden; - text-overflow: ellipsis; - } - } - - .ci-status-text { - max-width: 110px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - vertical-align: bottom; - display: inline-block; - position: relative; - font-weight: 100; - } - - a { - color: $gl-text-color-light; - text-decoration: none; - } + &:hover { + background-color: $stage-hover-bg; + border: 1px solid $stage-hover-border; + a, + .dropdown-counter-badge, .dropdown-menu-toggle { - background-color: transparent; - border: none; - width: auto; - padding: 0; - color: $gl-text-color-light; - flex-grow: 1; - - .ci-status-text { - max-width: 110px; - width: auto; - } + color: $gl-text-color; } - .grouped-pipeline-dropdown { - padding: 0; - width: 186px; - left: auto; - right: -197px; - top: -9px; - - ul { - max-height: 245px; - overflow: auto; - - li:first-child { - padding-top: 8px; - } - - li:last-child { - padding-bottom: 8px; - } - } + .grouped-pipeline-dropdown a { + color: $gl-text-color-light; - a { + &:hover { color: $gl-text-color; - padding: 7px 8px 8px; - - &:hover { - background-color: $blue-light-transparent; - border-radius: 3px; - - .ci-status-text { - text-decoration: none; - } - } - } - - svg { - width: 14px; - height: 14px; - } - - .ci-status-text { - width: 110px; } + } + } - .arrow { - &::before, - &::after { - content: ''; - display: inline-block; - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; - top: 18px; - } - - &::before { - left: -5px; - margin-top: -6px; - border-width: 7px 5px 7px 0; - border-right-color: $border-color; - } + .ci-status-icon svg { + height: 20px; + width: 20px; + } - &::after { - left: -4px; - margin-top: -9px; - border-width: 10px 7px 10px 0; - border-right-color: $white-light; - } - } + .arrow { + &::before, + &::after { + content: ''; + display: inline-block; + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; + top: 18px; } - .badge { - background-color: $gray-darker; - color: $gl-text-color-light; - font-weight: normal; - margin-left: $btn-xs-side-margin; + &::before { + left: -5px; + margin-top: -6px; + border-width: 7px 5px 7px 0; + border-right-color: $border-color; } - } - - .dropdown-counter-bagde { - float: right; - color: $stage-bagde-text; - font-weight: 100; - font-size: 13px; - margin-top: 1px; - margin-right: 2px; - } - svg { - vertical-align: middle; - margin-right: 3px; + &::after { + left: -4px; + margin-top: -9px; + border-width: 10px 7px 10px 0; + border-right-color: $white-light; + } } // Connect first build in each stage with right horizontal line @@ -595,113 +582,86 @@ } } - &:last-child { - .build { - // Remove right connecting horizontal line from first build in last stage - &:first-child { - &::after { - border: none; - } - } - // Remove right curved connectors from all builds in last stage - &:not(:first-child) { - &::after { - border: none; - } - } - // Remove opposite curve - .curve { - &::before { - display: none; - } - } - } - } - - &:first-child { - .build { - // Remove left curved connectors from all builds in first stage - &:not(:first-child) { - &::before { - border: none; - } - } - // Remove opposite curve - .curve { - &::after { - display: none; - } - } - } + .ci-status-text { + max-width: 110px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + vertical-align: bottom; + display: inline-block; + position: relative; + font-weight: 100; } - // Curve first child connecting lines in opposite direction - .curve { - display: none; + .dropdown-menu-toggle { + background-color: transparent; + border: none; + padding: 0; + color: $gl-text-color-light; + flex-grow: 1; - &::before, - &::after { - content: ''; - width: 21px; - height: 25px; - position: absolute; - top: -32px; - border-top: 2px solid $border-color; + &:focus { + outline: none; } - &::after { - left: -44px; - border-right: 2px solid $border-color; - border-radius: 0 20px; - } + &:hover { + color: $gl-text-color; - &::before { - right: -44px; - border-left: 2px solid $border-color; - border-radius: 20px 0 0; + .dropdown-counter-bagde { + color: $gl-text-color; + } } } -} -.pipeline-actions { - border-bottom: none; -} - -.toggle-pipeline-btn { - - .fa { - color: $dropdown-header-color; + .dropdown-counter-bagde { + float: right; + color: $stage-bagde-text; + font-weight: 100; + font-size: 13px; + margin-top: 1px; + margin-right: 2px; } -} -.tab-pane { + .grouped-pipeline-dropdown { + padding: 0; + width: 191px; + left: auto; + right: -206px; + top: -11px; + box-shadow: 0 1px 5px $black-transparent; + + ul { + max-height: 245px; + overflow: auto; - &.pipelines { + li { + padding-top: 1px; + padding-bottom: 1px; + } - .ci-table { - min-width: 900px; - } + li:first-child { + padding-top: 9px; + } - .content-list.pipelines { - overflow: auto; + li:last-child { + padding-bottom: 9px; + } } - .stage { - max-width: 100px; - width: 100px; - } + a { + color: $gl-text-color-light; + padding: 7px 8px 8px; - .pipeline-actions { - min-width: initial; + &:hover { + background-color: $stage-hover-bg; + border-radius: 3px; + color: $gl-text-color; + } } - } - - &.builds { - .ci-table { - tr { - height: 71px; - } + .ci-status-icon svg { + height: 18px; + width: 18px; } } } diff --git a/app/views/projects/ci/builds/_build_pipeline.html.haml b/app/views/projects/ci/builds/_build_pipeline.html.haml index 423a1282eb2..ac90d3278e2 100644 --- a/app/views/projects/ci/builds/_build_pipeline.html.haml +++ b/app/views/projects/ci/builds/_build_pipeline.html.haml @@ -1,9 +1,5 @@ - is_playable = subject.playable? && can?(current_user, :update_build, @project) -- if is_playable - = link_to play_namespace_project_build_path(subject.project.namespace, subject.project, subject, return_to: request.original_url), method: :post, data: { toggle: 'tooltip', title: "#{subject.name} - play", container: '.pipeline-graph', placement: 'bottom' } do - = ci_icon_for_status('play') - .ci-status-text= subject.name -- elsif can?(current_user, :read_build, @project) +- if can?(current_user, :read_build, @project) = link_to namespace_project_build_path(subject.project.namespace, subject.project, subject), data: { toggle: 'tooltip', title: "#{subject.name} - #{subject.status}", container: '.pipeline-graph', placement: 'bottom' } do %span{class: "ci-status-icon ci-status-icon-#{subject.status}"} = ci_icon_for_status(subject.status) diff --git a/app/views/projects/commit/_pipeline_status_group.html.haml b/app/views/projects/commit/_pipeline_status_group.html.haml index 1e91e249fe9..8b782d38193 100644 --- a/app/views/projects/commit/_pipeline_status_group.html.haml +++ b/app/views/projects/commit/_pipeline_status_group.html.haml @@ -4,7 +4,7 @@ = ci_icon_for_status(group_status) %span.ci-status-text = name - %span.dropdown-counter-bagde= subject.size + %span.dropdown-counter-badge= subject.size .dropdown-menu.grouped-pipeline-dropdown .arrow %ul -- cgit v1.2.1 From bd30f75af67240d4069d4a4559faecf4ad7fab5a Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 7 Dec 2016 18:03:40 +0000 Subject: Adds actions to the nodes Improve CSS for dropdown actions --- app/assets/stylesheets/framework/variables.scss | 2 +- app/assets/stylesheets/pages/pipelines.scss | 84 ++++++++++++++++------ .../projects/ci/builds/_build_pipeline.html.haml | 22 ++++++ .../commit/_pipeline_status_group.html.haml | 2 +- 4 files changed, 86 insertions(+), 24 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 0591801d259..cfb2ed9321b 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -577,4 +577,4 @@ Pipeline Graph */ $stage-hover-bg: #eaf3fc; $stage-hover-border: #d1e7fc; -$stage-bagde-text: #d4d4d4; +$stage-badge-text: #d4d4d4; diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index cd7df7beda8..81cd397ef14 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -463,19 +463,6 @@ width: 186px; margin-bottom: 10px; - &.playable { - svg { - height: 13px; - width: 20px; - position: relative; - top: 1px; - - path { - fill: $layout-link-gray; - } - } - } - &:hover { background-color: $stage-hover-bg; border: 1px solid $stage-hover-border; @@ -607,15 +594,15 @@ &:hover { color: $gl-text-color; - .dropdown-counter-bagde { + .dropdown-counter-badge { color: $gl-text-color; } } } - .dropdown-counter-bagde { + .dropdown-counter-badge { float: right; - color: $stage-bagde-text; + color: $stage-badge-text; font-weight: 100; font-size: 13px; margin-top: 1px; @@ -630,27 +617,49 @@ top: -11px; box-shadow: 0 1px 5px $black-transparent; + a { + display: inline-block; + + &:hover { + background-color: $stage-hover-bg; + } + } + ul { max-height: 245px; overflow: auto; li { - padding-top: 1px; - padding-bottom: 1px; + padding-top: 2px; + margin: 0 5px; } li:first-child { - padding-top: 9px; + padding-top: 6px; } li:last-child { - padding-bottom: 9px; + padding-bottom: 6px; } } - a { + .dropdown-build { color: $gl-text-color-light; - padding: 7px 8px 8px; + + a { + padding: 7px 8px 8px; + } + + a.ci-action-icon-container { + padding: 0; + font-size: 11px; + float: right; + margin-top: 5px; + + i { + font-size: 11px; + } + } &:hover { background-color: $stage-hover-bg; @@ -665,3 +674,34 @@ } } } + +// Action Icons +.ci-action-icon-container { + padding: 0; + + .ci-action-icon-wrapper { + display: inline-block; + float: right; + + i { + color: $stage-badge-text; + border-radius: 100%; + border: 1px solid $stage-badge-text; + text-align: center; + display: table-cell; + vertical-align: middle; + padding: 5px; + font-size: 13px; + + &:hover { + color: $gl-text-color; + background-color: $stage-hover-bg; + border: 1px solid $gl-text-color; + } + } + + .ci-play-icon { + padding: 5px 4px 5px 7px; + } + } +} diff --git a/app/views/projects/ci/builds/_build_pipeline.html.haml b/app/views/projects/ci/builds/_build_pipeline.html.haml index ac90d3278e2..41b9265fe5e 100644 --- a/app/views/projects/ci/builds/_build_pipeline.html.haml +++ b/app/views/projects/ci/builds/_build_pipeline.html.haml @@ -1,9 +1,31 @@ - is_playable = subject.playable? && can?(current_user, :update_build, @project) +- can_cancel = subject.active? && can?(current_user, :update_build, @project) +- can_retry = subject.retryable? && can?(current_user, :update_build, @project) +- can_stop = subject.complete? && subject.stops_environment? && can?(current_user, :update_build, @project) + - if can?(current_user, :read_build, @project) = link_to namespace_project_build_path(subject.project.namespace, subject.project, subject), data: { toggle: 'tooltip', title: "#{subject.name} - #{subject.status}", container: '.pipeline-graph', placement: 'bottom' } do %span{class: "ci-status-icon ci-status-icon-#{subject.status}"} = ci_icon_for_status(subject.status) .ci-status-text= subject.name + + - if is_playable + = link_to play_namespace_project_build_path(subject.project.namespace, subject.project, subject, return_to: request.original_url), method: :post, title: "#{subject.name} - Play", class: 'ci-action-icon-container' do + %i.ci-action-icon-wrapper + = icon('play', class: 'ci-play-icon') + - elsif can_cancel + = link_to cancel_namespace_project_build_path(subject.project.namespace, subject.project, subject, return_to: request.original_url), method: :post, title: "#{subject.name} - Cancel", class: 'ci-action-icon-container' do + %i.ci-action-icon-wrapper + = icon('ban') + - elsif can_retry + = link_to retry_namespace_project_build_path(subject.project.namespace, subject.project, subject, return_to: request.original_url), method: :post, title: "#{subject.name} - Retry", class: 'ci-action-icon-container' do + %i.ci-action-icon-wrapper + = icon('refresh') + - elsif can_stop + = link_to play_namespace_project_build_path(subject.project.namespace, subject.project, subject, return_to: request.original_url), method: :post, title: "#{subject.name} - Stop", class: 'ci-action-icon-container' do + %i.ci-action-icon-wrapper + = icon('stop') + - else %span{class: "ci-status-icon ci-status-icon-#{subject.status}"} = ci_icon_for_status(subject.status) diff --git a/app/views/projects/commit/_pipeline_status_group.html.haml b/app/views/projects/commit/_pipeline_status_group.html.haml index 8b782d38193..2d198d1b389 100644 --- a/app/views/projects/commit/_pipeline_status_group.html.haml +++ b/app/views/projects/commit/_pipeline_status_group.html.haml @@ -9,5 +9,5 @@ .arrow %ul - subject.each do |status| - %li + %li.dropdown-build = render "projects/#{status.to_partial_path}_pipeline", subject: status -- cgit v1.2.1 From 2320a5c7118084ed999b9fa0966c3315b94edd67 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 7 Dec 2016 20:28:29 +0000 Subject: Adds new icons for pipeline graph Fix padding Fix hover state of icon --- app/assets/stylesheets/pages/pipelines.scss | 5 +- app/helpers/ci_status_helper.rb | 66 ++++++++++++++-------- .../shared/icons/_icon_graph_job_cancelled.svg | 1 + app/views/shared/icons/_icon_graph_job_created.svg | 1 + app/views/shared/icons/_icon_graph_job_failed.svg | 1 + app/views/shared/icons/_icon_graph_job_manual.svg | 1 + app/views/shared/icons/_icon_graph_job_pending.svg | 1 + app/views/shared/icons/_icon_graph_job_running.svg | 1 + app/views/shared/icons/_icon_graph_job_skipped.svg | 1 + app/views/shared/icons/_icon_graph_job_success.svg | 1 + app/views/shared/icons/_icon_graph_job_warning.svg | 1 + 11 files changed, 56 insertions(+), 24 deletions(-) create mode 100755 app/views/shared/icons/_icon_graph_job_cancelled.svg create mode 100755 app/views/shared/icons/_icon_graph_job_created.svg create mode 100755 app/views/shared/icons/_icon_graph_job_failed.svg create mode 100755 app/views/shared/icons/_icon_graph_job_manual.svg create mode 100755 app/views/shared/icons/_icon_graph_job_pending.svg create mode 100755 app/views/shared/icons/_icon_graph_job_running.svg create mode 100755 app/views/shared/icons/_icon_graph_job_skipped.svg create mode 100755 app/views/shared/icons/_icon_graph_job_success.svg create mode 100755 app/views/shared/icons/_icon_graph_job_warning.svg (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 81cd397ef14..06b078d5345 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -647,7 +647,7 @@ color: $gl-text-color-light; a { - padding: 7px 8px 8px; + padding: 6px 8px 7px; } a.ci-action-icon-container { @@ -692,11 +692,12 @@ vertical-align: middle; padding: 5px; font-size: 13px; + background: $white-light; &:hover { color: $gl-text-color; background-color: $stage-hover-bg; - border: 1px solid $gl-text-color; + border: 1px solid $stage-hover-bg; } } diff --git a/app/helpers/ci_status_helper.rb b/app/helpers/ci_status_helper.rb index 8e19752a8a1..999d279e5b9 100644 --- a/app/helpers/ci_status_helper.rb +++ b/app/helpers/ci_status_helper.rb @@ -43,32 +43,54 @@ module CiStatusHelper status.humanize end - def ci_icon_for_status(status) + def ci_icon_for_status(status, graph: nil) if detailed_status?(status) return custom_icon(status.icon) end - icon_name = - case status - when 'success' - 'icon_status_success' - when 'success_with_warnings' - 'icon_status_warning' - when 'failed' - 'icon_status_failed' - when 'pending' - 'icon_status_pending' - when 'running' - 'icon_status_running' - when 'play' - 'icon_play' - when 'created' - 'icon_status_created' - when 'skipped' - 'icon_status_skipped' - else - 'icon_status_canceled' - end + if graph + icon_name = + case status + when 'success' + 'icon_graph_job_success' + when 'success_with_warnings' + 'icon_graph_job_warning' + when 'failed' + 'icon_graph_job_failed' + when 'pending' + 'icon_graph_job_pending' + when 'running' + 'icon_graph_job_running' + when 'created' + 'icon_graph_job_created' + when 'skipped' + 'icon_graph_job_skipped' + else + 'icon_graph_job_canceled' + end + else + icon_name = + case status + when 'success' + 'icon_status_success' + when 'success_with_warnings' + 'icon_status_warning' + when 'failed' + 'icon_status_failed' + when 'pending' + 'icon_status_pending' + when 'running' + 'icon_status_running' + when 'play' + 'icon_play' + when 'created' + 'icon_status_created' + when 'skipped' + 'icon_status_skipped' + else + 'icon_status_canceled' + end + end custom_icon(icon_name) end diff --git a/app/views/shared/icons/_icon_graph_job_cancelled.svg b/app/views/shared/icons/_icon_graph_job_cancelled.svg new file mode 100755 index 00000000000..bd5d04e1cd7 --- /dev/null +++ b/app/views/shared/icons/_icon_graph_job_cancelled.svg @@ -0,0 +1 @@ + diff --git a/app/views/shared/icons/_icon_graph_job_created.svg b/app/views/shared/icons/_icon_graph_job_created.svg new file mode 100755 index 00000000000..326ad04e017 --- /dev/null +++ b/app/views/shared/icons/_icon_graph_job_created.svg @@ -0,0 +1 @@ + diff --git a/app/views/shared/icons/_icon_graph_job_failed.svg b/app/views/shared/icons/_icon_graph_job_failed.svg new file mode 100755 index 00000000000..64da5aa31fc --- /dev/null +++ b/app/views/shared/icons/_icon_graph_job_failed.svg @@ -0,0 +1 @@ + diff --git a/app/views/shared/icons/_icon_graph_job_manual.svg b/app/views/shared/icons/_icon_graph_job_manual.svg new file mode 100755 index 00000000000..c98839f51a9 --- /dev/null +++ b/app/views/shared/icons/_icon_graph_job_manual.svg @@ -0,0 +1 @@ + diff --git a/app/views/shared/icons/_icon_graph_job_pending.svg b/app/views/shared/icons/_icon_graph_job_pending.svg new file mode 100755 index 00000000000..02d5da407e3 --- /dev/null +++ b/app/views/shared/icons/_icon_graph_job_pending.svg @@ -0,0 +1 @@ + diff --git a/app/views/shared/icons/_icon_graph_job_running.svg b/app/views/shared/icons/_icon_graph_job_running.svg new file mode 100755 index 00000000000..532f4fee33c --- /dev/null +++ b/app/views/shared/icons/_icon_graph_job_running.svg @@ -0,0 +1 @@ + diff --git a/app/views/shared/icons/_icon_graph_job_skipped.svg b/app/views/shared/icons/_icon_graph_job_skipped.svg new file mode 100755 index 00000000000..1998dfef9ea --- /dev/null +++ b/app/views/shared/icons/_icon_graph_job_skipped.svg @@ -0,0 +1 @@ + diff --git a/app/views/shared/icons/_icon_graph_job_success.svg b/app/views/shared/icons/_icon_graph_job_success.svg new file mode 100755 index 00000000000..eed5006bebe --- /dev/null +++ b/app/views/shared/icons/_icon_graph_job_success.svg @@ -0,0 +1 @@ + diff --git a/app/views/shared/icons/_icon_graph_job_warning.svg b/app/views/shared/icons/_icon_graph_job_warning.svg new file mode 100755 index 00000000000..cb785635b7e --- /dev/null +++ b/app/views/shared/icons/_icon_graph_job_warning.svg @@ -0,0 +1 @@ + -- cgit v1.2.1 From b4f18a30fb776e28fac405922cb5dfcfdc8ac5d7 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 7 Dec 2016 22:56:47 +0000 Subject: Adds tests for the status and actions icons rendered in the pipeline graph Fix padding in dropdown --- app/assets/stylesheets/pages/pipelines.scss | 4 ---- 1 file changed, 4 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 06b078d5345..304a7932a06 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -646,10 +646,6 @@ .dropdown-build { color: $gl-text-color-light; - a { - padding: 6px 8px 7px; - } - a.ci-action-icon-container { padding: 0; font-size: 11px; -- cgit v1.2.1 From 007255ed5833bdd7bec8927d9f197002dc519186 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 8 Dec 2016 09:51:36 +0100 Subject: Added Ci::Status::Build --- app/models/ci/build.rb | 4 ++++ app/models/commit_status.rb | 4 ++++ 2 files changed, 8 insertions(+) (limited to 'app') diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 88c46076df6..0f4c498c266 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -100,6 +100,10 @@ module Ci end end + def detailed_status + Gitlab::Ci::Status::Build::Factory.new(self).fabricate! + end + def manual? self.when == 'manual' end diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index cf90475f4d4..fce16174e22 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -131,4 +131,8 @@ class CommitStatus < ActiveRecord::Base def has_trace? false end + + def detailed_status + Gitlab::Ci::Status::Factory.new(self).fabricate! + end end -- cgit v1.2.1 From cd4a2270c5ccbdbd9e57e0c625eee2d80357d6be Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 8 Dec 2016 10:40:56 +0100 Subject: Improve actions --- app/models/ci/build.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app') diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 0f4c498c266..73564dd2aa0 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -127,6 +127,10 @@ module Ci end end + def cancelable? + active? + end + def retryable? project.builds_enabled? && commands.present? && complete? end -- cgit v1.2.1 From 65f3206024778b934171c9d9ece8ab627ba6c4c5 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 8 Dec 2016 11:03:01 +0100 Subject: Remove ci_status_with_icon helper and replace it with partial [ci skip] --- app/helpers/ci_status_helper.rb | 20 +------------------- app/views/admin/runners/show.html.haml | 2 +- app/views/ci/status/_icon_with_label.html.haml | 10 ++++++++++ app/views/projects/builds/_header.html.haml | 2 +- app/views/projects/ci/builds/_build.html.haml | 5 +---- app/views/projects/ci/pipelines/_pipeline.html.haml | 5 +---- .../_generic_commit_status.html.haml | 5 +---- app/views/projects/pipelines/_info.html.haml | 2 +- 8 files changed, 17 insertions(+), 34 deletions(-) create mode 100644 app/views/ci/status/_icon_with_label.html.haml (limited to 'app') diff --git a/app/helpers/ci_status_helper.rb b/app/helpers/ci_status_helper.rb index 8e19752a8a1..d9f5e01f0dc 100644 --- a/app/helpers/ci_status_helper.rb +++ b/app/helpers/ci_status_helper.rb @@ -4,25 +4,7 @@ module CiStatusHelper builds_namespace_project_commit_path(project.namespace, project, pipeline.sha) end - def ci_status_with_icon(status, target = nil) - content = ci_icon_for_status(status) + ci_text_for_status(status) - klass = "ci-status ci-#{status}" - - if target - link_to content, target, class: klass - else - content_tag :span, content, class: klass - end - end - - def ci_text_for_status(status) - if detailed_status?(status) - status.text - else - status - end - end - + # Is used by Commit and Merge Request Widget def ci_label_for_status(status) if detailed_status?(status) return status.label diff --git a/app/views/admin/runners/show.html.haml b/app/views/admin/runners/show.html.haml index 73038164056..fa8be25ffa8 100644 --- a/app/views/admin/runners/show.html.haml +++ b/app/views/admin/runners/show.html.haml @@ -91,7 +91,7 @@ %strong ##{build.id} %td.status - = ci_status_with_icon(build.status) + = render "ci/status/icon_with_label", subject: build %td.status - if project diff --git a/app/views/ci/status/_icon_with_label.html.haml b/app/views/ci/status/_icon_with_label.html.haml new file mode 100644 index 00000000000..65a74e88444 --- /dev/null +++ b/app/views/ci/status/_icon_with_label.html.haml @@ -0,0 +1,10 @@ +- details_path = subject.details_path if subject.has_details?(current_user) +- klass = "ci-status ci-#{subject.status}" +- if details_path + = link_to details_path, class: klass do + = custom_icon(status.icon) + = status.text +- else + %span{ class: klass } + = custom_icon(status.icon) + = status.text diff --git a/app/views/projects/builds/_header.html.haml b/app/views/projects/builds/_header.html.haml index f6aa20c4579..5e4e30f08d5 100644 --- a/app/views/projects/builds/_header.html.haml +++ b/app/views/projects/builds/_header.html.haml @@ -1,6 +1,6 @@ .content-block.build-header .header-content - = ci_status_with_icon(@build.status) + = render "ci/status/icon_with_label", subject: build Build %strong ##{@build.id} in pipeline diff --git a/app/views/projects/ci/builds/_build.html.haml b/app/views/projects/ci/builds/_build.html.haml index 18b3b04154f..6b0cd3e49a0 100644 --- a/app/views/projects/ci/builds/_build.html.haml +++ b/app/views/projects/ci/builds/_build.html.haml @@ -9,10 +9,7 @@ %tr.build.commit{class: ('retried' if retried)} %td.status - - if can?(current_user, :read_build, build) - = ci_status_with_icon(build.status, namespace_project_build_url(build.project.namespace, build.project, build)) - - else - = ci_status_with_icon(build.status) + = render "ci/status/icon_with_label", subject: build %td.branch-commit - if can?(current_user, :read_build, build) diff --git a/app/views/projects/ci/pipelines/_pipeline.html.haml b/app/views/projects/ci/pipelines/_pipeline.html.haml index b58dceb58c9..84243e4306d 100644 --- a/app/views/projects/ci/pipelines/_pipeline.html.haml +++ b/app/views/projects/ci/pipelines/_pipeline.html.haml @@ -1,13 +1,10 @@ - status = pipeline.status -- detailed_status = pipeline.detailed_status - show_commit = local_assigns.fetch(:show_commit, true) - show_branch = local_assigns.fetch(:show_branch, true) %tr.commit %td.commit-link - = link_to namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id), class: "ci-status ci-#{detailed_status}" do - = ci_icon_for_status(detailed_status) - = ci_text_for_status(detailed_status) + = render "ci/status/icon_with_label", subject: pipeline %td = link_to namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id) do diff --git a/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml b/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml index 7f751d9ae2e..69cb1631ee8 100644 --- a/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml +++ b/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml @@ -8,10 +8,7 @@ %tr.generic_commit_status{class: ('retried' if retried)} %td.status - - if can?(current_user, :read_commit_status, generic_commit_status) && generic_commit_status.target_url - = ci_status_with_icon(generic_commit_status.status, generic_commit_status.target_url) - - else - = ci_status_with_icon(generic_commit_status.status) + = render "ci/status/icon_with_label", subject: generic_commit_status %td.generic_commit_status-link - if can?(current_user, :read_commit_status, generic_commit_status) && generic_commit_status.target_url diff --git a/app/views/projects/pipelines/_info.html.haml b/app/views/projects/pipelines/_info.html.haml index 229bdfb0e8d..f7385184a2b 100644 --- a/app/views/projects/pipelines/_info.html.haml +++ b/app/views/projects/pipelines/_info.html.haml @@ -1,6 +1,6 @@ .page-content-header .header-main-content - = ci_status_with_icon(@pipeline.detailed_status) + = render "ci/status/icon_with_label", subject: @pipeline %strong Pipeline ##{@commit.pipelines.last.id} triggered #{time_ago_with_tooltip(@commit.authored_date)} by = author_avatar(@commit, size: 24) -- cgit v1.2.1 From c1db5b91207f4e3f7144c5cb62ce9160cf2e32e9 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 8 Dec 2016 14:51:38 +0100 Subject: Fix some detailed statuses specs related to abilities --- app/models/ability.rb | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'app') diff --git a/app/models/ability.rb b/app/models/ability.rb index fa8f8bc3a5f..ce461caf686 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -1,4 +1,10 @@ class Ability + module Allowable + def can?(user, action, subject) + Ability.allowed?(user, action, subject) + end + end + class << self # Given a list of users and a project this method returns the users that can # read the given project. -- cgit v1.2.1 From 5b89ec0dbf76784ccc1e41b66498dd0dc4f05042 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 8 Dec 2016 17:52:24 +0100 Subject: Fix auto loading of constants for Ci Statuses --- app/models/ci/build.rb | 6 +++--- app/models/ci/pipeline.rb | 4 ++-- app/models/ci/stage.rb | 4 ++-- app/models/commit_status.rb | 4 ++-- app/views/ci/status/_icon_with_label.html.haml | 13 +++++++------ 5 files changed, 16 insertions(+), 15 deletions(-) (limited to 'app') diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 73564dd2aa0..65ee327a8e5 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -100,8 +100,8 @@ module Ci end end - def detailed_status - Gitlab::Ci::Status::Build::Factory.new(self).fabricate! + def detailed_status(current_user) + Gitlab::Ci::Status::Build::Factory.new(self, current_user).fabricate! end def manual? @@ -156,7 +156,7 @@ module Ci end def environment_action - self.options.fetch(:environment, {}).fetch(:action, 'start') + self.options.fetch(:environment, {}).fetch(:action, 'start') if self.options end def outdated_deployment? diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index fda8228a1e9..1f33106d358 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -336,8 +336,8 @@ module Ci .select { |merge_request| merge_request.head_pipeline.try(:id) == self.id } end - def detailed_status - Gitlab::Ci::Status::Pipeline::Factory.new(self).fabricate! + def detailed_status(current_user) + Gitlab::Ci::Status::Pipeline::Factory.new(self, current_user).fabricate! end private diff --git a/app/models/ci/stage.rb b/app/models/ci/stage.rb index d2a37c0a827..be52cce20f1 100644 --- a/app/models/ci/stage.rb +++ b/app/models/ci/stage.rb @@ -22,8 +22,8 @@ module Ci @status ||= statuses.latest.status end - def detailed_status - Gitlab::Ci::Status::Stage::Factory.new(self).fabricate! + def detailed_status(current_user) + Gitlab::Ci::Status::Stage::Factory.new(self, current_user).fabricate! end def statuses diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index fce16174e22..6548a7dda2c 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -132,7 +132,7 @@ class CommitStatus < ActiveRecord::Base false end - def detailed_status - Gitlab::Ci::Status::Factory.new(self).fabricate! + def detailed_status(current_user) + Gitlab::Ci::Status::Factory.new(self, current_user).fabricate! end end diff --git a/app/views/ci/status/_icon_with_label.html.haml b/app/views/ci/status/_icon_with_label.html.haml index 65a74e88444..d3fe332cc78 100644 --- a/app/views/ci/status/_icon_with_label.html.haml +++ b/app/views/ci/status/_icon_with_label.html.haml @@ -1,10 +1,11 @@ -- details_path = subject.details_path if subject.has_details?(current_user) -- klass = "ci-status ci-#{subject.status}" +- detailed_status = subject.detailed_status(current_user) +- details_path = detailed_status.details_path if detailed_status.has_details? +- klass = "ci-status ci-#{detailed_status}" - if details_path = link_to details_path, class: klass do - = custom_icon(status.icon) - = status.text + = custom_icon(detailed_status.icon) + = detailed_status.text - else %span{ class: klass } - = custom_icon(status.icon) - = status.text + = custom_icon(detailed_status.icon) + = detailed_status.text -- cgit v1.2.1 From 20f74fe7ca6388a2dcc72231e84ed2945d6c4444 Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 8 Dec 2016 10:03:53 -0700 Subject: make Vue render with null commit object - handle scope and page in different tabs --- .../vue_pipelines_index/pipelines.js.es6 | 38 ++++++++++++++++++---- 1 file changed, 31 insertions(+), 7 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index 9f7e71dbee9..090ceb67593 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -66,6 +66,8 @@ }, methods: { changepage(e) { + const scope = getParameterByName('scope'); + if (scope) this.apiScope = scope; const text = e.target.innerText; const { totalPages, nextPage, previousPage } = this.pageInfo; if (text === SPREAD) return; @@ -74,14 +76,21 @@ if (text === NEXT) this.pagenum = nextPage; if (text === PREV) this.pagenum = previousPage; if (text === FIRST) this.pagenum = 1; - - window.history.pushState({}, null, `?p=${this.pagenum}`); + window.history.pushState({}, null, `?scope=${this.apiScope}&p=${this.pagenum}`); clearInterval(this.timeLoopInterval); this.pageRequest = true; - this.store.fetchDataLoop.call(this, Vue, this.pagenum, this.scope); + this.store.fetchDataLoop.call(this, Vue, this.pagenum, this.scope, this.apiScope); }, author(pipeline) { const { commit } = pipeline; + if (!commit) { + return ({ + avatar_url: '', + web_url: '', + username: '', + }); + } + const author = commit.author; if (author) return author; @@ -105,6 +114,21 @@ addTimeInterval(id, start) { this.allTimeIntervals.push({ id, start }); }, + commitTitle(pipeline) { + const { commit } = pipeline; + if (commit) return commit.title; + return ''; + }, + commitSha(pipeline) { + const { commit } = pipeline; + if (commit) return commit.short_id; + return ''; + }, + commitUrl(pipeline) { + const { commit } = pipeline; + if (commit) return commit.commit_url; + return ''; + }, }, template: `
    @@ -122,10 +146,10 @@ @@ -143,7 +167,7 @@
    Date: Thu, 8 Dec 2016 18:16:23 +0100 Subject: Rename icon_with_label to icon_with_description --- app/views/admin/runners/show.html.haml | 2 +- app/views/ci/status/_icon_with_description.html.haml | 12 ++++++++++++ app/views/ci/status/_icon_with_label.html.haml | 11 ----------- app/views/projects/builds/_header.html.haml | 2 +- app/views/projects/ci/builds/_build.html.haml | 2 +- app/views/projects/ci/pipelines/_pipeline.html.haml | 2 +- .../generic_commit_statuses/_generic_commit_status.html.haml | 2 +- app/views/projects/pipelines/_info.html.haml | 2 +- app/views/projects/stage/_graph.html.haml | 4 ++-- app/views/projects/stage/_in_stage_group.html.haml | 2 +- 10 files changed, 21 insertions(+), 20 deletions(-) create mode 100644 app/views/ci/status/_icon_with_description.html.haml delete mode 100644 app/views/ci/status/_icon_with_label.html.haml (limited to 'app') diff --git a/app/views/admin/runners/show.html.haml b/app/views/admin/runners/show.html.haml index fa8be25ffa8..badeb11b208 100644 --- a/app/views/admin/runners/show.html.haml +++ b/app/views/admin/runners/show.html.haml @@ -91,7 +91,7 @@ %strong ##{build.id} %td.status - = render "ci/status/icon_with_label", subject: build + = render "ci/status/icon_with_description", subject: build %td.status - if project diff --git a/app/views/ci/status/_icon_with_description.html.haml b/app/views/ci/status/_icon_with_description.html.haml new file mode 100644 index 00000000000..34c923440d0 --- /dev/null +++ b/app/views/ci/status/_icon_with_description.html.haml @@ -0,0 +1,12 @@ +- detailed_status = subject.detailed_status(current_user) +- details_path = detailed_status.details_path if detailed_status.has_details? +- klass = "ci-status ci-#{detailed_status}" + +- if details_path + = link_to details_path, class: klass do + = custom_icon(detailed_status.icon) + = detailed_status.text +- else + %span{ class: klass } + = custom_icon(detailed_status.icon) + = detailed_status.text diff --git a/app/views/ci/status/_icon_with_label.html.haml b/app/views/ci/status/_icon_with_label.html.haml deleted file mode 100644 index d3fe332cc78..00000000000 --- a/app/views/ci/status/_icon_with_label.html.haml +++ /dev/null @@ -1,11 +0,0 @@ -- detailed_status = subject.detailed_status(current_user) -- details_path = detailed_status.details_path if detailed_status.has_details? -- klass = "ci-status ci-#{detailed_status}" -- if details_path - = link_to details_path, class: klass do - = custom_icon(detailed_status.icon) - = detailed_status.text -- else - %span{ class: klass } - = custom_icon(detailed_status.icon) - = detailed_status.text diff --git a/app/views/projects/builds/_header.html.haml b/app/views/projects/builds/_header.html.haml index 5e4e30f08d5..85d1793ecb9 100644 --- a/app/views/projects/builds/_header.html.haml +++ b/app/views/projects/builds/_header.html.haml @@ -1,6 +1,6 @@ .content-block.build-header .header-content - = render "ci/status/icon_with_label", subject: build + = render "ci/status/icon_with_description", subject: build Build %strong ##{@build.id} in pipeline diff --git a/app/views/projects/ci/builds/_build.html.haml b/app/views/projects/ci/builds/_build.html.haml index 6b0cd3e49a0..4257bb86859 100644 --- a/app/views/projects/ci/builds/_build.html.haml +++ b/app/views/projects/ci/builds/_build.html.haml @@ -9,7 +9,7 @@ %tr.build.commit{class: ('retried' if retried)} %td.status - = render "ci/status/icon_with_label", subject: build + = render "ci/status/icon_with_description", subject: build %td.branch-commit - if can?(current_user, :read_build, build) diff --git a/app/views/projects/ci/pipelines/_pipeline.html.haml b/app/views/projects/ci/pipelines/_pipeline.html.haml index 84243e4306d..6dff955ea3d 100644 --- a/app/views/projects/ci/pipelines/_pipeline.html.haml +++ b/app/views/projects/ci/pipelines/_pipeline.html.haml @@ -4,7 +4,7 @@ %tr.commit %td.commit-link - = render "ci/status/icon_with_label", subject: pipeline + = render "ci/status/icon_with_description", subject: pipeline %td = link_to namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id) do diff --git a/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml b/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml index 69cb1631ee8..1dd07ae1a2a 100644 --- a/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml +++ b/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml @@ -8,7 +8,7 @@ %tr.generic_commit_status{class: ('retried' if retried)} %td.status - = render "ci/status/icon_with_label", subject: generic_commit_status + = render "ci/status/icon_with_description", subject: generic_commit_status %td.generic_commit_status-link - if can?(current_user, :read_commit_status, generic_commit_status) && generic_commit_status.target_url diff --git a/app/views/projects/pipelines/_info.html.haml b/app/views/projects/pipelines/_info.html.haml index f7385184a2b..d05697b4ee3 100644 --- a/app/views/projects/pipelines/_info.html.haml +++ b/app/views/projects/pipelines/_info.html.haml @@ -1,6 +1,6 @@ .page-content-header .header-main-content - = render "ci/status/icon_with_label", subject: @pipeline + = render "ci/status/icon_with_description", subject: @pipeline %strong Pipeline ##{@commit.pipelines.last.id} triggered #{time_ago_with_tooltip(@commit.authored_date)} by = author_avatar(@commit, size: 24) diff --git a/app/views/projects/stage/_graph.html.haml b/app/views/projects/stage/_graph.html.haml index d8c87fae5a1..cb845ae7f92 100644 --- a/app/views/projects/stage/_graph.html.haml +++ b/app/views/projects/stage/_graph.html.haml @@ -15,9 +15,9 @@ %li.build{ class: ("playable" if is_playable) } .curve .build-content - = render "projects/#{status.to_partial_path}_pipeline", subject: status + = render 'ci/status/icon_with_name_and_action', subject: status - else %li.build .curve .dropdown.inline.build-content - = render "projects/stage/in_stage_group", name: group_name, subject: grouped_statuses + = render 'projects/stage/in_stage_group', name: group_name, subject: grouped_statuses diff --git a/app/views/projects/stage/_in_stage_group.html.haml b/app/views/projects/stage/_in_stage_group.html.haml index 2d198d1b389..5c9b6549b37 100644 --- a/app/views/projects/stage/_in_stage_group.html.haml +++ b/app/views/projects/stage/_in_stage_group.html.haml @@ -10,4 +10,4 @@ %ul - subject.each do |status| %li.dropdown-build - = render "projects/#{status.to_partial_path}_pipeline", subject: status + = render 'ci/status/icon_with_name_and_action', subject: status -- cgit v1.2.1 From 203c9040571944f573d18db2bd477521b6c76535 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 8 Dec 2016 18:19:17 +0100 Subject: Add icon_with_name_and_action and use it everywhere --- app/views/ci/status/_icon_with_name.html.haml | 11 ++++++++ .../ci/status/_icon_with_name_and_action.html.haml | 8 ++++++ .../projects/ci/builds/_build_pipeline.html.haml | 31 ---------------------- .../_generic_commit_status_pipeline.html.haml | 10 ------- 4 files changed, 19 insertions(+), 41 deletions(-) create mode 100644 app/views/ci/status/_icon_with_name.html.haml create mode 100644 app/views/ci/status/_icon_with_name_and_action.html.haml delete mode 100644 app/views/projects/ci/builds/_build_pipeline.html.haml delete mode 100644 app/views/projects/generic_commit_statuses/_generic_commit_status_pipeline.html.haml (limited to 'app') diff --git a/app/views/ci/status/_icon_with_name.html.haml b/app/views/ci/status/_icon_with_name.html.haml new file mode 100644 index 00000000000..028e1fe9402 --- /dev/null +++ b/app/views/ci/status/_icon_with_name.html.haml @@ -0,0 +1,11 @@ +- detailed_status = subject.detailed_status(current_user) +- details_path = detailed_status.details_path if detailed_status.has_details? +- klass = "ci-status-icon ci-status-icon-#{detailed_status}" + +- if details_path + = link_to details_path, class: klass, data: { toggle: 'tooltip', title: "#{subject.name} - #{detailed_status}" } do + %span{ class: klass }= custom_icon(detailed_status.icon) + .ci-status-text= subject.name +- else + %span{ class: klass }= custom_icon(detailed_status.icon) + .ci-status-text= subject.name diff --git a/app/views/ci/status/_icon_with_name_and_action.html.haml b/app/views/ci/status/_icon_with_name_and_action.html.haml new file mode 100644 index 00000000000..76db3b7f38a --- /dev/null +++ b/app/views/ci/status/_icon_with_name_and_action.html.haml @@ -0,0 +1,8 @@ += render "ci/status/icon_with_name", subject: subject + +- detailed_status = subject.detailed_status(current_user) +- if detailed_status.has_action? + = link_to detailed_status.action_path, method: detailed_status.action_method, + title: "#{subject.name}: #{detailed_status.action_title}", class: 'ci-action-icon-container' do + %i.ci-action-icon-wrapper + = icon(detailed_status.action_icon, class: detailed_status.action_class) diff --git a/app/views/projects/ci/builds/_build_pipeline.html.haml b/app/views/projects/ci/builds/_build_pipeline.html.haml deleted file mode 100644 index 41b9265fe5e..00000000000 --- a/app/views/projects/ci/builds/_build_pipeline.html.haml +++ /dev/null @@ -1,31 +0,0 @@ -- is_playable = subject.playable? && can?(current_user, :update_build, @project) -- can_cancel = subject.active? && can?(current_user, :update_build, @project) -- can_retry = subject.retryable? && can?(current_user, :update_build, @project) -- can_stop = subject.complete? && subject.stops_environment? && can?(current_user, :update_build, @project) - -- if can?(current_user, :read_build, @project) - = link_to namespace_project_build_path(subject.project.namespace, subject.project, subject), data: { toggle: 'tooltip', title: "#{subject.name} - #{subject.status}", container: '.pipeline-graph', placement: 'bottom' } do - %span{class: "ci-status-icon ci-status-icon-#{subject.status}"} - = ci_icon_for_status(subject.status) - .ci-status-text= subject.name - - - if is_playable - = link_to play_namespace_project_build_path(subject.project.namespace, subject.project, subject, return_to: request.original_url), method: :post, title: "#{subject.name} - Play", class: 'ci-action-icon-container' do - %i.ci-action-icon-wrapper - = icon('play', class: 'ci-play-icon') - - elsif can_cancel - = link_to cancel_namespace_project_build_path(subject.project.namespace, subject.project, subject, return_to: request.original_url), method: :post, title: "#{subject.name} - Cancel", class: 'ci-action-icon-container' do - %i.ci-action-icon-wrapper - = icon('ban') - - elsif can_retry - = link_to retry_namespace_project_build_path(subject.project.namespace, subject.project, subject, return_to: request.original_url), method: :post, title: "#{subject.name} - Retry", class: 'ci-action-icon-container' do - %i.ci-action-icon-wrapper - = icon('refresh') - - elsif can_stop - = link_to play_namespace_project_build_path(subject.project.namespace, subject.project, subject, return_to: request.original_url), method: :post, title: "#{subject.name} - Stop", class: 'ci-action-icon-container' do - %i.ci-action-icon-wrapper - = icon('stop') - -- else - %span{class: "ci-status-icon ci-status-icon-#{subject.status}"} - = ci_icon_for_status(subject.status) diff --git a/app/views/projects/generic_commit_statuses/_generic_commit_status_pipeline.html.haml b/app/views/projects/generic_commit_statuses/_generic_commit_status_pipeline.html.haml deleted file mode 100644 index 7b82d913d29..00000000000 --- a/app/views/projects/generic_commit_statuses/_generic_commit_status_pipeline.html.haml +++ /dev/null @@ -1,10 +0,0 @@ -%a{ data: { toggle: 'tooltip', title: "#{subject.name} - #{subject.status}", container: '.pipeline-graph', placement: 'bottom' } } - - if subject.target_url - = link_to subject.target_url do - %span{class: "ci-status-icon ci-status-icon-#{subject.status}"} - = ci_icon_for_status(subject.status) - %span.ci-status-text= subject.name - - else - %span{class: "ci-status-icon ci-status-icon-#{subject.status}"} - = ci_icon_for_status(subject.status) - %span.ci-status-text= subject.name -- cgit v1.2.1 From b64cf8405c551e79520e8ce4eef2dc17259c41e3 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Thu, 8 Dec 2016 17:58:32 +0000 Subject: Renders new icons for the pipeline graph --- app/helpers/ci_status_helper.rb | 66 ++++++++-------------- app/views/ci/status/_icon_with_name.html.haml | 3 +- .../ci/status/_icon_with_name_and_action.html.haml | 2 +- .../shared/icons/_icon_graph_job_cancelled.svg | 1 - app/views/shared/icons/_icon_graph_job_created.svg | 1 - app/views/shared/icons/_icon_graph_job_failed.svg | 1 - app/views/shared/icons/_icon_graph_job_manual.svg | 1 - app/views/shared/icons/_icon_graph_job_pending.svg | 1 - app/views/shared/icons/_icon_graph_job_running.svg | 1 - app/views/shared/icons/_icon_graph_job_skipped.svg | 1 - app/views/shared/icons/_icon_graph_job_success.svg | 1 - app/views/shared/icons/_icon_graph_job_warning.svg | 1 - .../shared/icons/_icon_status_canceled_graph.svg | 1 + .../shared/icons/_icon_status_created_graph.svg | 1 + .../shared/icons/_icon_status_failed_graph.svg | 1 + .../shared/icons/_icon_status_manual_graph.svg | 1 + .../shared/icons/_icon_status_pending_graph.svg | 1 + .../shared/icons/_icon_status_running_graph.svg | 1 + .../shared/icons/_icon_status_skipped_graph.svg | 1 + .../shared/icons/_icon_status_success_graph.svg | 1 + .../shared/icons/_icon_status_warning_graph.svg | 1 + 21 files changed, 34 insertions(+), 55 deletions(-) delete mode 100755 app/views/shared/icons/_icon_graph_job_cancelled.svg delete mode 100755 app/views/shared/icons/_icon_graph_job_created.svg delete mode 100755 app/views/shared/icons/_icon_graph_job_failed.svg delete mode 100755 app/views/shared/icons/_icon_graph_job_manual.svg delete mode 100755 app/views/shared/icons/_icon_graph_job_pending.svg delete mode 100755 app/views/shared/icons/_icon_graph_job_running.svg delete mode 100755 app/views/shared/icons/_icon_graph_job_skipped.svg delete mode 100755 app/views/shared/icons/_icon_graph_job_success.svg delete mode 100755 app/views/shared/icons/_icon_graph_job_warning.svg create mode 100755 app/views/shared/icons/_icon_status_canceled_graph.svg create mode 100755 app/views/shared/icons/_icon_status_created_graph.svg create mode 100755 app/views/shared/icons/_icon_status_failed_graph.svg create mode 100755 app/views/shared/icons/_icon_status_manual_graph.svg create mode 100755 app/views/shared/icons/_icon_status_pending_graph.svg create mode 100755 app/views/shared/icons/_icon_status_running_graph.svg create mode 100755 app/views/shared/icons/_icon_status_skipped_graph.svg create mode 100755 app/views/shared/icons/_icon_status_success_graph.svg create mode 100755 app/views/shared/icons/_icon_status_warning_graph.svg (limited to 'app') diff --git a/app/helpers/ci_status_helper.rb b/app/helpers/ci_status_helper.rb index 7ddef2cdd5f..d9f5e01f0dc 100644 --- a/app/helpers/ci_status_helper.rb +++ b/app/helpers/ci_status_helper.rb @@ -25,54 +25,32 @@ module CiStatusHelper status.humanize end - def ci_icon_for_status(status, graph: nil) + def ci_icon_for_status(status) if detailed_status?(status) return custom_icon(status.icon) end - if graph - icon_name = - case status - when 'success' - 'icon_graph_job_success' - when 'success_with_warnings' - 'icon_graph_job_warning' - when 'failed' - 'icon_graph_job_failed' - when 'pending' - 'icon_graph_job_pending' - when 'running' - 'icon_graph_job_running' - when 'created' - 'icon_graph_job_created' - when 'skipped' - 'icon_graph_job_skipped' - else - 'icon_graph_job_canceled' - end - else - icon_name = - case status - when 'success' - 'icon_status_success' - when 'success_with_warnings' - 'icon_status_warning' - when 'failed' - 'icon_status_failed' - when 'pending' - 'icon_status_pending' - when 'running' - 'icon_status_running' - when 'play' - 'icon_play' - when 'created' - 'icon_status_created' - when 'skipped' - 'icon_status_skipped' - else - 'icon_status_canceled' - end - end + icon_name = + case status + when 'success' + 'icon_status_success' + when 'success_with_warnings' + 'icon_status_warning' + when 'failed' + 'icon_status_failed' + when 'pending' + 'icon_status_pending' + when 'running' + 'icon_status_running' + when 'play' + 'icon_play' + when 'created' + 'icon_status_created' + when 'skipped' + 'icon_status_skipped' + else + 'icon_status_canceled' + end custom_icon(icon_name) end diff --git a/app/views/ci/status/_icon_with_name.html.haml b/app/views/ci/status/_icon_with_name.html.haml index 028e1fe9402..a467316ef47 100644 --- a/app/views/ci/status/_icon_with_name.html.haml +++ b/app/views/ci/status/_icon_with_name.html.haml @@ -1,10 +1,11 @@ - detailed_status = subject.detailed_status(current_user) - details_path = detailed_status.details_path if detailed_status.has_details? - klass = "ci-status-icon ci-status-icon-#{detailed_status}" +- status_icon = graph ? "#{detailed_status.icon}_graph" : detailed_status.icon - if details_path = link_to details_path, class: klass, data: { toggle: 'tooltip', title: "#{subject.name} - #{detailed_status}" } do - %span{ class: klass }= custom_icon(detailed_status.icon) + %span{ class: klass }= custom_icon(status_icon) .ci-status-text= subject.name - else %span{ class: klass }= custom_icon(detailed_status.icon) diff --git a/app/views/ci/status/_icon_with_name_and_action.html.haml b/app/views/ci/status/_icon_with_name_and_action.html.haml index 76db3b7f38a..b912c212534 100644 --- a/app/views/ci/status/_icon_with_name_and_action.html.haml +++ b/app/views/ci/status/_icon_with_name_and_action.html.haml @@ -1,4 +1,4 @@ -= render "ci/status/icon_with_name", subject: subject += render "ci/status/icon_with_name", subject: subject, graph: true - detailed_status = subject.detailed_status(current_user) - if detailed_status.has_action? diff --git a/app/views/shared/icons/_icon_graph_job_cancelled.svg b/app/views/shared/icons/_icon_graph_job_cancelled.svg deleted file mode 100755 index bd5d04e1cd7..00000000000 --- a/app/views/shared/icons/_icon_graph_job_cancelled.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/app/views/shared/icons/_icon_graph_job_created.svg b/app/views/shared/icons/_icon_graph_job_created.svg deleted file mode 100755 index 326ad04e017..00000000000 --- a/app/views/shared/icons/_icon_graph_job_created.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/app/views/shared/icons/_icon_graph_job_failed.svg b/app/views/shared/icons/_icon_graph_job_failed.svg deleted file mode 100755 index 64da5aa31fc..00000000000 --- a/app/views/shared/icons/_icon_graph_job_failed.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/app/views/shared/icons/_icon_graph_job_manual.svg b/app/views/shared/icons/_icon_graph_job_manual.svg deleted file mode 100755 index c98839f51a9..00000000000 --- a/app/views/shared/icons/_icon_graph_job_manual.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/app/views/shared/icons/_icon_graph_job_pending.svg b/app/views/shared/icons/_icon_graph_job_pending.svg deleted file mode 100755 index 02d5da407e3..00000000000 --- a/app/views/shared/icons/_icon_graph_job_pending.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/app/views/shared/icons/_icon_graph_job_running.svg b/app/views/shared/icons/_icon_graph_job_running.svg deleted file mode 100755 index 532f4fee33c..00000000000 --- a/app/views/shared/icons/_icon_graph_job_running.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/app/views/shared/icons/_icon_graph_job_skipped.svg b/app/views/shared/icons/_icon_graph_job_skipped.svg deleted file mode 100755 index 1998dfef9ea..00000000000 --- a/app/views/shared/icons/_icon_graph_job_skipped.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/app/views/shared/icons/_icon_graph_job_success.svg b/app/views/shared/icons/_icon_graph_job_success.svg deleted file mode 100755 index eed5006bebe..00000000000 --- a/app/views/shared/icons/_icon_graph_job_success.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/app/views/shared/icons/_icon_graph_job_warning.svg b/app/views/shared/icons/_icon_graph_job_warning.svg deleted file mode 100755 index cb785635b7e..00000000000 --- a/app/views/shared/icons/_icon_graph_job_warning.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/app/views/shared/icons/_icon_status_canceled_graph.svg b/app/views/shared/icons/_icon_status_canceled_graph.svg new file mode 100755 index 00000000000..bd5d04e1cd7 --- /dev/null +++ b/app/views/shared/icons/_icon_status_canceled_graph.svg @@ -0,0 +1 @@ + diff --git a/app/views/shared/icons/_icon_status_created_graph.svg b/app/views/shared/icons/_icon_status_created_graph.svg new file mode 100755 index 00000000000..326ad04e017 --- /dev/null +++ b/app/views/shared/icons/_icon_status_created_graph.svg @@ -0,0 +1 @@ + diff --git a/app/views/shared/icons/_icon_status_failed_graph.svg b/app/views/shared/icons/_icon_status_failed_graph.svg new file mode 100755 index 00000000000..64da5aa31fc --- /dev/null +++ b/app/views/shared/icons/_icon_status_failed_graph.svg @@ -0,0 +1 @@ + diff --git a/app/views/shared/icons/_icon_status_manual_graph.svg b/app/views/shared/icons/_icon_status_manual_graph.svg new file mode 100755 index 00000000000..c98839f51a9 --- /dev/null +++ b/app/views/shared/icons/_icon_status_manual_graph.svg @@ -0,0 +1 @@ + diff --git a/app/views/shared/icons/_icon_status_pending_graph.svg b/app/views/shared/icons/_icon_status_pending_graph.svg new file mode 100755 index 00000000000..02d5da407e3 --- /dev/null +++ b/app/views/shared/icons/_icon_status_pending_graph.svg @@ -0,0 +1 @@ + diff --git a/app/views/shared/icons/_icon_status_running_graph.svg b/app/views/shared/icons/_icon_status_running_graph.svg new file mode 100755 index 00000000000..532f4fee33c --- /dev/null +++ b/app/views/shared/icons/_icon_status_running_graph.svg @@ -0,0 +1 @@ + diff --git a/app/views/shared/icons/_icon_status_skipped_graph.svg b/app/views/shared/icons/_icon_status_skipped_graph.svg new file mode 100755 index 00000000000..1998dfef9ea --- /dev/null +++ b/app/views/shared/icons/_icon_status_skipped_graph.svg @@ -0,0 +1 @@ + diff --git a/app/views/shared/icons/_icon_status_success_graph.svg b/app/views/shared/icons/_icon_status_success_graph.svg new file mode 100755 index 00000000000..eed5006bebe --- /dev/null +++ b/app/views/shared/icons/_icon_status_success_graph.svg @@ -0,0 +1 @@ + diff --git a/app/views/shared/icons/_icon_status_warning_graph.svg b/app/views/shared/icons/_icon_status_warning_graph.svg new file mode 100755 index 00000000000..cb785635b7e --- /dev/null +++ b/app/views/shared/icons/_icon_status_warning_graph.svg @@ -0,0 +1 @@ + -- cgit v1.2.1 From 473addf14244ba7ae280d1f7b409064e7a22b4bc Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 8 Dec 2016 11:05:20 -0700 Subject: bunch of blocked tests now passing - moving on --- .../vue_pipelines_index/pipelines.js.es6 | 70 +++++----------------- 1 file changed, 15 insertions(+), 55 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index 090ceb67593..2c18b6cc7e5 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -38,31 +38,17 @@ apiScope: 'all', pageInfo: {}, pagenum: 1, - count: { - all: 0, - running_or_pending: 0, - }, + count: { all: 0, running_or_pending: 0 }, pageRequest: false, }; }, - props: [ - 'scope', - 'store', - ], + props: ['scope', 'store'], created() { const pagenum = getParameterByName('p'); const scope = getParameterByName('scope'); - if (pagenum) this.pagenum = pagenum; if (scope) this.apiScope = scope; - - this.store.fetchDataLoop.call( - this, - Vue, - this.pagenum, - this.scope, - this.apiScope, - ); + this.store.fetchDataLoop.call(this, Vue, this.pagenum, this.scope, this.apiScope); }, methods: { changepage(e) { @@ -82,51 +68,28 @@ this.store.fetchDataLoop.call(this, Vue, this.pagenum, this.scope, this.apiScope); }, author(pipeline) { - const { commit } = pipeline; - if (!commit) { - return ({ - avatar_url: '', - web_url: '', - username: '', - }); - } - - const author = commit.author; - if (author) return author; - - const nonUser = { - avatar_url: commit.author_gravatar_url, - web_url: `mailto:${commit.author_email}`, - username: commit.author_name, - }; - - return nonUser; + if (!pipeline.commit) return ({ avatar_url: '', web_url: '', username: '' }); + if (pipeline.commit.author) return pipeline.commit.author; + return ({ + avatar_url: pipeline.commit.author_gravatar_url, + web_url: `mailto:${pipeline.commit.author_email}`, + username: pipeline.commit.author_name, + }); }, ref(pipeline) { const { ref } = pipeline; - const commitRef = { - name: ref.name, - tag: ref['tag?'], - ref_url: ref.url, - }; - return commitRef; - }, - addTimeInterval(id, start) { - this.allTimeIntervals.push({ id, start }); + return ({ name: ref.name, tag: ref['tag?'], ref_url: ref.url }); }, commitTitle(pipeline) { - const { commit } = pipeline; - if (commit) return commit.title; + if (pipeline.commit) return pipeline.commit.title; return ''; }, commitSha(pipeline) { - const { commit } = pipeline; - if (commit) return commit.short_id; + if (pipeline.commit) return pipeline.commit.short_id; return ''; }, commitUrl(pipeline) { - const { commit } = pipeline; - if (commit) return commit.commit_url; + if (pipeline.commit) return pipeline.commit.commit_url; return ''; }, }, @@ -154,10 +117,7 @@ - - + -- cgit v1.2.1 From aa74a704ca43334fa521ff99696513012ebee66c Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 8 Dec 2016 11:22:05 -0700 Subject: first manual build test passing --- app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 index e99e65d50b8..fe1db7aae29 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 @@ -20,8 +20,8 @@ v-if='pipeline.details.manual_actions.length > 0' class="dropdown-toggle btn btn-default" data-toggle="dropdown" - type="button" title="Manual build" + alt="Manual Build" > Date: Thu, 8 Dec 2016 11:35:39 -0700 Subject: tests don't see Manual build link --- app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 index fe1db7aae29..1c7fa994900 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 @@ -23,7 +23,7 @@ title="Manual build" alt="Manual Build" > - + - + Date: Thu, 8 Dec 2016 22:39:37 +0000 Subject: Math works for inline syntax --- app/assets/javascripts/syntax_highlight.js | 30 ----------- app/assets/javascripts/syntax_highlight.js.erb | 75 ++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 30 deletions(-) delete mode 100644 app/assets/javascripts/syntax_highlight.js create mode 100644 app/assets/javascripts/syntax_highlight.js.erb (limited to 'app') diff --git a/app/assets/javascripts/syntax_highlight.js b/app/assets/javascripts/syntax_highlight.js deleted file mode 100644 index bd37d69165f..00000000000 --- a/app/assets/javascripts/syntax_highlight.js +++ /dev/null @@ -1,30 +0,0 @@ -/* eslint-disable func-names, space-before-function-paren, consistent-return, no-var, no-undef, no-else-return, prefer-arrow-callback, padded-blocks, max-len */ -// Syntax Highlighter -// -// Applies a syntax highlighting color scheme CSS class to any element with the -// `js-syntax-highlight` class -// -// ### Example Markup -// -//
    -// -(function() { - $.fn.syntaxHighlight = function() { - var $children; - if ($(this).hasClass('js-syntax-highlight')) { - // Given the element itself, apply highlighting - return $(this).addClass(gon.user_color_scheme); - } else { - // Given a parent element, recurse to any of its applicable children - $children = $(this).find('.js-syntax-highlight'); - if ($children.length) { - return $children.syntaxHighlight(); - } - } - }; - - $(document).on('ready page:load', function() { - return $('.js-syntax-highlight').syntaxHighlight(); - }); - -}).call(this); diff --git a/app/assets/javascripts/syntax_highlight.js.erb b/app/assets/javascripts/syntax_highlight.js.erb new file mode 100644 index 00000000000..5664c32d7b6 --- /dev/null +++ b/app/assets/javascripts/syntax_highlight.js.erb @@ -0,0 +1,75 @@ +/* eslint-disable func-names, space-before-function-paren, consistent-return, no-var, no-undef, no-else-return, prefer-arrow-callback, padded-blocks, max-len */ +// Syntax Highlighter +// +// Applies a syntax highlighting color scheme CSS class to any element with the +// `js-syntax-highlight` class +// +// ### Example Markup +// +//
    +// +(function() { + // CSS and JS for KaTeX + CSS_PATH = "<%= asset_path('katex.css') %>"; + JS_PATH = "<%= asset_path('katex.js') %>"; + + // Only load once + var katexLoaded = false; + + // Loop over all math elements and render math + var renderWithKaTeX = function (elements) { + elements.each(function () { + $(this).hide(); + var mathNode = $( "Test" ); + mathNode.insertAfter($(this)); + + katex.render($(this).text(), mathNode.get(0), { displayMode: false }) + }) + }; + var handleMath = function () { + var mathElements = $('.code.math'); + + if (mathElements.length == 0) return; + + if (katexLoaded) renderWithKaTeX(mathElements); + else { + // Request CSS file so it is in the cache + $.get(CSS_PATH, function(){ + var css = $('', + {rel:'stylesheet', + type:'text/css', + href: CSS_PATH + }); + css.appendTo('head'); + + // Load KaTeX js + $.getScript(JS_PATH, function() { + katexLoaded = true; + renderWithKaTeX(mathElements); // Run KaTeX + }) + }); + } + }; + + $.fn.syntaxHighlight = function() { + var $children; + + handleMath(); + + if ($(this).hasClass('js-syntax-highlight')) { + // Given the element itself, apply highlighting + return $(this).addClass(gon.user_color_scheme); + } else { + // Given a parent element, recurse to any of its applicable children + $children = $(this).find('.js-syntax-highlight'); + if ($children.length) { + return $children.syntaxHighlight(); + } + } + }; + + $(document).on('ready page:load', function() { + return $('.js-syntax-highlight').syntaxHighlight(); + }); + +}).call(this); -- cgit v1.2.1 From 63bc23cfe242edd800730827c2d47dd025a26b2f Mon Sep 17 00:00:00 2001 From: Munken Date: Thu, 8 Dec 2016 23:04:07 +0000 Subject: Detect whether math is display style --- app/assets/javascripts/syntax_highlight.js.erb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/syntax_highlight.js.erb b/app/assets/javascripts/syntax_highlight.js.erb index 5664c32d7b6..3b9a7d9baf9 100644 --- a/app/assets/javascripts/syntax_highlight.js.erb +++ b/app/assets/javascripts/syntax_highlight.js.erb @@ -23,7 +23,8 @@ var mathNode = $( "Test" ); mathNode.insertAfter($(this)); - katex.render($(this).text(), mathNode.get(0), { displayMode: false }) + var display = $(this).hasClass('highlight'); + katex.render($(this).text(), mathNode.get(0), { displayMode: display }) }) }; var handleMath = function () { -- cgit v1.2.1 From b5cd430a6cafa80583fffeeae52b4f2392a72419 Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 8 Dec 2016 16:18:24 -0700 Subject: add passed scope to adhere to dynamic api response --- app/assets/stylesheets/pages/status.scss | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'app') diff --git a/app/assets/stylesheets/pages/status.scss b/app/assets/stylesheets/pages/status.scss index 5084b466722..c77995b8fb6 100644 --- a/app/assets/stylesheets/pages/status.scss +++ b/app/assets/stylesheets/pages/status.scss @@ -47,6 +47,20 @@ } } + &.ci-passed, + &.ci-passed_with_warnings { + color: $gl-success; + border-color: $gl-success; + + &:not(span):hover { + background-color: rgba( $gl-success, .07); + } + + svg { + fill: $gl-success; + } + } + &.ci-info { color: $gl-info; border-color: $gl-info; -- cgit v1.2.1 From 7f829f52e1faff770eca93b9ffdcd1c4832f62fd Mon Sep 17 00:00:00 2001 From: Munken Date: Thu, 8 Dec 2016 23:21:27 +0000 Subject: Don't double render --- app/assets/javascripts/syntax_highlight.js.erb | 3 +++ 1 file changed, 3 insertions(+) (limited to 'app') diff --git a/app/assets/javascripts/syntax_highlight.js.erb b/app/assets/javascripts/syntax_highlight.js.erb index 3b9a7d9baf9..ea79e82d887 100644 --- a/app/assets/javascripts/syntax_highlight.js.erb +++ b/app/assets/javascripts/syntax_highlight.js.erb @@ -19,6 +19,9 @@ // Loop over all math elements and render math var renderWithKaTeX = function (elements) { elements.each(function () { + if (!!$(this).attr('rendered')) return; + + $(this).attr('rendered', true); $(this).hide(); var mathNode = $( "Test" ); mathNode.insertAfter($(this)); -- cgit v1.2.1 From bff8e5bad99ccf515133a82576ca38165de0624c Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 8 Dec 2016 17:37:00 -0700 Subject: add change page logic to pagination component - add first test for pagination --- app/assets/javascripts/vue_pagination/index.js.es6 | 32 +++++++++++++++++++++- .../vue_pipelines_index/pipelines.js.es6 | 24 +++------------- 2 files changed, 35 insertions(+), 21 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pagination/index.js.es6 b/app/assets/javascripts/vue_pagination/index.js.es6 index 961f7101fb1..ed2357b5d9e 100644 --- a/app/assets/javascripts/vue_pagination/index.js.es6 +++ b/app/assets/javascripts/vue_pagination/index.js.es6 @@ -9,11 +9,41 @@ const FIRST = '<< First'; const LAST = 'Last >>'; + const getParameterByName = (name) => { + const url = window.location.href; + name = name.replace(/[[\]]/g, '\\$&'); + const regex = new RegExp(`[?&]${name}(=([^&#]*)|&|#|$)`); + const results = regex.exec(url); + if (!results) return null; + if (!results[2]) return ''; + return decodeURIComponent(results[2].replace(/\+/g, ' ')); + }; + gl.VueGlPagination = Vue.extend({ props: [ - 'changepage', + 'change', 'pageInfo', ], + methods: { + changepage(e) { + let pagenum = this.pageInfo.page; + let apiScope = getParameterByName('scope'); + + if (!apiScope) apiScope = 'all'; + + const text = e.target.innerText; + const { totalPages, nextPage, previousPage } = this.pageInfo; + + if (text === SPREAD) return; + if (/^-?[\d.]+(?:e-?\d+)?$/.test(text)) pagenum = +text; + if (text === LAST) pagenum = totalPages; + if (text === NEXT) pagenum = nextPage; + if (text === PREV) pagenum = previousPage; + if (text === FIRST) pagenum = 1; + + this.change(pagenum, apiScope); + }, + }, computed: { prev() { return this.pageInfo.previousPage; diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index 2c18b6cc7e5..ac889bb2d9f 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -2,12 +2,6 @@ /* eslint-disable no-param-reassign, no-bitwise*/ ((gl) => { - const SPREAD = '...'; - const PREV = 'Prev'; - const NEXT = 'Next'; - const FIRST = '<< First'; - const LAST = 'Last >>'; - const getParameterByName = (name) => { const url = window.location.href; name = name.replace(/[[\]]/g, '\\$&'); @@ -51,21 +45,11 @@ this.store.fetchDataLoop.call(this, Vue, this.pagenum, this.scope, this.apiScope); }, methods: { - changepage(e) { - const scope = getParameterByName('scope'); - if (scope) this.apiScope = scope; - const text = e.target.innerText; - const { totalPages, nextPage, previousPage } = this.pageInfo; - if (text === SPREAD) return; - if (/^-?[\d.]+(?:e-?\d+)?$/.test(text)) this.pagenum = +text; - if (text === LAST) this.pagenum = totalPages; - if (text === NEXT) this.pagenum = nextPage; - if (text === PREV) this.pagenum = previousPage; - if (text === FIRST) this.pagenum = 1; - window.history.pushState({}, null, `?scope=${this.apiScope}&p=${this.pagenum}`); + change(pagenum, apiScope) { + window.history.pushState({}, null, `?scope=${apiScope}&p=${pagenum}`); clearInterval(this.timeLoopInterval); this.pageRequest = true; - this.store.fetchDataLoop.call(this, Vue, this.pagenum, this.scope, this.apiScope); + this.store.fetchDataLoop.call(this, Vue, pagenum, this.scope, apiScope); }, author(pipeline) { if (!pipeline.commit) return ({ avatar_url: '', web_url: '', username: '' }); @@ -129,7 +113,7 @@ -- cgit v1.2.1 From 2ecb65b8c4a3fc277925938e691621e34c449664 Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 8 Dec 2016 17:41:59 -0700 Subject: extract param helper to pagination dir --- app/assets/javascripts/vue_pagination/index.js.es6 | 14 +++----------- app/assets/javascripts/vue_pagination/param_helper.js.es6 | 13 +++++++++++++ .../javascripts/vue_pipelines_index/pipelines.js.es6 | 14 ++------------ 3 files changed, 18 insertions(+), 23 deletions(-) create mode 100644 app/assets/javascripts/vue_pagination/param_helper.js.es6 (limited to 'app') diff --git a/app/assets/javascripts/vue_pagination/index.js.es6 b/app/assets/javascripts/vue_pagination/index.js.es6 index ed2357b5d9e..f0f0b54dd2b 100644 --- a/app/assets/javascripts/vue_pagination/index.js.es6 +++ b/app/assets/javascripts/vue_pagination/index.js.es6 @@ -1,6 +1,8 @@ /* global Vue, gl */ /* eslint-disable no-param-reassign, no-plusplus */ +//= require ./param_helper.js.es6 + ((gl) => { const PAGINATION_UI_BUTTON_LIMIT = 4; const SPREAD = '...'; @@ -9,16 +11,6 @@ const FIRST = '<< First'; const LAST = 'Last >>'; - const getParameterByName = (name) => { - const url = window.location.href; - name = name.replace(/[[\]]/g, '\\$&'); - const regex = new RegExp(`[?&]${name}(=([^&#]*)|&|#|$)`); - const results = regex.exec(url); - if (!results) return null; - if (!results[2]) return ''; - return decodeURIComponent(results[2].replace(/\+/g, ' ')); - }; - gl.VueGlPagination = Vue.extend({ props: [ 'change', @@ -27,7 +19,7 @@ methods: { changepage(e) { let pagenum = this.pageInfo.page; - let apiScope = getParameterByName('scope'); + let apiScope = gl.getParameterByName('scope'); if (!apiScope) apiScope = 'all'; diff --git a/app/assets/javascripts/vue_pagination/param_helper.js.es6 b/app/assets/javascripts/vue_pagination/param_helper.js.es6 new file mode 100644 index 00000000000..4c684f96e9e --- /dev/null +++ b/app/assets/javascripts/vue_pagination/param_helper.js.es6 @@ -0,0 +1,13 @@ +/* eslint-disable no-param-reassign */ + +((w) => { + w.getParameterByName = (name) => { + const url = window.location.href; + name = name.replace(/[[\]]/g, '\\$&'); + const regex = new RegExp(`[?&]${name}(=([^&#]*)|&|#|$)`); + const results = regex.exec(url); + if (!results) return null; + if (!results[2]) return ''; + return decodeURIComponent(results[2].replace(/\+/g, ' ')); + }; +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index ac889bb2d9f..2fdcaf3e16c 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -2,16 +2,6 @@ /* eslint-disable no-param-reassign, no-bitwise*/ ((gl) => { - const getParameterByName = (name) => { - const url = window.location.href; - name = name.replace(/[[\]]/g, '\\$&'); - const regex = new RegExp(`[?&]${name}(=([^&#]*)|&|#|$)`); - const results = regex.exec(url); - if (!results) return null; - if (!results[2]) return ''; - return decodeURIComponent(results[2].replace(/\+/g, ' ')); - }; - gl.VuePipelines = Vue.extend({ components: { runningPipeline: gl.VueRunningPipeline, @@ -38,8 +28,8 @@ }, props: ['scope', 'store'], created() { - const pagenum = getParameterByName('p'); - const scope = getParameterByName('scope'); + const pagenum = gl.getParameterByName('p'); + const scope = gl.getParameterByName('scope'); if (pagenum) this.pagenum = pagenum; if (scope) this.apiScope = scope; this.store.fetchDataLoop.call(this, Vue, this.pagenum, this.scope, this.apiScope); -- cgit v1.2.1 From b727a4399cb3f4ec2937d8135b3e2b769d887b0d Mon Sep 17 00:00:00 2001 From: Victor Wu Date: Fri, 9 Dec 2016 06:43:52 +0000 Subject: Remove unnecessary message --- app/views/projects/merge_requests/show/_commits.html.haml | 4 ---- 1 file changed, 4 deletions(-) (limited to 'app') diff --git a/app/views/projects/merge_requests/show/_commits.html.haml b/app/views/projects/merge_requests/show/_commits.html.haml index a0e12fb3f38..baa1ade5eee 100644 --- a/app/views/projects/merge_requests/show/_commits.html.haml +++ b/app/views/projects/merge_requests/show/_commits.html.haml @@ -1,6 +1,2 @@ -.content-block.oneline-block - = icon("sort-amount-desc") - Most recent commits displayed first - %ol#commits-list.list-unstyled = render "projects/commits/commits", project: @merge_request.source_project, ref: @merge_request.source_branch -- cgit v1.2.1 From 858ec6048223f2eec8c1386d33e3a6c5827233cb Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Fri, 9 Dec 2016 16:59:23 +0200 Subject: Handling OAuth2 errors --- app/controllers/import/bitbucket_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/controllers/import/bitbucket_controller.rb b/app/controllers/import/bitbucket_controller.rb index 12716d60e7d..b9cc6556140 100644 --- a/app/controllers/import/bitbucket_controller.rb +++ b/app/controllers/import/bitbucket_controller.rb @@ -2,7 +2,7 @@ class Import::BitbucketController < Import::BaseController before_action :verify_bitbucket_import_enabled before_action :bitbucket_auth, except: :callback - rescue_from OAuth::Error, with: :bitbucket_unauthorized + rescue_from OAuth2::Error, with: :bitbucket_unauthorized rescue_from Bitbucket::Error::Unauthorized, with: :bitbucket_unauthorized def callback -- cgit v1.2.1 From 1e8271b60bcd16b6fcc20d574c9583d593084eef Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Fri, 9 Dec 2016 17:24:21 +0000 Subject: Adds new partial for graph icons. Fix tests --- app/views/ci/status/_graph_icon_with_name.html.haml | 12 ++++++++++++ .../ci/status/_graph_icon_with_name_and_action.html.haml | 8 ++++++++ app/views/ci/status/_icon_with_name.html.haml | 3 +-- app/views/ci/status/_icon_with_name_and_action.html.haml | 2 +- app/views/projects/stage/_graph.html.haml | 2 +- app/views/projects/stage/_in_stage_group.html.haml | 2 +- 6 files changed, 24 insertions(+), 5 deletions(-) create mode 100644 app/views/ci/status/_graph_icon_with_name.html.haml create mode 100644 app/views/ci/status/_graph_icon_with_name_and_action.html.haml (limited to 'app') diff --git a/app/views/ci/status/_graph_icon_with_name.html.haml b/app/views/ci/status/_graph_icon_with_name.html.haml new file mode 100644 index 00000000000..51037a3bd20 --- /dev/null +++ b/app/views/ci/status/_graph_icon_with_name.html.haml @@ -0,0 +1,12 @@ +- detailed_status = subject.detailed_status(current_user) +- details_path = detailed_status.details_path if detailed_status.has_details? +- klass = "ci-status-icon ci-status-icon-#{detailed_status}" +- graph_status_icon = "#{detailed_status.icon}_graph" + +- if details_path + = link_to details_path, class: klass, data: { toggle: 'tooltip', title: "#{subject.name} - #{detailed_status}" } do + %span{ class: klass }= custom_icon(graph_status_icon) + .ci-status-text= subject.name +- else + %span{ class: klass }= custom_icon(graph_status_icon) + .ci-status-text= subject.name diff --git a/app/views/ci/status/_graph_icon_with_name_and_action.html.haml b/app/views/ci/status/_graph_icon_with_name_and_action.html.haml new file mode 100644 index 00000000000..525075ced70 --- /dev/null +++ b/app/views/ci/status/_graph_icon_with_name_and_action.html.haml @@ -0,0 +1,8 @@ += render "ci/status/graph_icon_with_name", subject: subject + +- detailed_status = subject.detailed_status(current_user) +- if detailed_status.has_action? + = link_to detailed_status.action_path, method: detailed_status.action_method, + title: "#{subject.name}: #{detailed_status.action_title}", class: 'ci-action-icon-container' do + %i.ci-action-icon-wrapper + = icon(detailed_status.action_icon, class: detailed_status.action_class) diff --git a/app/views/ci/status/_icon_with_name.html.haml b/app/views/ci/status/_icon_with_name.html.haml index a467316ef47..028e1fe9402 100644 --- a/app/views/ci/status/_icon_with_name.html.haml +++ b/app/views/ci/status/_icon_with_name.html.haml @@ -1,11 +1,10 @@ - detailed_status = subject.detailed_status(current_user) - details_path = detailed_status.details_path if detailed_status.has_details? - klass = "ci-status-icon ci-status-icon-#{detailed_status}" -- status_icon = graph ? "#{detailed_status.icon}_graph" : detailed_status.icon - if details_path = link_to details_path, class: klass, data: { toggle: 'tooltip', title: "#{subject.name} - #{detailed_status}" } do - %span{ class: klass }= custom_icon(status_icon) + %span{ class: klass }= custom_icon(detailed_status.icon) .ci-status-text= subject.name - else %span{ class: klass }= custom_icon(detailed_status.icon) diff --git a/app/views/ci/status/_icon_with_name_and_action.html.haml b/app/views/ci/status/_icon_with_name_and_action.html.haml index b912c212534..76db3b7f38a 100644 --- a/app/views/ci/status/_icon_with_name_and_action.html.haml +++ b/app/views/ci/status/_icon_with_name_and_action.html.haml @@ -1,4 +1,4 @@ -= render "ci/status/icon_with_name", subject: subject, graph: true += render "ci/status/icon_with_name", subject: subject - detailed_status = subject.detailed_status(current_user) - if detailed_status.has_action? diff --git a/app/views/projects/stage/_graph.html.haml b/app/views/projects/stage/_graph.html.haml index 745b6d143f4..255091cbfe8 100644 --- a/app/views/projects/stage/_graph.html.haml +++ b/app/views/projects/stage/_graph.html.haml @@ -14,7 +14,7 @@ %li.build{ class: ("playable" if is_playable) } .curve .build-content - = render 'ci/status/icon_with_name_and_action', subject: status + = render 'ci/status/graph_icon_with_name_and_action', subject: status - else %li.build .curve diff --git a/app/views/projects/stage/_in_stage_group.html.haml b/app/views/projects/stage/_in_stage_group.html.haml index 5c9b6549b37..70101ccf806 100644 --- a/app/views/projects/stage/_in_stage_group.html.haml +++ b/app/views/projects/stage/_in_stage_group.html.haml @@ -10,4 +10,4 @@ %ul - subject.each do |status| %li.dropdown-build - = render 'ci/status/icon_with_name_and_action', subject: status + = render 'ci/status/graph_icon_with_name_and_action', subject: status -- cgit v1.2.1 From f97965395198ef1da892dde246edb1e6ef480127 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Sat, 10 Dec 2016 02:25:31 +0800 Subject: Use consistent words, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7383#note_19581826 --- app/views/admin/deploy_keys/index.html.haml | 2 +- app/views/admin/deploy_keys/new.html.haml | 2 +- app/views/projects/deploy_keys/_deploy_key.html.haml | 4 ++-- app/views/projects/deploy_keys/_form.html.haml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/views/admin/deploy_keys/index.html.haml b/app/views/admin/deploy_keys/index.html.haml index dee611ae014..0ba8e087e08 100644 --- a/app/views/admin/deploy_keys/index.html.haml +++ b/app/views/admin/deploy_keys/index.html.haml @@ -11,7 +11,7 @@ %tr %th Title %th Fingerprint - %th Write access + %th Write access allowed %th Added at %th %tbody diff --git a/app/views/admin/deploy_keys/new.html.haml b/app/views/admin/deploy_keys/new.html.haml index 96055174ad0..a064efc231f 100644 --- a/app/views/admin/deploy_keys/new.html.haml +++ b/app/views/admin/deploy_keys/new.html.haml @@ -21,7 +21,7 @@ .col-sm-10 = f.label :can_push do = f.check_box :can_push - %strong Write access allowed? + %strong Write access allowed %p.light.append-bottom-0 Allow this key to push to repository as well? (Default only allows pull access.) diff --git a/app/views/projects/deploy_keys/_deploy_key.html.haml b/app/views/projects/deploy_keys/_deploy_key.html.haml index d360f1bab28..d1e3cb14022 100644 --- a/app/views/projects/deploy_keys/_deploy_key.html.haml +++ b/app/views/projects/deploy_keys/_deploy_key.html.haml @@ -7,8 +7,8 @@ .description = deploy_key.fingerprint - if deploy_key.can_push? - .can-write - Can write + .write-access-allowed + Write access allowed .deploy-key-content.prepend-left-default.deploy-key-projects - deploy_key.projects.each do |project| - if can?(current_user, :read_project, project) diff --git a/app/views/projects/deploy_keys/_form.html.haml b/app/views/projects/deploy_keys/_form.html.haml index 757260aa5b5..c91bb9c255a 100644 --- a/app/views/projects/deploy_keys/_form.html.haml +++ b/app/views/projects/deploy_keys/_form.html.haml @@ -14,7 +14,7 @@ .checkbox = f.label :can_push do = f.check_box :can_push - %strong Write access allowed? + %strong Write access allowed .form-group %p.light.append-bottom-0 Allow this key to push to repository as well? (Default only allows pull access.) -- cgit v1.2.1 From 67e46e6f9f73b25b7fc2428cfac3110ada849f35 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 9 Dec 2016 21:56:12 +0100 Subject: Integrate new stages into ci pipeline serializer --- app/serializers/pipeline_entity.rb | 2 +- app/serializers/pipeline_stage_entity.rb | 11 +++-------- 2 files changed, 4 insertions(+), 9 deletions(-) (limited to 'app') diff --git a/app/serializers/pipeline_entity.rb b/app/serializers/pipeline_entity.rb index a07abb4bec0..e071c03e20b 100644 --- a/app/serializers/pipeline_entity.rb +++ b/app/serializers/pipeline_entity.rb @@ -15,7 +15,7 @@ class PipelineEntity < Grape::Entity expose :detailed_status, as: :status, using: StatusEntity expose :duration expose :finished_at - expose :stages_with_statuses, as: :stages, using: PipelineStageEntity + expose :stages, using: PipelineStageEntity expose :artifacts, using: PipelineArtifactEntity expose :manual_actions, using: PipelineActionEntity end diff --git a/app/serializers/pipeline_stage_entity.rb b/app/serializers/pipeline_stage_entity.rb index 230ef8a22da..e4681a0a633 100644 --- a/app/serializers/pipeline_stage_entity.rb +++ b/app/serializers/pipeline_stage_entity.rb @@ -1,15 +1,10 @@ class PipelineStageEntity < Grape::Entity include RequestAwareEntity - expose :name do |stage| - stage.name - end - - expose :status do |stage| - stage.status || 'not found' - end + expose :name + expose :detailed_status, as: :status, using: StatusEntity - expose :url do |stage| + expose :path do |stage| namespace_project_pipeline_path( stage.pipeline.project.namespace, stage.pipeline.project, -- cgit v1.2.1 From ee10a1cc5157e78384bac16f9ee2cf43d66513df Mon Sep 17 00:00:00 2001 From: tauriedavis Date: Wed, 30 Nov 2016 12:37:54 -0800 Subject: 20916 Shorten line length of issues and mrs --- app/assets/javascripts/issue.js | 6 ++++++ app/assets/javascripts/merge_request.js | 6 ++++++ app/assets/stylesheets/framework/layout.scss | 4 ++++ app/assets/stylesheets/framework/variables.scss | 3 +++ app/assets/stylesheets/pages/issuable.scss | 13 +++++++++++++ 5 files changed, 32 insertions(+) (limited to 'app') diff --git a/app/assets/javascripts/issue.js b/app/assets/javascripts/issue.js index 8540b199aba..56a2b6a5295 100644 --- a/app/assets/javascripts/issue.js +++ b/app/assets/javascripts/issue.js @@ -11,6 +11,7 @@ function Issue() { this.submitNoteForm = bind(this.submitNoteForm, this); // Prevent duplicate event bindings + this.limitContainerWidth(); this.disableTaskList(); if ($('a.btn-close').length) { this.initTaskList(); @@ -21,6 +22,11 @@ this.initCanCreateBranch(); } + Issue.prototype.limitContainerWidth = function() { + var $wrapper = $('.content-wrapper .container-fluid'); + $wrapper.addClass('limit-container-width') + }; + Issue.prototype.initTaskList = function() { $('.detail-page-description .js-task-list-container').taskList('enable'); return $(document).on('tasklist:changed', '.detail-page-description .js-task-list-container', this.updateTaskList); diff --git a/app/assets/javascripts/merge_request.js b/app/assets/javascripts/merge_request.js index 88c3636be6c..b3a1ec39c13 100644 --- a/app/assets/javascripts/merge_request.js +++ b/app/assets/javascripts/merge_request.js @@ -14,6 +14,7 @@ // Options: // action - String, current controller action // + this.limitContainerWidth(); this.opts = opts != null ? opts : {}; this.submitNoteForm = bind(this.submitNoteForm, this); this.$el = $('.merge-request'); @@ -31,6 +32,11 @@ } } + MergeRequest.prototype.limitContainerWidth = function() { + var $wrapper = $('.content-wrapper .container-fluid'); + $wrapper.addClass('limit-container-width') + }; + // Local jQuery finder MergeRequest.prototype.$ = function(selector) { return this.$el.find(selector); diff --git a/app/assets/stylesheets/framework/layout.scss b/app/assets/stylesheets/framework/layout.scss index dfaf2f7f1d3..66711aa1804 100644 --- a/app/assets/stylesheets/framework/layout.scss +++ b/app/assets/stylesheets/framework/layout.scss @@ -26,6 +26,10 @@ body { .container-limited { max-width: $fixed-layout-width; + + &.limit-container-width { + max-width: $limited-layout-width; + } } diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 18716813c48..55d97b9219c 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -166,6 +166,9 @@ $row-hover-border: #b2d7ff; $progress-color: #c0392b; $header-height: 50px; $fixed-layout-width: 1280px; +$limited-layout-width: 958px; +$line-length-width: 700px; +$gl-avatar-size: 40px; $error-exclamation-point: #e62958; $border-radius-default: 2px; $btn-transparent-color: #8f8f8f; diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 90587b9425b..6c35496b846 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -1,3 +1,16 @@ +.container-limited.limit-container-width { + .issue-details { + .description, + .note-body { + p, + ul, + ol, + .code { + max-width: $line-length-width; + } + } + } +} .issuable-details { section { .issuable-discussion { -- cgit v1.2.1 From 258ab29435d4a02ab5ded6c19de597fdf847ef80 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Fri, 2 Dec 2016 10:13:04 -0600 Subject: Add content_class for limited width --- app/assets/javascripts/issue.js | 6 ------ app/assets/javascripts/merge_request.js | 6 ------ app/assets/stylesheets/pages/issuable.scss | 1 + app/views/projects/issues/show.html.haml | 1 + app/views/projects/merge_requests/_show.html.haml | 1 + 5 files changed, 3 insertions(+), 12 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/issue.js b/app/assets/javascripts/issue.js index 56a2b6a5295..8540b199aba 100644 --- a/app/assets/javascripts/issue.js +++ b/app/assets/javascripts/issue.js @@ -11,7 +11,6 @@ function Issue() { this.submitNoteForm = bind(this.submitNoteForm, this); // Prevent duplicate event bindings - this.limitContainerWidth(); this.disableTaskList(); if ($('a.btn-close').length) { this.initTaskList(); @@ -22,11 +21,6 @@ this.initCanCreateBranch(); } - Issue.prototype.limitContainerWidth = function() { - var $wrapper = $('.content-wrapper .container-fluid'); - $wrapper.addClass('limit-container-width') - }; - Issue.prototype.initTaskList = function() { $('.detail-page-description .js-task-list-container').taskList('enable'); return $(document).on('tasklist:changed', '.detail-page-description .js-task-list-container', this.updateTaskList); diff --git a/app/assets/javascripts/merge_request.js b/app/assets/javascripts/merge_request.js index b3a1ec39c13..88c3636be6c 100644 --- a/app/assets/javascripts/merge_request.js +++ b/app/assets/javascripts/merge_request.js @@ -14,7 +14,6 @@ // Options: // action - String, current controller action // - this.limitContainerWidth(); this.opts = opts != null ? opts : {}; this.submitNoteForm = bind(this.submitNoteForm, this); this.$el = $('.merge-request'); @@ -32,11 +31,6 @@ } } - MergeRequest.prototype.limitContainerWidth = function() { - var $wrapper = $('.content-wrapper .container-fluid'); - $wrapper.addClass('limit-container-width') - }; - // Local jQuery finder MergeRequest.prototype.$ = function(selector) { return this.$el.find(selector); diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 6c35496b846..2357dd2fe6f 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -11,6 +11,7 @@ } } } + .issuable-details { section { .issuable-discussion { diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index bd629b5c519..981bf640a6b 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -1,3 +1,4 @@ +- @content_class = "limit-container-width" - page_title "#{@issue.title} (#{@issue.to_reference})", "Issues" - page_description @issue.description - page_card_attributes @issue.card_attributes diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml index 896f10104fa..0db5548d36e 100644 --- a/app/views/projects/merge_requests/_show.html.haml +++ b/app/views/projects/merge_requests/_show.html.haml @@ -1,3 +1,4 @@ +- @content_class = "limit-container-width" - page_title "#{@merge_request.title} (#{@merge_request.to_reference})", "Merge Requests" - page_description @merge_request.description - page_card_attributes @merge_request.card_attributes -- cgit v1.2.1 From 793a717bad5491c523d4551ef72287f8be9c1062 Mon Sep 17 00:00:00 2001 From: Ryan Harris Date: Fri, 9 Dec 2016 23:59:20 -0500 Subject: Change cursor type only for inactive stage-nav-items on Cycle Analytics page --- app/assets/stylesheets/pages/cycle_analytics.scss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/cycle_analytics.scss b/app/assets/stylesheets/pages/cycle_analytics.scss index ce708106490..21a5bd047f7 100644 --- a/app/assets/stylesheets/pages/cycle_analytics.scss +++ b/app/assets/stylesheets/pages/cycle_analytics.scss @@ -215,7 +215,7 @@ border-bottom: 1px solid transparent; border-right: 1px solid $border-color; background-color: $gray-light; - cursor: pointer; + cursor: default; &.active { background-color: transparent; @@ -232,6 +232,7 @@ &:hover:not(.active) { background-color: $gray-lightest; box-shadow: inset 2px 0 0 0 $border-color; + cursor: pointer; } &:first-child { -- cgit v1.2.1 From d8b7df3cbcfd4fcdf204fdcba01720e60fb598bf Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 8 Dec 2016 20:59:41 +0200 Subject: Add support for nested groups to admin routing Signed-off-by: Dmitriy Zaporozhets --- app/views/admin/dashboard/_head.html.haml | 2 +- app/views/admin/dashboard/index.html.haml | 2 +- app/views/admin/groups/_group.html.haml | 2 +- app/views/admin/groups/show.html.haml | 4 ++-- app/views/admin/projects/index.html.haml | 12 ++++++------ app/views/repository_check_mailer/notify.html.haml | 2 +- app/views/repository_check_mailer/notify.text.haml | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) (limited to 'app') diff --git a/app/views/admin/dashboard/_head.html.haml b/app/views/admin/dashboard/_head.html.haml index ec40391a3e3..b5f96363230 100644 --- a/app/views/admin/dashboard/_head.html.haml +++ b/app/views/admin/dashboard/_head.html.haml @@ -8,7 +8,7 @@ %span Overview = nav_link(controller: [:admin, :projects]) do - = link_to admin_namespaces_projects_path, title: 'Projects' do + = link_to admin_projects_path, title: 'Projects' do %span Projects = nav_link(controller: :users) do diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml index e51f4ac1d93..5238623e936 100644 --- a/app/views/admin/dashboard/index.html.haml +++ b/app/views/admin/dashboard/index.html.haml @@ -116,7 +116,7 @@ .light-well.well-centered %h4 Projects .data - = link_to admin_namespaces_projects_path do + = link_to admin_projects_path do %h1= number_with_delimiter(Project.cached_count) %hr = link_to('New Project', new_project_path, class: "btn btn-new") diff --git a/app/views/admin/groups/_group.html.haml b/app/views/admin/groups/_group.html.haml index 664bb417c6a..4efeec0ea4e 100644 --- a/app/views/admin/groups/_group.html.haml +++ b/app/views/admin/groups/_group.html.haml @@ -2,7 +2,7 @@ %li.group-row{ class: css_class } .controls - = link_to 'Edit', edit_admin_group_path(group), id: "edit_#{dom_id(group)}", class: 'btn' + = link_to 'Edit', admin_group_edit_path(group), id: "edit_#{dom_id(group)}", class: 'btn' = link_to 'Delete', [:admin, group], data: { confirm: "Are you sure you want to remove #{group.name}?" }, method: :delete, class: 'btn btn-remove' .stats %span diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml index 40871e32913..71a605f33b1 100644 --- a/app/views/admin/groups/show.html.haml +++ b/app/views/admin/groups/show.html.haml @@ -2,7 +2,7 @@ %h3.page-title Group: #{@group.name} - = link_to edit_admin_group_path(@group), class: "btn pull-right" do + = link_to admin_group_edit_path(@group), class: "btn pull-right" do %i.fa.fa-pencil-square-o Edit %hr @@ -88,7 +88,7 @@ Read more about project permissions %strong= link_to "here", help_page_path("user/permissions"), class: "vlink" - = form_tag members_update_admin_group_path(@group), id: "new_project_member", class: "bulk_import", method: :put do + = form_tag admin_group_members_update_path(@group), id: "new_project_member", class: "bulk_import", method: :put do %div = users_select_tag(:user_ids, multiple: true, email_user: true, scope: :all) %div.prepend-top-10 diff --git a/app/views/admin/projects/index.html.haml b/app/views/admin/projects/index.html.haml index b37b8d4fee7..8bc7dc7dd51 100644 --- a/app/views/admin/projects/index.html.haml +++ b/app/views/admin/projects/index.html.haml @@ -7,7 +7,7 @@ %div{ class: container_class } .top-area .prepend-top-default - = form_tag admin_namespaces_projects_path, method: :get do |f| + = form_tag admin_projects_path, method: :get do |f| .search-holder .search-field-holder = search_field_tag :name, params[:name], class: "form-control search-text-input js-search-input", id: "dashboard_search", autofocus: true, spellcheck: false, placeholder: 'Search by name' @@ -41,19 +41,19 @@ = button_tag "Search", class: "btn btn-primary btn-search" %ul.nav-links - - opts = params[:visibility_level].present? ? {} : { page: admin_namespaces_projects_path } + - opts = params[:visibility_level].present? ? {} : { page: admin_projects_path } = nav_link(opts) do - = link_to admin_namespaces_projects_path do + = link_to admin_projects_path do All = nav_link(html_options: { class: params[:visibility_level] == Gitlab::VisibilityLevel::PRIVATE.to_s ? 'active' : '' }) do - = link_to admin_namespaces_projects_path(visibility_level: Gitlab::VisibilityLevel::PRIVATE) do + = link_to admin_projects_path(visibility_level: Gitlab::VisibilityLevel::PRIVATE) do Private = nav_link(html_options: { class: params[:visibility_level] == Gitlab::VisibilityLevel::INTERNAL.to_s ? 'active' : '' }) do - = link_to admin_namespaces_projects_path(visibility_level: Gitlab::VisibilityLevel::INTERNAL) do + = link_to admin_projects_path(visibility_level: Gitlab::VisibilityLevel::INTERNAL) do Internal = nav_link(html_options: { class: params[:visibility_level] == Gitlab::VisibilityLevel::PUBLIC.to_s ? 'active' : '' }) do - = link_to admin_namespaces_projects_path(visibility_level: Gitlab::VisibilityLevel::PUBLIC) do + = link_to admin_projects_path(visibility_level: Gitlab::VisibilityLevel::PUBLIC) do Public .nav-controls diff --git a/app/views/repository_check_mailer/notify.html.haml b/app/views/repository_check_mailer/notify.html.haml index a585147ddd1..94e5a5d9709 100644 --- a/app/views/repository_check_mailer/notify.html.haml +++ b/app/views/repository_check_mailer/notify.html.haml @@ -2,7 +2,7 @@ #{@message}. %p - = link_to "See the affected projects in the GitLab admin panel", admin_namespaces_projects_url(last_repository_check_failed: 1) + = link_to "See the affected projects in the GitLab admin panel", admin_projects_url(last_repository_check_failed: 1) %p You are receiving this message because you are a GitLab administrator for #{Gitlab.config.gitlab.url}. diff --git a/app/views/repository_check_mailer/notify.text.haml b/app/views/repository_check_mailer/notify.text.haml index 93db151329e..0902c50d052 100644 --- a/app/views/repository_check_mailer/notify.text.haml +++ b/app/views/repository_check_mailer/notify.text.haml @@ -1,6 +1,6 @@ #{@message}. \ -View details: #{admin_namespaces_projects_url(last_repository_check_failed: 1)} +View details: #{admin_projects_url(last_repository_check_failed: 1)} You are receiving this message because you are a GitLab administrator for #{Gitlab.config.gitlab.url}. -- cgit v1.2.1 From e1f563109c19a08405170d281a7ac537b7c881ff Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Mon, 12 Dec 2016 09:54:27 +0000 Subject: Fixed GFM autocomplete to disallow non-word characters in string Closes #25540 --- app/assets/javascripts/gfm_auto_complete.js.es6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/gfm_auto_complete.js.es6 b/app/assets/javascripts/gfm_auto_complete.js.es6 index 6f9d6283071..076475d3ed4 100644 --- a/app/assets/javascripts/gfm_auto_complete.js.es6 +++ b/app/assets/javascripts/gfm_auto_complete.js.es6 @@ -69,7 +69,7 @@ _a = decodeURI("%C3%80"); _y = decodeURI("%C3%BF"); - regexp = new RegExp("(?:\\B|\\W|\\s)" + flag + "(?!\\W)([A-Za-z" + _a + "-" + _y + "0-9_\'\.\+\-]*)|([^\\x00-\\xff]*)$", 'gi'); + regexp = new RegExp("(?:\\B|\\W|\\s)" + flag + "(?!\\W)([A-Za-z" + _a + "-" + _y + "0-9_\'\.\+\-]*)$", 'gi'); match = regexp.exec(subtext); -- cgit v1.2.1 From f726dfba6269c68ce17a81a7f973e6b5e23964cb Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 12 Dec 2016 18:47:12 +0800 Subject: Use btn-inverted for New Deploy Key --- app/views/admin/deploy_keys/index.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/admin/deploy_keys/index.html.haml b/app/views/admin/deploy_keys/index.html.haml index 0ba8e087e08..646c9815cfe 100644 --- a/app/views/admin/deploy_keys/index.html.haml +++ b/app/views/admin/deploy_keys/index.html.haml @@ -3,7 +3,7 @@ .panel-heading Public deploy keys (#{@deploy_keys.count}) .controls - = link_to 'New Deploy Key', new_admin_deploy_key_path, class: "btn btn-new btn-sm" + = link_to 'New Deploy Key', new_admin_deploy_key_path, class: "btn btn-new btn-sm btn-inverted" - if @deploy_keys.any? .table-holder %table.table -- cgit v1.2.1 From 633e64382d30674fecb1aaf138d18c73827c9a40 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 8 Dec 2016 09:51:36 +0100 Subject: Added Ci::Status::Build --- app/models/ci/build.rb | 4 ++++ app/models/commit_status.rb | 4 ++++ 2 files changed, 8 insertions(+) (limited to 'app') diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 88c46076df6..0f4c498c266 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -100,6 +100,10 @@ module Ci end end + def detailed_status + Gitlab::Ci::Status::Build::Factory.new(self).fabricate! + end + def manual? self.when == 'manual' end diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index cf90475f4d4..fce16174e22 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -131,4 +131,8 @@ class CommitStatus < ActiveRecord::Base def has_trace? false end + + def detailed_status + Gitlab::Ci::Status::Factory.new(self).fabricate! + end end -- cgit v1.2.1 From 516dc7a5be3624f1866fa46f19f6472e2f9fae22 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 8 Dec 2016 10:40:56 +0100 Subject: Improve actions --- app/models/ci/build.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app') diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 0f4c498c266..73564dd2aa0 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -127,6 +127,10 @@ module Ci end end + def cancelable? + active? + end + def retryable? project.builds_enabled? && commands.present? && complete? end -- cgit v1.2.1 From feaf01802c092be8f55994c910f2975376cbd20f Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 8 Dec 2016 11:03:01 +0100 Subject: Remove ci_status_with_icon helper and replace it with partial [ci skip] --- app/helpers/ci_status_helper.rb | 20 +------------------- app/views/admin/runners/show.html.haml | 2 +- app/views/ci/status/_icon_with_label.html.haml | 10 ++++++++++ app/views/projects/builds/_header.html.haml | 2 +- app/views/projects/ci/builds/_build.html.haml | 5 +---- app/views/projects/ci/pipelines/_pipeline.html.haml | 5 +---- .../_generic_commit_status.html.haml | 5 +---- app/views/projects/pipelines/_info.html.haml | 2 +- 8 files changed, 17 insertions(+), 34 deletions(-) create mode 100644 app/views/ci/status/_icon_with_label.html.haml (limited to 'app') diff --git a/app/helpers/ci_status_helper.rb b/app/helpers/ci_status_helper.rb index 8e19752a8a1..d9f5e01f0dc 100644 --- a/app/helpers/ci_status_helper.rb +++ b/app/helpers/ci_status_helper.rb @@ -4,25 +4,7 @@ module CiStatusHelper builds_namespace_project_commit_path(project.namespace, project, pipeline.sha) end - def ci_status_with_icon(status, target = nil) - content = ci_icon_for_status(status) + ci_text_for_status(status) - klass = "ci-status ci-#{status}" - - if target - link_to content, target, class: klass - else - content_tag :span, content, class: klass - end - end - - def ci_text_for_status(status) - if detailed_status?(status) - status.text - else - status - end - end - + # Is used by Commit and Merge Request Widget def ci_label_for_status(status) if detailed_status?(status) return status.label diff --git a/app/views/admin/runners/show.html.haml b/app/views/admin/runners/show.html.haml index 73038164056..fa8be25ffa8 100644 --- a/app/views/admin/runners/show.html.haml +++ b/app/views/admin/runners/show.html.haml @@ -91,7 +91,7 @@ %strong ##{build.id} %td.status - = ci_status_with_icon(build.status) + = render "ci/status/icon_with_label", subject: build %td.status - if project diff --git a/app/views/ci/status/_icon_with_label.html.haml b/app/views/ci/status/_icon_with_label.html.haml new file mode 100644 index 00000000000..65a74e88444 --- /dev/null +++ b/app/views/ci/status/_icon_with_label.html.haml @@ -0,0 +1,10 @@ +- details_path = subject.details_path if subject.has_details?(current_user) +- klass = "ci-status ci-#{subject.status}" +- if details_path + = link_to details_path, class: klass do + = custom_icon(status.icon) + = status.text +- else + %span{ class: klass } + = custom_icon(status.icon) + = status.text diff --git a/app/views/projects/builds/_header.html.haml b/app/views/projects/builds/_header.html.haml index f6aa20c4579..5e4e30f08d5 100644 --- a/app/views/projects/builds/_header.html.haml +++ b/app/views/projects/builds/_header.html.haml @@ -1,6 +1,6 @@ .content-block.build-header .header-content - = ci_status_with_icon(@build.status) + = render "ci/status/icon_with_label", subject: build Build %strong ##{@build.id} in pipeline diff --git a/app/views/projects/ci/builds/_build.html.haml b/app/views/projects/ci/builds/_build.html.haml index 18b3b04154f..6b0cd3e49a0 100644 --- a/app/views/projects/ci/builds/_build.html.haml +++ b/app/views/projects/ci/builds/_build.html.haml @@ -9,10 +9,7 @@ %tr.build.commit{class: ('retried' if retried)} %td.status - - if can?(current_user, :read_build, build) - = ci_status_with_icon(build.status, namespace_project_build_url(build.project.namespace, build.project, build)) - - else - = ci_status_with_icon(build.status) + = render "ci/status/icon_with_label", subject: build %td.branch-commit - if can?(current_user, :read_build, build) diff --git a/app/views/projects/ci/pipelines/_pipeline.html.haml b/app/views/projects/ci/pipelines/_pipeline.html.haml index b58dceb58c9..84243e4306d 100644 --- a/app/views/projects/ci/pipelines/_pipeline.html.haml +++ b/app/views/projects/ci/pipelines/_pipeline.html.haml @@ -1,13 +1,10 @@ - status = pipeline.status -- detailed_status = pipeline.detailed_status - show_commit = local_assigns.fetch(:show_commit, true) - show_branch = local_assigns.fetch(:show_branch, true) %tr.commit %td.commit-link - = link_to namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id), class: "ci-status ci-#{detailed_status}" do - = ci_icon_for_status(detailed_status) - = ci_text_for_status(detailed_status) + = render "ci/status/icon_with_label", subject: pipeline %td = link_to namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id) do diff --git a/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml b/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml index 7f751d9ae2e..69cb1631ee8 100644 --- a/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml +++ b/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml @@ -8,10 +8,7 @@ %tr.generic_commit_status{class: ('retried' if retried)} %td.status - - if can?(current_user, :read_commit_status, generic_commit_status) && generic_commit_status.target_url - = ci_status_with_icon(generic_commit_status.status, generic_commit_status.target_url) - - else - = ci_status_with_icon(generic_commit_status.status) + = render "ci/status/icon_with_label", subject: generic_commit_status %td.generic_commit_status-link - if can?(current_user, :read_commit_status, generic_commit_status) && generic_commit_status.target_url diff --git a/app/views/projects/pipelines/_info.html.haml b/app/views/projects/pipelines/_info.html.haml index 229bdfb0e8d..f7385184a2b 100644 --- a/app/views/projects/pipelines/_info.html.haml +++ b/app/views/projects/pipelines/_info.html.haml @@ -1,6 +1,6 @@ .page-content-header .header-main-content - = ci_status_with_icon(@pipeline.detailed_status) + = render "ci/status/icon_with_label", subject: @pipeline %strong Pipeline ##{@commit.pipelines.last.id} triggered #{time_ago_with_tooltip(@commit.authored_date)} by = author_avatar(@commit, size: 24) -- cgit v1.2.1 From f0cd73bfadbe9fa27b25473dab61d8c566292392 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 8 Dec 2016 14:51:38 +0100 Subject: Fix some detailed statuses specs related to abilities --- app/models/ability.rb | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'app') diff --git a/app/models/ability.rb b/app/models/ability.rb index fa8f8bc3a5f..ce461caf686 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -1,4 +1,10 @@ class Ability + module Allowable + def can?(user, action, subject) + Ability.allowed?(user, action, subject) + end + end + class << self # Given a list of users and a project this method returns the users that can # read the given project. -- cgit v1.2.1 From 980009e6e85562c9ee8026878929d09905b2a0a9 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 8 Dec 2016 17:52:24 +0100 Subject: Fix auto loading of constants for Ci Statuses --- app/models/ci/build.rb | 6 +++--- app/models/ci/pipeline.rb | 4 ++-- app/models/ci/stage.rb | 4 ++-- app/models/commit_status.rb | 4 ++-- app/views/ci/status/_icon_with_label.html.haml | 13 +++++++------ 5 files changed, 16 insertions(+), 15 deletions(-) (limited to 'app') diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 73564dd2aa0..65ee327a8e5 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -100,8 +100,8 @@ module Ci end end - def detailed_status - Gitlab::Ci::Status::Build::Factory.new(self).fabricate! + def detailed_status(current_user) + Gitlab::Ci::Status::Build::Factory.new(self, current_user).fabricate! end def manual? @@ -156,7 +156,7 @@ module Ci end def environment_action - self.options.fetch(:environment, {}).fetch(:action, 'start') + self.options.fetch(:environment, {}).fetch(:action, 'start') if self.options end def outdated_deployment? diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index fda8228a1e9..1f33106d358 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -336,8 +336,8 @@ module Ci .select { |merge_request| merge_request.head_pipeline.try(:id) == self.id } end - def detailed_status - Gitlab::Ci::Status::Pipeline::Factory.new(self).fabricate! + def detailed_status(current_user) + Gitlab::Ci::Status::Pipeline::Factory.new(self, current_user).fabricate! end private diff --git a/app/models/ci/stage.rb b/app/models/ci/stage.rb index d2a37c0a827..be52cce20f1 100644 --- a/app/models/ci/stage.rb +++ b/app/models/ci/stage.rb @@ -22,8 +22,8 @@ module Ci @status ||= statuses.latest.status end - def detailed_status - Gitlab::Ci::Status::Stage::Factory.new(self).fabricate! + def detailed_status(current_user) + Gitlab::Ci::Status::Stage::Factory.new(self, current_user).fabricate! end def statuses diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index fce16174e22..6548a7dda2c 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -132,7 +132,7 @@ class CommitStatus < ActiveRecord::Base false end - def detailed_status - Gitlab::Ci::Status::Factory.new(self).fabricate! + def detailed_status(current_user) + Gitlab::Ci::Status::Factory.new(self, current_user).fabricate! end end diff --git a/app/views/ci/status/_icon_with_label.html.haml b/app/views/ci/status/_icon_with_label.html.haml index 65a74e88444..d3fe332cc78 100644 --- a/app/views/ci/status/_icon_with_label.html.haml +++ b/app/views/ci/status/_icon_with_label.html.haml @@ -1,10 +1,11 @@ -- details_path = subject.details_path if subject.has_details?(current_user) -- klass = "ci-status ci-#{subject.status}" +- detailed_status = subject.detailed_status(current_user) +- details_path = detailed_status.details_path if detailed_status.has_details? +- klass = "ci-status ci-#{detailed_status}" - if details_path = link_to details_path, class: klass do - = custom_icon(status.icon) - = status.text + = custom_icon(detailed_status.icon) + = detailed_status.text - else %span{ class: klass } - = custom_icon(status.icon) - = status.text + = custom_icon(detailed_status.icon) + = detailed_status.text -- cgit v1.2.1 From d1dd89356c4cd5e70f2b81ef416e52b745486293 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 8 Dec 2016 18:16:23 +0100 Subject: Rename icon_with_label to icon_with_description --- app/views/admin/runners/show.html.haml | 2 +- app/views/ci/status/_icon_with_description.html.haml | 12 ++++++++++++ app/views/ci/status/_icon_with_label.html.haml | 11 ----------- app/views/projects/builds/_header.html.haml | 2 +- app/views/projects/ci/builds/_build.html.haml | 2 +- app/views/projects/ci/pipelines/_pipeline.html.haml | 2 +- .../generic_commit_statuses/_generic_commit_status.html.haml | 2 +- app/views/projects/pipelines/_info.html.haml | 2 +- app/views/projects/stage/_graph.html.haml | 4 ++-- 9 files changed, 20 insertions(+), 19 deletions(-) create mode 100644 app/views/ci/status/_icon_with_description.html.haml delete mode 100644 app/views/ci/status/_icon_with_label.html.haml (limited to 'app') diff --git a/app/views/admin/runners/show.html.haml b/app/views/admin/runners/show.html.haml index fa8be25ffa8..badeb11b208 100644 --- a/app/views/admin/runners/show.html.haml +++ b/app/views/admin/runners/show.html.haml @@ -91,7 +91,7 @@ %strong ##{build.id} %td.status - = render "ci/status/icon_with_label", subject: build + = render "ci/status/icon_with_description", subject: build %td.status - if project diff --git a/app/views/ci/status/_icon_with_description.html.haml b/app/views/ci/status/_icon_with_description.html.haml new file mode 100644 index 00000000000..34c923440d0 --- /dev/null +++ b/app/views/ci/status/_icon_with_description.html.haml @@ -0,0 +1,12 @@ +- detailed_status = subject.detailed_status(current_user) +- details_path = detailed_status.details_path if detailed_status.has_details? +- klass = "ci-status ci-#{detailed_status}" + +- if details_path + = link_to details_path, class: klass do + = custom_icon(detailed_status.icon) + = detailed_status.text +- else + %span{ class: klass } + = custom_icon(detailed_status.icon) + = detailed_status.text diff --git a/app/views/ci/status/_icon_with_label.html.haml b/app/views/ci/status/_icon_with_label.html.haml deleted file mode 100644 index d3fe332cc78..00000000000 --- a/app/views/ci/status/_icon_with_label.html.haml +++ /dev/null @@ -1,11 +0,0 @@ -- detailed_status = subject.detailed_status(current_user) -- details_path = detailed_status.details_path if detailed_status.has_details? -- klass = "ci-status ci-#{detailed_status}" -- if details_path - = link_to details_path, class: klass do - = custom_icon(detailed_status.icon) - = detailed_status.text -- else - %span{ class: klass } - = custom_icon(detailed_status.icon) - = detailed_status.text diff --git a/app/views/projects/builds/_header.html.haml b/app/views/projects/builds/_header.html.haml index 5e4e30f08d5..85d1793ecb9 100644 --- a/app/views/projects/builds/_header.html.haml +++ b/app/views/projects/builds/_header.html.haml @@ -1,6 +1,6 @@ .content-block.build-header .header-content - = render "ci/status/icon_with_label", subject: build + = render "ci/status/icon_with_description", subject: build Build %strong ##{@build.id} in pipeline diff --git a/app/views/projects/ci/builds/_build.html.haml b/app/views/projects/ci/builds/_build.html.haml index 6b0cd3e49a0..4257bb86859 100644 --- a/app/views/projects/ci/builds/_build.html.haml +++ b/app/views/projects/ci/builds/_build.html.haml @@ -9,7 +9,7 @@ %tr.build.commit{class: ('retried' if retried)} %td.status - = render "ci/status/icon_with_label", subject: build + = render "ci/status/icon_with_description", subject: build %td.branch-commit - if can?(current_user, :read_build, build) diff --git a/app/views/projects/ci/pipelines/_pipeline.html.haml b/app/views/projects/ci/pipelines/_pipeline.html.haml index 84243e4306d..6dff955ea3d 100644 --- a/app/views/projects/ci/pipelines/_pipeline.html.haml +++ b/app/views/projects/ci/pipelines/_pipeline.html.haml @@ -4,7 +4,7 @@ %tr.commit %td.commit-link - = render "ci/status/icon_with_label", subject: pipeline + = render "ci/status/icon_with_description", subject: pipeline %td = link_to namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id) do diff --git a/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml b/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml index 69cb1631ee8..1dd07ae1a2a 100644 --- a/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml +++ b/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml @@ -8,7 +8,7 @@ %tr.generic_commit_status{class: ('retried' if retried)} %td.status - = render "ci/status/icon_with_label", subject: generic_commit_status + = render "ci/status/icon_with_description", subject: generic_commit_status %td.generic_commit_status-link - if can?(current_user, :read_commit_status, generic_commit_status) && generic_commit_status.target_url diff --git a/app/views/projects/pipelines/_info.html.haml b/app/views/projects/pipelines/_info.html.haml index f7385184a2b..d05697b4ee3 100644 --- a/app/views/projects/pipelines/_info.html.haml +++ b/app/views/projects/pipelines/_info.html.haml @@ -1,6 +1,6 @@ .page-content-header .header-main-content - = render "ci/status/icon_with_label", subject: @pipeline + = render "ci/status/icon_with_description", subject: @pipeline %strong Pipeline ##{@commit.pipelines.last.id} triggered #{time_ago_with_tooltip(@commit.authored_date)} by = author_avatar(@commit, size: 24) diff --git a/app/views/projects/stage/_graph.html.haml b/app/views/projects/stage/_graph.html.haml index 1d8fa10db0c..745b6d143f4 100644 --- a/app/views/projects/stage/_graph.html.haml +++ b/app/views/projects/stage/_graph.html.haml @@ -14,9 +14,9 @@ %li.build{ class: ("playable" if is_playable) } .curve .build-content - = render "projects/#{status.to_partial_path}_pipeline", subject: status + = render 'ci/status/icon_with_name_and_action', subject: status - else %li.build .curve .dropdown.inline.build-content - = render "projects/stage/in_stage_group", name: group_name, subject: grouped_statuses + = render 'projects/stage/in_stage_group', name: group_name, subject: grouped_statuses -- cgit v1.2.1 From 23f02681c036b150966ce4459410c94694167b34 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 8 Dec 2016 18:21:11 +0100 Subject: Revert some unneeded changes --- app/views/projects/stage/_graph.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/projects/stage/_graph.html.haml b/app/views/projects/stage/_graph.html.haml index 745b6d143f4..bf8c75b6e5c 100644 --- a/app/views/projects/stage/_graph.html.haml +++ b/app/views/projects/stage/_graph.html.haml @@ -14,7 +14,7 @@ %li.build{ class: ("playable" if is_playable) } .curve .build-content - = render 'ci/status/icon_with_name_and_action', subject: status + = render "projects/#{status.to_partial_path}_pipeline", subject: status - else %li.build .curve -- cgit v1.2.1 From a2a16503a8ecfe1b38f6ef8e31c96b53537dfe02 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Mon, 12 Dec 2016 12:12:37 +0000 Subject: Fix vertical alignment of action icon with status icon --- app/assets/stylesheets/pages/pipelines.scss | 42 +++++++++++++---------------- app/views/projects/stage/_graph.html.haml | 3 +-- 2 files changed, 19 insertions(+), 26 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 304a7932a06..75b127eb7f6 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -654,6 +654,7 @@ i { font-size: 11px; + margin-top: 0; } } @@ -672,33 +673,26 @@ } // Action Icons -.ci-action-icon-container { - padding: 0; +.ci-action-icon-container .ci-action-icon-wrapper { + float: right; + margin-top: -1px; - .ci-action-icon-wrapper { - display: inline-block; - float: right; - - i { - color: $stage-badge-text; - border-radius: 100%; - border: 1px solid $stage-badge-text; - text-align: center; - display: table-cell; - vertical-align: middle; - padding: 5px; - font-size: 13px; - background: $white-light; + i { + color: $stage-badge-text; + border-radius: 100%; + border: 1px solid $stage-badge-text; + padding: 5px 6px; + font-size: 13px; + background: $white-light; - &:hover { - color: $gl-text-color; - background-color: $stage-hover-bg; - border: 1px solid $stage-hover-bg; - } + &:hover { + color: $gl-text-color; + background-color: $stage-hover-bg; + border: 1px solid $stage-hover-bg; } + } - .ci-play-icon { - padding: 5px 4px 5px 7px; - } + .ci-play-icon { + padding: 5px 5px 5px 7px; } } diff --git a/app/views/projects/stage/_graph.html.haml b/app/views/projects/stage/_graph.html.haml index 255091cbfe8..cf3050eea63 100644 --- a/app/views/projects/stage/_graph.html.haml +++ b/app/views/projects/stage/_graph.html.haml @@ -10,8 +10,7 @@ - status_groups.each do |group_name, grouped_statuses| - if grouped_statuses.one? - status = grouped_statuses.first - - is_playable = status.playable? && can?(current_user, :update_build, @project) - %li.build{ class: ("playable" if is_playable) } + %li.build .curve .build-content = render 'ci/status/graph_icon_with_name_and_action', subject: status -- cgit v1.2.1 From 161d7c02d4ff49d6d91b982faee61b5de00d2631 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 7 Dec 2016 19:15:26 +0200 Subject: Modify namespace name and path validation Currently namespace name and path have uniq validaiton which does not allow us to use same group name/path inside different groups. This commit changes validation in next way: * Allow same namespace name with different parent_id * Allow same namespace path. Uniq validation should be handled by routes table Signed-off-by: Dmitriy Zaporozhets --- app/models/namespace.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'app') diff --git a/app/models/namespace.rb b/app/models/namespace.rb index 37374044551..f0479d94986 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -17,14 +17,13 @@ class Namespace < ActiveRecord::Base validates :owner, presence: true, unless: ->(n) { n.type == "Group" } validates :name, presence: true, - uniqueness: true, + uniqueness: { scope: :parent_id }, length: { maximum: 255 }, namespace_name: true validates :description, length: { maximum: 255 } validates :path, presence: true, - uniqueness: { case_sensitive: false }, length: { maximum: 255 }, namespace: true -- cgit v1.2.1 From dc67554c08ac6cfe23809af9f086336ca9ca740e Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Mon, 12 Dec 2016 13:28:02 +0100 Subject: Improve detailed status badge partial --- app/views/admin/runners/show.html.haml | 2 +- app/views/ci/status/_badge.html.haml | 8 ++++++++ app/views/ci/status/_icon_with_description.html.haml | 12 ------------ app/views/projects/builds/_header.html.haml | 2 +- app/views/projects/ci/builds/_build.html.haml | 2 +- app/views/projects/ci/pipelines/_pipeline.html.haml | 2 +- .../generic_commit_statuses/_generic_commit_status.html.haml | 2 +- app/views/projects/pipelines/_info.html.haml | 2 +- 8 files changed, 14 insertions(+), 18 deletions(-) create mode 100644 app/views/ci/status/_badge.html.haml delete mode 100644 app/views/ci/status/_icon_with_description.html.haml (limited to 'app') diff --git a/app/views/admin/runners/show.html.haml b/app/views/admin/runners/show.html.haml index badeb11b208..ca503e35623 100644 --- a/app/views/admin/runners/show.html.haml +++ b/app/views/admin/runners/show.html.haml @@ -91,7 +91,7 @@ %strong ##{build.id} %td.status - = render "ci/status/icon_with_description", subject: build + = render 'ci/status/badge', status: build.detailed_status(current_user) %td.status - if project diff --git a/app/views/ci/status/_badge.html.haml b/app/views/ci/status/_badge.html.haml new file mode 100644 index 00000000000..b1b6e9c2b05 --- /dev/null +++ b/app/views/ci/status/_badge.html.haml @@ -0,0 +1,8 @@ +- if status.has_details? + = link_to status.details_path, class: "ci-status ci-#{status}" do + = custom_icon(status.icon) + = status.text +- else + %span{ class: "ci-status ci-#{status}" } + = custom_icon(status.icon) + = detailed_status.text diff --git a/app/views/ci/status/_icon_with_description.html.haml b/app/views/ci/status/_icon_with_description.html.haml deleted file mode 100644 index 34c923440d0..00000000000 --- a/app/views/ci/status/_icon_with_description.html.haml +++ /dev/null @@ -1,12 +0,0 @@ -- detailed_status = subject.detailed_status(current_user) -- details_path = detailed_status.details_path if detailed_status.has_details? -- klass = "ci-status ci-#{detailed_status}" - -- if details_path - = link_to details_path, class: klass do - = custom_icon(detailed_status.icon) - = detailed_status.text -- else - %span{ class: klass } - = custom_icon(detailed_status.icon) - = detailed_status.text diff --git a/app/views/projects/builds/_header.html.haml b/app/views/projects/builds/_header.html.haml index 85d1793ecb9..057a720a54a 100644 --- a/app/views/projects/builds/_header.html.haml +++ b/app/views/projects/builds/_header.html.haml @@ -1,6 +1,6 @@ .content-block.build-header .header-content - = render "ci/status/icon_with_description", subject: build + = render 'ci/status/badge', status: @build.detailed_status(current_user) Build %strong ##{@build.id} in pipeline diff --git a/app/views/projects/ci/builds/_build.html.haml b/app/views/projects/ci/builds/_build.html.haml index 4257bb86859..f1cb0201032 100644 --- a/app/views/projects/ci/builds/_build.html.haml +++ b/app/views/projects/ci/builds/_build.html.haml @@ -9,7 +9,7 @@ %tr.build.commit{class: ('retried' if retried)} %td.status - = render "ci/status/icon_with_description", subject: build + = render "ci/status/badge", status: build.detailed_status(current_user) %td.branch-commit - if can?(current_user, :read_build, build) diff --git a/app/views/projects/ci/pipelines/_pipeline.html.haml b/app/views/projects/ci/pipelines/_pipeline.html.haml index 6dff955ea3d..3f05a21990f 100644 --- a/app/views/projects/ci/pipelines/_pipeline.html.haml +++ b/app/views/projects/ci/pipelines/_pipeline.html.haml @@ -4,7 +4,7 @@ %tr.commit %td.commit-link - = render "ci/status/icon_with_description", subject: pipeline + = render 'ci/status/badge', status: pipeline.detailed_status(current_user) %td = link_to namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id) do diff --git a/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml b/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml index 1dd07ae1a2a..9f444f076c0 100644 --- a/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml +++ b/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml @@ -8,7 +8,7 @@ %tr.generic_commit_status{class: ('retried' if retried)} %td.status - = render "ci/status/icon_with_description", subject: generic_commit_status + = render 'ci/status/badge', status: generic_commit_status.detailed_status(current_user) %td.generic_commit_status-link - if can?(current_user, :read_commit_status, generic_commit_status) && generic_commit_status.target_url diff --git a/app/views/projects/pipelines/_info.html.haml b/app/views/projects/pipelines/_info.html.haml index d05697b4ee3..b00ba2d5307 100644 --- a/app/views/projects/pipelines/_info.html.haml +++ b/app/views/projects/pipelines/_info.html.haml @@ -1,6 +1,6 @@ .page-content-header .header-main-content - = render "ci/status/icon_with_description", subject: @pipeline + = render 'ci/status/badge', status: @pipeline.detailed_status(current_user) %strong Pipeline ##{@commit.pipelines.last.id} triggered #{time_ago_with_tooltip(@commit.authored_date)} by = author_avatar(@commit, size: 24) -- cgit v1.2.1 From be13fc68e74cd6820a5b175365f72f12de339e57 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Mon, 12 Dec 2016 15:17:18 +0100 Subject: Fix detailed status badge for generic commit status [ci skip] --- app/views/ci/status/_badge.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/ci/status/_badge.html.haml b/app/views/ci/status/_badge.html.haml index b1b6e9c2b05..c00ddd183fb 100644 --- a/app/views/ci/status/_badge.html.haml +++ b/app/views/ci/status/_badge.html.haml @@ -5,4 +5,4 @@ - else %span{ class: "ci-status ci-#{status}" } = custom_icon(status.icon) - = detailed_status.text + = status.text -- cgit v1.2.1 From ce867db6b8b1b317ebe864d36d50fde5aad787d4 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Mon, 12 Dec 2016 16:00:50 +0000 Subject: Adds CSS to match the mockups and makes table responsive --- app/assets/stylesheets/pages/admin.scss | 14 +++++++ app/views/admin/deploy_keys/index.html.haml | 63 +++++++++++++++-------------- 2 files changed, 46 insertions(+), 31 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/admin.scss b/app/assets/stylesheets/pages/admin.scss index 44eac21b143..23b69e4d16f 100644 --- a/app/assets/stylesheets/pages/admin.scss +++ b/app/assets/stylesheets/pages/admin.scss @@ -166,3 +166,17 @@ min-width: 120px; } } + +.deploy-keys-list { + width: 100%; + overflow: auto; + + table { + border: 1px solid $table-border-color; + } +} + +.deploy-keys-title { + padding-bottom: 2px; + line-height: 2; +} diff --git a/app/views/admin/deploy_keys/index.html.haml b/app/views/admin/deploy_keys/index.html.haml index 646c9815cfe..7b71bb5b287 100644 --- a/app/views/admin/deploy_keys/index.html.haml +++ b/app/views/admin/deploy_keys/index.html.haml @@ -1,33 +1,34 @@ - page_title "Deploy Keys" -.panel.panel-default.prepend-top-default - .panel-heading - Public deploy keys (#{@deploy_keys.count}) - .controls - = link_to 'New Deploy Key', new_admin_deploy_key_path, class: "btn btn-new btn-sm btn-inverted" - - if @deploy_keys.any? - .table-holder - %table.table - %thead.panel-heading + +%h3.page-title.deploy-keys-title + Public deploy keys (#{@deploy_keys.count}) + .pull-right + = link_to 'New Deploy Key', new_admin_deploy_key_path, class: 'btn btn-new btn-sm btn-inverted' + +- if @deploy_keys.any? + .table-holder.deploy-keys-list + %table.table + %thead + %tr + %th.col-sm-2 Title + %th.col-sm-4 Fingerprint + %th.col-sm-2 Write access allowed + %th.col-sm-2 Added at + %th.col-sm-2 + %tbody + - @deploy_keys.each do |deploy_key| %tr - %th Title - %th Fingerprint - %th Write access allowed - %th Added at - %th - %tbody - - @deploy_keys.each do |deploy_key| - %tr - %td - %strong= deploy_key.title - %td - %code.key-fingerprint= deploy_key.fingerprint - %td - - if deploy_key.can_push? - Yes - - else - No - %td - %span.cgray - added #{time_ago_with_tooltip(deploy_key.created_at)} - %td - = link_to 'Remove', admin_deploy_key_path(deploy_key), data: { confirm: 'Are you sure?'}, method: :delete, class: "btn btn-sm btn-remove delete-key pull-right" + %td + %strong= deploy_key.title + %td + %code.key-fingerprint= deploy_key.fingerprint + %td + - if deploy_key.can_push? + Yes + - else + No + %td + %span.cgray + added #{time_ago_with_tooltip(deploy_key.created_at)} + %td + = link_to 'Remove', admin_deploy_key_path(deploy_key), data: { confirm: 'Are you sure?'}, method: :delete, class: 'btn btn-sm btn-remove delete-key pull-right' -- cgit v1.2.1 From 07c6c8e0a1438f745f9f420b24a66a05a76c4272 Mon Sep 17 00:00:00 2001 From: Regis Date: Mon, 12 Dec 2016 11:59:22 -0700 Subject: stages render correctly and use new status object --- app/assets/javascripts/vue_pipelines_index/stage.js.es6 | 9 +++------ app/assets/stylesheets/pages/icons.scss | 8 ++++++++ 2 files changed, 11 insertions(+), 6 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 index b313317b0bb..3761977d5db 100644 --- a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 @@ -6,16 +6,13 @@ props: ['stage'], computed: { buildStatus() { - return `Build: ${this.stage.status}`; + return `Build: ${this.stage.status.label}`; }, tooltip() { - return `has-tooltip ci-status-icon-${this.stage.status}`; + return `has-tooltip ci-status-icon-${this.stage.status.label}`; }, svg() { - return document - .querySelector( - `.icon_status_${this.stage.status}`, - ).innerHTML; + return document.querySelector(`.${this.stage.status.icon}`).innerHTML; }, }, template: ` diff --git a/app/assets/stylesheets/pages/icons.scss b/app/assets/stylesheets/pages/icons.scss index 226bd2ead31..8210208cbf6 100644 --- a/app/assets/stylesheets/pages/icons.scss +++ b/app/assets/stylesheets/pages/icons.scss @@ -6,6 +6,14 @@ } } +.ci-status-icon-passed { + color: $gl-success; + + svg { + fill: $gl-success; + } +} + .ci-status-icon-failed { color: $gl-danger; -- cgit v1.2.1 From 562df3a3fb6d41c83180b3b3c519920c9e156de5 Mon Sep 17 00:00:00 2001 From: Regis Date: Mon, 12 Dec 2016 12:11:28 -0700 Subject: pass svg as prop to commit component --- app/assets/javascripts/vue_pipelines_index/index.js.es6 | 3 +++ app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 | 9 +++++---- app/views/projects/pipelines/index.html.haml | 4 ++-- 3 files changed, 10 insertions(+), 6 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/index.js.es6 b/app/assets/javascripts/vue_pipelines_index/index.js.es6 index 25f5c796a60..ced3e8f2602 100644 --- a/app/assets/javascripts/vue_pipelines_index/index.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/index.js.es6 @@ -19,6 +19,7 @@ (() => { const project = document.querySelector('.pipelines'); const entry = document.querySelector('.vue-pipelines-index'); + const svgs = document.querySelector('.pipeline-svgs'); Vue.use(VueResource); @@ -28,6 +29,7 @@ data: { scope: project.dataset.url, store: new gl.PipelineStore(), + svgs: svgs.dataset, }, components: { 'vue-pipelines': gl.VuePipelines, @@ -37,6 +39,7 @@
    diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index 2fdcaf3e16c..37fe6c29c5a 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -26,7 +26,7 @@ pageRequest: false, }; }, - props: ['scope', 'store'], + props: ['scope', 'store', 'svgs'], created() { const pagenum = gl.getParameterByName('p'); const scope = gl.getParameterByName('scope'); @@ -81,12 +81,13 @@ diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index fd1baa6195b..565dfa36e8e 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -40,8 +40,8 @@ %div .nothing-here-block No pipelines to show - else - .commit-icon-svg.hidden - = custom_icon("icon_commit") + .pipeline-svgs{"data" => {"commit-icon-svg" => custom_icon("icon_commit")} } + .icon_status_canceled.hidden = custom_icon("icon_status_canceled") .icon_status_running.hidden -- cgit v1.2.1 From 1de2edc1f14a805afa23c6fde79bdd499af75f33 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Mon, 12 Dec 2016 21:09:17 +0000 Subject: Fix pipeline stroke position --- app/assets/stylesheets/pages/pipelines.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 75b127eb7f6..4a5b0b5922c 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -427,7 +427,7 @@ width: 21px; height: 25px; position: absolute; - top: -31px; + top: -30px; border-top: 2px solid $border-color; } -- cgit v1.2.1 From 605715067767572ff96964370d78e7b31083ddde Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Mon, 28 Nov 2016 11:34:02 +0000 Subject: Adds manual action icon and case to show it --- app/helpers/ci_status_helper.rb | 2 ++ app/views/shared/icons/_icon_status_manual.svg | 1 + 2 files changed, 3 insertions(+) create mode 100755 app/views/shared/icons/_icon_status_manual.svg (limited to 'app') diff --git a/app/helpers/ci_status_helper.rb b/app/helpers/ci_status_helper.rb index d9f5e01f0dc..eb2aeaa4628 100644 --- a/app/helpers/ci_status_helper.rb +++ b/app/helpers/ci_status_helper.rb @@ -48,6 +48,8 @@ module CiStatusHelper 'icon_status_created' when 'skipped' 'icon_status_skipped' + when 'manual' + 'icon_status_manual' else 'icon_status_canceled' end diff --git a/app/views/shared/icons/_icon_status_manual.svg b/app/views/shared/icons/_icon_status_manual.svg new file mode 100755 index 00000000000..ffb00c6f443 --- /dev/null +++ b/app/views/shared/icons/_icon_status_manual.svg @@ -0,0 +1 @@ + -- cgit v1.2.1 From 2011f8f1c2b4788df04fd76dcab816ab337e9e08 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 13 Dec 2016 11:53:36 +0100 Subject: Use manual build icon in play/stop build statuses --- app/helpers/ci_status_helper.rb | 2 -- 1 file changed, 2 deletions(-) (limited to 'app') diff --git a/app/helpers/ci_status_helper.rb b/app/helpers/ci_status_helper.rb index eb2aeaa4628..d9f5e01f0dc 100644 --- a/app/helpers/ci_status_helper.rb +++ b/app/helpers/ci_status_helper.rb @@ -48,8 +48,6 @@ module CiStatusHelper 'icon_status_created' when 'skipped' 'icon_status_skipped' - when 'manual' - 'icon_status_manual' else 'icon_status_canceled' end -- cgit v1.2.1 From 0b9df1bd93f9b6b6a5714431d8b815b0225917b5 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Tue, 13 Dec 2016 11:30:12 +0000 Subject: Replace old icons with new ones --- app/views/shared/icons/_icon_status_canceled.svg | 2 +- app/views/shared/icons/_icon_status_canceled_graph.svg | 1 - app/views/shared/icons/_icon_status_created.svg | 2 +- app/views/shared/icons/_icon_status_created_graph.svg | 1 - app/views/shared/icons/_icon_status_failed.svg | 2 +- app/views/shared/icons/_icon_status_failed_graph.svg | 1 - app/views/shared/icons/_icon_status_manual.svg | 1 + app/views/shared/icons/_icon_status_manual_graph.svg | 1 - app/views/shared/icons/_icon_status_pending.svg | 2 +- app/views/shared/icons/_icon_status_pending_graph.svg | 1 - app/views/shared/icons/_icon_status_running.svg | 2 +- app/views/shared/icons/_icon_status_running_graph.svg | 1 - app/views/shared/icons/_icon_status_skipped.svg | 2 +- app/views/shared/icons/_icon_status_skipped_graph.svg | 1 - app/views/shared/icons/_icon_status_success.svg | 2 +- app/views/shared/icons/_icon_status_success_graph.svg | 1 - app/views/shared/icons/_icon_status_warning.svg | 2 +- app/views/shared/icons/_icon_status_warning_graph.svg | 1 - 18 files changed, 9 insertions(+), 17 deletions(-) mode change 100644 => 100755 app/views/shared/icons/_icon_status_canceled.svg delete mode 100755 app/views/shared/icons/_icon_status_canceled_graph.svg mode change 100644 => 100755 app/views/shared/icons/_icon_status_created.svg delete mode 100755 app/views/shared/icons/_icon_status_created_graph.svg mode change 100644 => 100755 app/views/shared/icons/_icon_status_failed.svg delete mode 100755 app/views/shared/icons/_icon_status_failed_graph.svg create mode 100755 app/views/shared/icons/_icon_status_manual.svg delete mode 100755 app/views/shared/icons/_icon_status_manual_graph.svg mode change 100644 => 100755 app/views/shared/icons/_icon_status_pending.svg delete mode 100755 app/views/shared/icons/_icon_status_pending_graph.svg mode change 100644 => 100755 app/views/shared/icons/_icon_status_running.svg delete mode 100755 app/views/shared/icons/_icon_status_running_graph.svg mode change 100644 => 100755 app/views/shared/icons/_icon_status_skipped.svg delete mode 100755 app/views/shared/icons/_icon_status_skipped_graph.svg mode change 100644 => 100755 app/views/shared/icons/_icon_status_success.svg delete mode 100755 app/views/shared/icons/_icon_status_success_graph.svg mode change 100644 => 100755 app/views/shared/icons/_icon_status_warning.svg delete mode 100755 app/views/shared/icons/_icon_status_warning_graph.svg (limited to 'app') diff --git a/app/views/shared/icons/_icon_status_canceled.svg b/app/views/shared/icons/_icon_status_canceled.svg old mode 100644 new mode 100755 index 41a210a8ed9..bd5d04e1cd7 --- a/app/views/shared/icons/_icon_status_canceled.svg +++ b/app/views/shared/icons/_icon_status_canceled.svg @@ -1 +1 @@ - + diff --git a/app/views/shared/icons/_icon_status_canceled_graph.svg b/app/views/shared/icons/_icon_status_canceled_graph.svg deleted file mode 100755 index bd5d04e1cd7..00000000000 --- a/app/views/shared/icons/_icon_status_canceled_graph.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/app/views/shared/icons/_icon_status_created.svg b/app/views/shared/icons/_icon_status_created.svg old mode 100644 new mode 100755 index 1f5c3b51b03..326ad04e017 --- a/app/views/shared/icons/_icon_status_created.svg +++ b/app/views/shared/icons/_icon_status_created.svg @@ -1 +1 @@ - + diff --git a/app/views/shared/icons/_icon_status_created_graph.svg b/app/views/shared/icons/_icon_status_created_graph.svg deleted file mode 100755 index 326ad04e017..00000000000 --- a/app/views/shared/icons/_icon_status_created_graph.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/app/views/shared/icons/_icon_status_failed.svg b/app/views/shared/icons/_icon_status_failed.svg old mode 100644 new mode 100755 index af267b8938a..64da5aa31fc --- a/app/views/shared/icons/_icon_status_failed.svg +++ b/app/views/shared/icons/_icon_status_failed.svg @@ -1 +1 @@ - + diff --git a/app/views/shared/icons/_icon_status_failed_graph.svg b/app/views/shared/icons/_icon_status_failed_graph.svg deleted file mode 100755 index 64da5aa31fc..00000000000 --- a/app/views/shared/icons/_icon_status_failed_graph.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/app/views/shared/icons/_icon_status_manual.svg b/app/views/shared/icons/_icon_status_manual.svg new file mode 100755 index 00000000000..c98839f51a9 --- /dev/null +++ b/app/views/shared/icons/_icon_status_manual.svg @@ -0,0 +1 @@ + diff --git a/app/views/shared/icons/_icon_status_manual_graph.svg b/app/views/shared/icons/_icon_status_manual_graph.svg deleted file mode 100755 index c98839f51a9..00000000000 --- a/app/views/shared/icons/_icon_status_manual_graph.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/app/views/shared/icons/_icon_status_pending.svg b/app/views/shared/icons/_icon_status_pending.svg old mode 100644 new mode 100755 index 516231d1b44..02d5da407e3 --- a/app/views/shared/icons/_icon_status_pending.svg +++ b/app/views/shared/icons/_icon_status_pending.svg @@ -1 +1 @@ - + diff --git a/app/views/shared/icons/_icon_status_pending_graph.svg b/app/views/shared/icons/_icon_status_pending_graph.svg deleted file mode 100755 index 02d5da407e3..00000000000 --- a/app/views/shared/icons/_icon_status_pending_graph.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/app/views/shared/icons/_icon_status_running.svg b/app/views/shared/icons/_icon_status_running.svg old mode 100644 new mode 100755 index d2618bce200..532f4fee33c --- a/app/views/shared/icons/_icon_status_running.svg +++ b/app/views/shared/icons/_icon_status_running.svg @@ -1 +1 @@ - + diff --git a/app/views/shared/icons/_icon_status_running_graph.svg b/app/views/shared/icons/_icon_status_running_graph.svg deleted file mode 100755 index 532f4fee33c..00000000000 --- a/app/views/shared/icons/_icon_status_running_graph.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/app/views/shared/icons/_icon_status_skipped.svg b/app/views/shared/icons/_icon_status_skipped.svg old mode 100644 new mode 100755 index 701f33bcbea..1998dfef9ea --- a/app/views/shared/icons/_icon_status_skipped.svg +++ b/app/views/shared/icons/_icon_status_skipped.svg @@ -1 +1 @@ - + diff --git a/app/views/shared/icons/_icon_status_skipped_graph.svg b/app/views/shared/icons/_icon_status_skipped_graph.svg deleted file mode 100755 index 1998dfef9ea..00000000000 --- a/app/views/shared/icons/_icon_status_skipped_graph.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/app/views/shared/icons/_icon_status_success.svg b/app/views/shared/icons/_icon_status_success.svg old mode 100644 new mode 100755 index b7c21ba6971..eed5006bebe --- a/app/views/shared/icons/_icon_status_success.svg +++ b/app/views/shared/icons/_icon_status_success.svg @@ -1 +1 @@ - + diff --git a/app/views/shared/icons/_icon_status_success_graph.svg b/app/views/shared/icons/_icon_status_success_graph.svg deleted file mode 100755 index eed5006bebe..00000000000 --- a/app/views/shared/icons/_icon_status_success_graph.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/app/views/shared/icons/_icon_status_warning.svg b/app/views/shared/icons/_icon_status_warning.svg old mode 100644 new mode 100755 index 9191e0050a6..cb785635b7e --- a/app/views/shared/icons/_icon_status_warning.svg +++ b/app/views/shared/icons/_icon_status_warning.svg @@ -1 +1 @@ - + diff --git a/app/views/shared/icons/_icon_status_warning_graph.svg b/app/views/shared/icons/_icon_status_warning_graph.svg deleted file mode 100755 index cb785635b7e..00000000000 --- a/app/views/shared/icons/_icon_status_warning_graph.svg +++ /dev/null @@ -1 +0,0 @@ - -- cgit v1.2.1 From a06016d00cd363eec7ef748e5fda6459c911eaba Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Tue, 13 Dec 2016 11:38:34 +0000 Subject: Remove unneeded partial --- app/views/ci/status/_graph_icon_with_name.html.haml | 12 ------------ .../ci/status/_graph_icon_with_name_and_action.html.haml | 8 -------- app/views/projects/stage/_graph.html.haml | 2 +- app/views/projects/stage/_in_stage_group.html.haml | 2 +- 4 files changed, 2 insertions(+), 22 deletions(-) delete mode 100644 app/views/ci/status/_graph_icon_with_name.html.haml delete mode 100644 app/views/ci/status/_graph_icon_with_name_and_action.html.haml (limited to 'app') diff --git a/app/views/ci/status/_graph_icon_with_name.html.haml b/app/views/ci/status/_graph_icon_with_name.html.haml deleted file mode 100644 index 51037a3bd20..00000000000 --- a/app/views/ci/status/_graph_icon_with_name.html.haml +++ /dev/null @@ -1,12 +0,0 @@ -- detailed_status = subject.detailed_status(current_user) -- details_path = detailed_status.details_path if detailed_status.has_details? -- klass = "ci-status-icon ci-status-icon-#{detailed_status}" -- graph_status_icon = "#{detailed_status.icon}_graph" - -- if details_path - = link_to details_path, class: klass, data: { toggle: 'tooltip', title: "#{subject.name} - #{detailed_status}" } do - %span{ class: klass }= custom_icon(graph_status_icon) - .ci-status-text= subject.name -- else - %span{ class: klass }= custom_icon(graph_status_icon) - .ci-status-text= subject.name diff --git a/app/views/ci/status/_graph_icon_with_name_and_action.html.haml b/app/views/ci/status/_graph_icon_with_name_and_action.html.haml deleted file mode 100644 index 525075ced70..00000000000 --- a/app/views/ci/status/_graph_icon_with_name_and_action.html.haml +++ /dev/null @@ -1,8 +0,0 @@ -= render "ci/status/graph_icon_with_name", subject: subject - -- detailed_status = subject.detailed_status(current_user) -- if detailed_status.has_action? - = link_to detailed_status.action_path, method: detailed_status.action_method, - title: "#{subject.name}: #{detailed_status.action_title}", class: 'ci-action-icon-container' do - %i.ci-action-icon-wrapper - = icon(detailed_status.action_icon, class: detailed_status.action_class) diff --git a/app/views/projects/stage/_graph.html.haml b/app/views/projects/stage/_graph.html.haml index cf3050eea63..6d280468262 100644 --- a/app/views/projects/stage/_graph.html.haml +++ b/app/views/projects/stage/_graph.html.haml @@ -13,7 +13,7 @@ %li.build .curve .build-content - = render 'ci/status/graph_icon_with_name_and_action', subject: status + = render 'ci/status/icon_with_name_and_action', subject: status - else %li.build .curve diff --git a/app/views/projects/stage/_in_stage_group.html.haml b/app/views/projects/stage/_in_stage_group.html.haml index 70101ccf806..5c9b6549b37 100644 --- a/app/views/projects/stage/_in_stage_group.html.haml +++ b/app/views/projects/stage/_in_stage_group.html.haml @@ -10,4 +10,4 @@ %ul - subject.each do |status| %li.dropdown-build - = render 'ci/status/graph_icon_with_name_and_action', subject: status + = render 'ci/status/icon_with_name_and_action', subject: status -- cgit v1.2.1 From 92b0f54ea222ce4c4437a50683c972bacc1fee06 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Tue, 13 Dec 2016 11:39:13 +0000 Subject: Fix graph stroke position --- app/assets/stylesheets/pages/pipelines.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 4a5b0b5922c..15da30dda2b 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -427,7 +427,7 @@ width: 21px; height: 25px; position: absolute; - top: -30px; + top: -32px; border-top: 2px solid $border-color; } -- cgit v1.2.1 From 07d69d8a6763984536a590690bb58527f6175bc1 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 13 Dec 2016 19:58:26 +0800 Subject: Fix Slack pipeline message by API Pipelines triggered from API don't have a corresponding user, so we show that it's from API, same as from the web UI Closes #25609 --- app/models/project_services/slack_service/pipeline_message.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/models/project_services/slack_service/pipeline_message.rb b/app/models/project_services/slack_service/pipeline_message.rb index f8d03c0e2fa..b6355fc4171 100644 --- a/app/models/project_services/slack_service/pipeline_message.rb +++ b/app/models/project_services/slack_service/pipeline_message.rb @@ -13,7 +13,7 @@ class SlackService @project_name = data[:project][:path_with_namespace] @project_url = data[:project][:web_url] - @user_name = data[:user] && data[:user][:name] + @user_name = (data[:user] && data[:user][:name]) || 'API' end def pretext -- cgit v1.2.1 From 5f590a71fd26b637501f8751bc6f9adff4d9c8db Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 13 Dec 2016 13:24:25 +0100 Subject: Improve readability in methods for detailed status --- app/models/ci/build.rb | 4 +++- app/models/ci/pipeline.rb | 4 +++- app/models/ci/stage.rb | 4 +++- app/models/commit_status.rb | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 65ee327a8e5..63a4a075f8e 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -101,7 +101,9 @@ module Ci end def detailed_status(current_user) - Gitlab::Ci::Status::Build::Factory.new(self, current_user).fabricate! + Gitlab::Ci::Status::Build::Factory + .new(self, current_user) + .fabricate! end def manual? diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 1f33106d358..54f73171fd4 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -337,7 +337,9 @@ module Ci end def detailed_status(current_user) - Gitlab::Ci::Status::Pipeline::Factory.new(self, current_user).fabricate! + Gitlab::Ci::Status::Pipeline::Factory + .new(self, current_user) + .fabricate! end private diff --git a/app/models/ci/stage.rb b/app/models/ci/stage.rb index be52cce20f1..7ef59445d77 100644 --- a/app/models/ci/stage.rb +++ b/app/models/ci/stage.rb @@ -23,7 +23,9 @@ module Ci end def detailed_status(current_user) - Gitlab::Ci::Status::Stage::Factory.new(self, current_user).fabricate! + Gitlab::Ci::Status::Stage::Factory + .new(self, current_user) + .fabricate! end def statuses diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index 6548a7dda2c..31cd381dcd2 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -133,6 +133,8 @@ class CommitStatus < ActiveRecord::Base end def detailed_status(current_user) - Gitlab::Ci::Status::Factory.new(self, current_user).fabricate! + Gitlab::Ci::Status::Factory + .new(self, current_user) + .fabricate! end end -- cgit v1.2.1 From a9ec4ec07e64d5f823c30d9bcc4c4bb1be7f2d75 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 13 Dec 2016 13:57:18 +0100 Subject: Make build retryable only if complete and executed --- app/models/ci/build.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 63a4a075f8e..89b0cae25ed 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -134,7 +134,8 @@ module Ci end def retryable? - project.builds_enabled? && commands.present? && complete? + project.builds_enabled? && commands.present? && + (success? || failed?) end def retried? -- cgit v1.2.1 From f4513d5c1981922e71a00b9e4b135605eb674c6f Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 13 Dec 2016 14:01:17 +0100 Subject: Make it possible to retry build that was canceled --- app/models/ci/build.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 89b0cae25ed..e7cf606a7ae 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -135,7 +135,7 @@ module Ci def retryable? project.builds_enabled? && commands.present? && - (success? || failed?) + (success? || failed? || canceled?) end def retried? -- cgit v1.2.1 From 00970606d78486a8b6672659e9ea28521a102e44 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 13 Dec 2016 14:44:43 +0100 Subject: Extract abilities checking module from ability model --- app/models/ability.rb | 6 ------ 1 file changed, 6 deletions(-) (limited to 'app') diff --git a/app/models/ability.rb b/app/models/ability.rb index ce461caf686..fa8f8bc3a5f 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -1,10 +1,4 @@ class Ability - module Allowable - def can?(user, action, subject) - Ability.allowed?(user, action, subject) - end - end - class << self # Given a list of users and a project this method returns the users that can # read the given project. -- cgit v1.2.1 From f62e6081fd114641e41ffa1614d16c30a742cbaa Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 13 Dec 2016 14:58:56 +0100 Subject: Update manual build icon SVG --- app/views/shared/icons/_icon_status_manual.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/shared/icons/_icon_status_manual.svg b/app/views/shared/icons/_icon_status_manual.svg index ffb00c6f443..c98839f51a9 100755 --- a/app/views/shared/icons/_icon_status_manual.svg +++ b/app/views/shared/icons/_icon_status_manual.svg @@ -1 +1 @@ - + -- cgit v1.2.1 From 6328f26c41114c4bc6606097a718022fac2bb168 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 8 Dec 2016 18:28:49 +0200 Subject: Show full path in header UI for nested groups/projects Signed-off-by: Dmitriy Zaporozhets --- app/helpers/groups_helper.rb | 11 +++++++++-- app/helpers/projects_helper.rb | 4 ++-- 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb index f6d4ea4659a..77dc9e7d538 100644 --- a/app/helpers/groups_helper.rb +++ b/app/helpers/groups_helper.rb @@ -12,11 +12,18 @@ module GroupsHelper end def group_title(group, name = nil, url = nil) - full_title = link_to(simple_sanitize(group.name), group_path(group)) + full_title = '' + + group.parents.each do |parent| + full_title += link_to(simple_sanitize(parent.name), group_path(parent)) + full_title += ' / '.html_safe + end + + full_title += link_to(simple_sanitize(group.name), group_path(group)) full_title += ' · '.html_safe + link_to(simple_sanitize(name), url) if name content_tag :span do - full_title + full_title.html_safe end end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 9cda3b78761..d2177f683a1 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -52,7 +52,7 @@ module ProjectsHelper def project_title(project) namespace_link = if project.group - link_to(simple_sanitize(project.group.name), group_path(project.group)) + group_title(project.group) else owner = project.namespace.owner link_to(simple_sanitize(owner.name), user_path(owner)) @@ -390,7 +390,7 @@ module ProjectsHelper "success" end end - + def readme_cache_key sha = @project.commit.try(:sha) || 'nil' [@project.path_with_namespace, sha, "readme"].join('-') -- cgit v1.2.1 From 8128ce3054749401acfee2c91d38e0e731253624 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 8 Dec 2016 18:30:11 +0200 Subject: Show full path for nested groups at dashboard groups list Signed-off-by: Dmitriy Zaporozhets --- app/models/namespace.rb | 8 ++++++++ app/views/shared/groups/_group.html.haml | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/models/namespace.rb b/app/models/namespace.rb index 37374044551..464be910f5a 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -162,6 +162,14 @@ class Namespace < ActiveRecord::Base end end + def full_name + if parent + parent.full_name + ' / ' + name + else + name + end + end + private def repository_storage_paths diff --git a/app/views/shared/groups/_group.html.haml b/app/views/shared/groups/_group.html.haml index 19221e3391f..8164f61797c 100644 --- a/app/views/shared/groups/_group.html.haml +++ b/app/views/shared/groups/_group.html.haml @@ -28,7 +28,7 @@ = image_tag group_icon(group), class: "avatar s40 hidden-xs" .title = link_to group, class: 'group-name' do - = group.name + = group.full_name - if group_member as -- cgit v1.2.1 From 5c06875c39c8b525db41e73560f8cb1746119dd9 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 8 Dec 2016 21:11:20 +0200 Subject: Use full group name for admin group index and show pages Signed-off-by: Dmitriy Zaporozhets --- app/views/admin/groups/_group.html.haml | 2 +- app/views/admin/groups/show.html.haml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/views/admin/groups/_group.html.haml b/app/views/admin/groups/_group.html.haml index 664bb417c6a..eb4de01fb18 100644 --- a/app/views/admin/groups/_group.html.haml +++ b/app/views/admin/groups/_group.html.haml @@ -20,7 +20,7 @@ = image_tag group_icon(group), class: "avatar s40 hidden-xs" .title = link_to [:admin, group], class: 'group-name' do - = group.name + = group.full_name - if group.description.present? .description diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml index 40871e32913..969b59ef232 100644 --- a/app/views/admin/groups/show.html.haml +++ b/app/views/admin/groups/show.html.haml @@ -1,6 +1,6 @@ - page_title @group.name, "Groups" %h3.page-title - Group: #{@group.name} + Group: #{@group.full_name} = link_to edit_admin_group_path(@group), class: "btn pull-right" do %i.fa.fa-pencil-square-o -- cgit v1.2.1 From d806230f9f95a2d08253f6c534ba69d1b9a498ea Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 13 Dec 2016 16:59:49 +0200 Subject: Add parents method to Namespace Signed-off-by: Dmitriy Zaporozhets --- app/models/namespace.rb | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/models/namespace.rb b/app/models/namespace.rb index 464be910f5a..b3cefc01b99 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -163,11 +163,26 @@ class Namespace < ActiveRecord::Base end def full_name - if parent - parent.full_name + ' / ' + name - else - name - end + @full_name ||= + if parent + parent.full_name + ' / ' + name + else + name + end + end + + def parents + @parents ||= + begin + parents = [] + + if parent + parents << parent + parents += parent.parents + end + + parents + end end private -- cgit v1.2.1 From 78115dc13af2b72d87ddbe2c5e42b24d75cd1b17 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 13 Dec 2016 17:00:06 +0200 Subject: Use full_name for Group in UI Signed-off-by: Dmitriy Zaporozhets --- app/models/group.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/models/group.rb b/app/models/group.rb index 4248e1162d8..ac8a82c8c1e 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -83,7 +83,7 @@ class Group < Namespace end def human_name - name + full_name end def visibility_level_field -- cgit v1.2.1 From 13798c003eb7c2f2f6ccc1ec5a8728b1ed1a130e Mon Sep 17 00:00:00 2001 From: Regis Date: Tue, 13 Dec 2016 09:54:18 -0700 Subject: dynamic API consumption for SVGs --- .../vue_pipelines_index/pipelines.js.es6 | 17 ++++++++++++-- .../javascripts/vue_pipelines_index/stage.js.es6 | 4 ++-- .../javascripts/vue_pipelines_index/stages.js.es6 | 4 ++-- app/views/projects/pipelines/index.html.haml | 27 ++++++++-------------- 4 files changed, 29 insertions(+), 23 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index 37fe6c29c5a..a2b12554494 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -66,6 +66,9 @@ if (pipeline.commit) return pipeline.commit.commit_url; return ''; }, + match(string) { + return string.replace(/_([a-z])/g, (m, w) => w.toUpperCase()); + }, }, template: `
    @@ -77,7 +80,12 @@ - + + - + + diff --git a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 index 3761977d5db..7821ed62bd5 100644 --- a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 @@ -3,7 +3,7 @@ ((gl) => { gl.VueStage = Vue.extend({ - props: ['stage'], + props: ['stage', 'svgs', 'match'], computed: { buildStatus() { return `Build: ${this.stage.status.label}`; @@ -12,7 +12,7 @@ return `has-tooltip ci-status-icon-${this.stage.status.label}`; }, svg() { - return document.querySelector(`.${this.stage.status.icon}`).innerHTML; + return this.svgs[this.match(this.stage.status.icon)]; }, }, template: ` diff --git a/app/assets/javascripts/vue_pipelines_index/stages.js.es6 b/app/assets/javascripts/vue_pipelines_index/stages.js.es6 index f91c44174de..d7dda9294cd 100644 --- a/app/assets/javascripts/vue_pipelines_index/stages.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/stages.js.es6 @@ -6,14 +6,14 @@ components: { 'vue-stage': gl.VueStage, }, - props: ['pipeline'], + props: ['pipeline', 'svgs', 'match'], template: `
    - +
    `, diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index 565dfa36e8e..0822480ae14 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -40,24 +40,17 @@ %div .nothing-here-block No pipelines to show - else - .pipeline-svgs{"data" => {"commit-icon-svg" => custom_icon("icon_commit")} } + .pipeline-svgs{"data" => {"commit_icon_svg" => custom_icon("icon_commit"), + "icon_status_canceled" => custom_icon("icon_status_canceled"), + "icon_status_running" => custom_icon("icon_status_running"), + "icon_status_skipped" => custom_icon("icon_status_skipped"), + "icon_status_created" => custom_icon("icon_status_created"), + "icon_status_pending" => custom_icon("icon_status_pending"), + "icon_status_success" => custom_icon("icon_status_success"), + "icon_status_failed" => custom_icon("icon_status_failed"), + "icon_status_warning" => custom_icon("icon_status_warning"), + } } - .icon_status_canceled.hidden - = custom_icon("icon_status_canceled") - .icon_status_running.hidden - = custom_icon("icon_status_running") - .icon_status_skipped.hidden - = custom_icon("icon_status_skipped") - .icon_status_created.hidden - = custom_icon("icon_status_created") - .icon_status_pending.hidden - = custom_icon("icon_status_pending") - .icon_status_success.hidden - = custom_icon("icon_status_success") - .icon_status_failed.hidden - = custom_icon("icon_status_failed") - .icon_status_warning.hidden - = custom_icon("icon_status_warning") .vue-pipelines-index = page_specific_javascript_tag('vue_pagination/index.js') -- cgit v1.2.1 From 1f99283519bd9a009e38464e5029d460fe1e290d Mon Sep 17 00:00:00 2001 From: Regis Date: Tue, 13 Dec 2016 10:27:34 -0700 Subject: status dynamic --- app/assets/javascripts/vue_pipelines_index/status.js.es6 | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/status.js.es6 b/app/assets/javascripts/vue_pipelines_index/status.js.es6 index 2f362d0c69e..fd145f5e066 100644 --- a/app/assets/javascripts/vue_pipelines_index/status.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/status.js.es6 @@ -4,7 +4,7 @@ ((gl) => { gl.VueStatusScope = Vue.extend({ props: [ - 'pipeline', + 'pipeline', 'svgs', 'match', ], computed: { cssClasses() { @@ -14,8 +14,7 @@ return cssObject; }, svg() { - return document - .querySelector(`.${this.pipeline.details.status.icon}`).innerHTML; + return this.svgs[this.match(this.pipeline.details.status.icon)]; }, }, template: ` -- cgit v1.2.1 From 7d2ca647df50f66eba40654b0d52fd8a9aa0d30d Mon Sep 17 00:00:00 2001 From: Regis Date: Tue, 13 Dec 2016 10:31:09 -0700 Subject: stage icon link --- app/assets/javascripts/vue_pipelines_index/stage.js.es6 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 index 7821ed62bd5..9a2aa5af2b4 100644 --- a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 @@ -12,6 +12,7 @@ return `has-tooltip ci-status-icon-${this.stage.status.label}`; }, svg() { + // debugger return this.svgs[this.match(this.stage.status.icon)]; }, }, @@ -19,7 +20,7 @@
    -- cgit v1.2.1 From f9db61fa7c596816367345de948fc6c92a1eabbe Mon Sep 17 00:00:00 2001 From: Regis Date: Tue, 13 Dec 2016 10:38:51 -0700 Subject: add more tests for pagination --- app/assets/javascripts/vue_pipelines_index/stage.js.es6 | 1 - 1 file changed, 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 index 9a2aa5af2b4..7fcf575b17f 100644 --- a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 @@ -12,7 +12,6 @@ return `has-tooltip ci-status-icon-${this.stage.status.label}`; }, svg() { - // debugger return this.svgs[this.match(this.stage.status.icon)]; }, }, -- cgit v1.2.1 From c5d12e3706ee6bc41d6be897e923b6c20a267078 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Mon, 12 Dec 2016 15:31:11 -0600 Subject: Remove duplicate shades of gray and black --- app/assets/stylesheets/framework/buttons.scss | 2 +- app/assets/stylesheets/framework/dropdowns.scss | 10 +++++----- app/assets/stylesheets/framework/forms.scss | 2 +- app/assets/stylesheets/framework/header.scss | 6 +++--- app/assets/stylesheets/framework/nav.scss | 2 +- app/assets/stylesheets/framework/page-header.scss | 2 +- app/assets/stylesheets/framework/variables.scss | 10 ++-------- app/assets/stylesheets/framework/zen.scss | 2 +- app/assets/stylesheets/pages/boards.scss | 2 +- app/assets/stylesheets/pages/builds.scss | 4 ++-- app/assets/stylesheets/pages/commits.scss | 4 ++-- app/assets/stylesheets/pages/environments.scss | 8 ++++---- app/assets/stylesheets/pages/issuable.scss | 4 ++-- app/assets/stylesheets/pages/merge_requests.scss | 2 +- app/assets/stylesheets/pages/milestone.scss | 2 +- app/assets/stylesheets/pages/pipelines.scss | 10 +++++----- app/assets/stylesheets/pages/settings.scss | 2 +- app/assets/stylesheets/pages/status.scss | 8 ++++---- 18 files changed, 38 insertions(+), 44 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss index 1c7b2f4df7c..d87a2620376 100644 --- a/app/assets/stylesheets/framework/buttons.scss +++ b/app/assets/stylesheets/framework/buttons.scss @@ -331,7 +331,7 @@ margin-left: 10px; i { - color: $gl-icon-color; + color: $gl-gray-light; } } diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index d5914b900e2..628e426891e 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -35,7 +35,7 @@ .dropdown-toggle { padding: 6px 8px 6px 10px; background-color: $dropdown-toggle-bg; - color: $dropdown-toggle-color; + color: $gl-text-color; font-size: 14px; text-align: left; border: 1px solid $border-color; @@ -131,7 +131,7 @@ font-size: 14px; font-weight: normal; padding: 8px 0; - background-color: $dropdown-bg; + background-color: $white-light; border: 1px solid $dropdown-border-color; border-radius: $border-radius-base; box-shadow: 0 2px 4px $dropdown-shadow-color; @@ -202,7 +202,7 @@ } .icon-play { - fill: $table-text-gray; + fill: $gl-gray-light; margin-right: 6px; height: 12px; width: 11px; @@ -621,11 +621,11 @@ .dropdown-menu-inner-content { display: block; - color: $gl-placeholder-color; + color: $gl-gray-light; } .dropdown-toggle-text { &.is-default { - color: $gl-placeholder-color; + color: $gl-gray-light; } } diff --git a/app/assets/stylesheets/framework/forms.scss b/app/assets/stylesheets/framework/forms.scss index 25a2b38baaa..89a51959571 100644 --- a/app/assets/stylesheets/framework/forms.scss +++ b/app/assets/stylesheets/framework/forms.scss @@ -149,7 +149,7 @@ label { } .form-control::-webkit-input-placeholder { - color: $gl-placeholder-color; + color: $gl-gray-light; } .input-group { diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index cc2286038c0..74fd97f811e 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -45,7 +45,7 @@ header { padding: 0; .nav > li > a { - color: $gl-icon-color; + color: $gl-gray-light; font-size: 18px; padding: 0; margin: ($header-height - 28) / 2 0; @@ -63,7 +63,7 @@ header { &:focus, &:active { background-color: $background-color; - color: darken($gl-icon-color, 30%); + color: darken($gl-gray-light, 30%); .todos-pending-count { background: darken($todo-alert-blue, 10%); @@ -88,7 +88,7 @@ header { } &.active { - color: $gl-icon-color; + color: $gl-gray-light; } } } diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index ea77348633d..ea86961eabc 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -317,7 +317,7 @@ .fa-caret-down { margin-left: 5px; - color: $gl-icon-color; + color: $gl-gray-light; } .dropdown { diff --git a/app/assets/stylesheets/framework/page-header.scss b/app/assets/stylesheets/framework/page-header.scss index 85c1385d5d9..fff7d7f7524 100644 --- a/app/assets/stylesheets/framework/page-header.scss +++ b/app/assets/stylesheets/framework/page-header.scss @@ -14,7 +14,7 @@ .header-action-buttons { i { - color: $gl-icon-color; + color: $gl-gray-light; font-size: 13px; margin-right: 3px; } diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index a1d5f6427f4..4b178a75f58 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -93,7 +93,6 @@ $focus-border-color: #3aabf0; $table-border-color: #f0f0f0; $background-color: $gray-light; $dark-background-color: #f5f5f5; -$table-text-gray: #8f8f8f; $well-expand-item: #e8f2f7; $well-inner-border: #eef0f2; $well-light-border: #f1f1f1; @@ -113,12 +112,11 @@ $gl-text-orange: #d90; $gl-link-color: #3777b0; $gl-diff-text-color: #555; $gl-dark-link-color: #333; -$gl-placeholder-color: #8f8f8f; -$gl-icon-color: $gl-placeholder-color; +$gl-gray-light: #8f8f8f; $gl-grayish-blue: #7f8fa4; $gl-gray: $gl-text-color; $gl-gray-dark: #313236; -$gl-gray-light: $gl-placeholder-color; +$gl-gray-light: $gl-gray-light; $gl-header-color: #4c4e54; /* @@ -272,7 +270,6 @@ $regular_font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-San * Dropdowns */ $dropdown-width: 300px; -$dropdown-bg: #fff; $dropdown-link-color: #555; $dropdown-link-hover-bg: $row-hover; $dropdown-empty-row-bg: rgba(#000, .04); @@ -289,7 +286,6 @@ $dropdown-loading-bg: rgba(#fff, .6); $dropdown-chevron-size: 10px; $dropdown-toggle-bg: #fff; -$dropdown-toggle-color: #5c5c5c; $dropdown-toggle-border-color: #e5e5e5; $dropdown-toggle-hover-border-color: darken($dropdown-toggle-border-color, 13%); $dropdown-toggle-active-border-color: darken($dropdown-toggle-border-color, 14%); @@ -344,7 +340,6 @@ $note-line2-border: #ddd; * Zen */ $zen-control-color: #555; -$zen-control-hover-color: #111; /* * Calendar @@ -373,7 +368,6 @@ $personal-access-tokens-disabled-label-color: #bbb; /* * CI */ -$ci-output-bg: #1d1f21; $ci-text-color: #c5c8c6; $ci-skipped-color: #888; diff --git a/app/assets/stylesheets/framework/zen.scss b/app/assets/stylesheets/framework/zen.scss index e5c7d70d45a..a1e3038b8de 100644 --- a/app/assets/stylesheets/framework/zen.scss +++ b/app/assets/stylesheets/framework/zen.scss @@ -57,6 +57,6 @@ font-size: 36px; &:hover { - color: $zen-control-hover-color; + color: $black; } } diff --git a/app/assets/stylesheets/pages/boards.scss b/app/assets/stylesheets/pages/boards.scss index 0d9cf679e7c..59ba0939785 100644 --- a/app/assets/stylesheets/pages/boards.scss +++ b/app/assets/stylesheets/pages/boards.scss @@ -253,7 +253,7 @@ .board-list-count { padding: 10px 0; - color: $gl-placeholder-color; + color: $gl-gray-light; font-size: 13px; > .fa { diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index dcc13f6d74a..bf00b23d787 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -96,7 +96,7 @@ } .build-trace { - background: $ci-output-bg; + background: $black; color: $ci-text-color; white-space: pre; overflow-x: auto; @@ -257,7 +257,7 @@ } .build-light-text { - color: $gl-placeholder-color; + color: $gl-gray-light; } .build-gutter-toggle { diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss index c29b5fdea78..c4ee9a51ed5 100644 --- a/app/assets/stylesheets/pages/commits.scss +++ b/app/assets/stylesheets/pages/commits.scss @@ -38,7 +38,7 @@ .text-expander { display: inline-block; background: $gray-light; - color: $gl-placeholder-color; + color: $gl-gray-light; padding: 0 5px; cursor: pointer; border: 1px solid $border-gray-dark; @@ -174,7 +174,7 @@ height: 14px; width: 14px; vertical-align: middle; - fill: $table-text-gray; + fill: $gl-gray-light; } } diff --git a/app/assets/stylesheets/pages/environments.scss b/app/assets/stylesheets/pages/environments.scss index de3d2ba549f..96aee3a300a 100644 --- a/app/assets/stylesheets/pages/environments.scss +++ b/app/assets/stylesheets/pages/environments.scss @@ -64,14 +64,14 @@ .external-url, .dropdown-new { - color: $table-text-gray; + color: $gl-gray-light; } .dropdown-menu { .fa { margin-right: 6px; - color: $table-text-gray; + color: $gl-gray-light; } } @@ -82,7 +82,7 @@ .stop-env-link, .external-url { - color: $table-text-gray; + color: $gl-gray-light; .stop-env-icon { font-size: 14px; @@ -117,7 +117,7 @@ .badge { font-weight: normal; background-color: $gray-darker; - color: $gl-placeholder-color; + color: $gl-gray-light; vertical-align: baseline; } } diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 407c0afbac8..6ef7f9c2c1e 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -169,7 +169,7 @@ } .no-value { - color: $gl-placeholder-color; + color: $gl-gray-light; } .sidebar-collapsed-icon { @@ -333,7 +333,7 @@ margin-left: 5px; a { - color: $gl-placeholder-color; + color: $gl-gray-light; } } diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index 6234779ac19..156724f44a8 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -359,7 +359,7 @@ th { background-color: $white-light; - color: $gl-placeholder-color; + color: $gl-gray-light; } } } diff --git a/app/assets/stylesheets/pages/milestone.scss b/app/assets/stylesheets/pages/milestone.scss index dfc6079bd15..77c523d7310 100644 --- a/app/assets/stylesheets/pages/milestone.scss +++ b/app/assets/stylesheets/pages/milestone.scss @@ -108,7 +108,7 @@ margin-top: 7px; .issuable-number { - color: $gl-placeholder-color; + color: $gl-gray-light; margin-right: 5px; } diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 08062b85504..656dcd92a06 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -117,7 +117,7 @@ height: 14px; width: 14px; vertical-align: middle; - fill: $table-text-gray; + fill: $gl-gray-light; } .fa { @@ -200,7 +200,7 @@ .duration, .finished-at { - color: $table-text-gray; + color: $gl-gray-light; margin: 4px 0; .fa { @@ -221,7 +221,7 @@ .btn { margin: 0; - color: $table-text-gray; + color: $gl-gray-light; } .cancel-retry-btns { @@ -234,10 +234,10 @@ .dropdown-toggle, .dropdown-menu { - color: $table-text-gray; + color: $gl-gray-light; .fa { - color: $table-text-gray; + color: $gl-gray-light; font-size: 14px; } diff --git a/app/assets/stylesheets/pages/settings.scss b/app/assets/stylesheets/pages/settings.scss index 51c926608f9..ddee2c95247 100644 --- a/app/assets/stylesheets/pages/settings.scss +++ b/app/assets/stylesheets/pages/settings.scss @@ -1,5 +1,5 @@ .settings-list-icon { - color: $gl-placeholder-color; + color: $gl-gray-light; font-size: $settings-icon-size; line-height: 42px; } diff --git a/app/assets/stylesheets/pages/status.scss b/app/assets/stylesheets/pages/status.scss index 5084b466722..f3b0608e545 100644 --- a/app/assets/stylesheets/pages/status.scss +++ b/app/assets/stylesheets/pages/status.scss @@ -102,15 +102,15 @@ &.ci-created, &.ci-skipped { - color: $table-text-gray; - border-color: $table-text-gray; + color: $gl-gray-light; + border-color: $gl-gray-light; &:not(span):hover { - background-color: rgba( $table-text-gray, .07); + background-color: rgba( $gl-gray-light, .07); } svg { - fill: $table-text-gray; + fill: $gl-gray-light; } } } -- cgit v1.2.1 From e4a000478f327885fd9dcbc7d47ba77045cef139 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Mon, 12 Dec 2016 15:49:12 -0600 Subject: Combining more grays --- app/assets/stylesheets/framework/buttons.scss | 6 +++--- app/assets/stylesheets/framework/dropdowns.scss | 14 ++++++------- app/assets/stylesheets/framework/issue_box.scss | 2 +- app/assets/stylesheets/framework/lists.scss | 2 +- .../stylesheets/framework/markdown_area.scss | 2 +- app/assets/stylesheets/framework/nav.scss | 4 ++-- app/assets/stylesheets/framework/variables.scss | 23 ++-------------------- app/assets/stylesheets/framework/zen.scss | 2 +- app/assets/stylesheets/pages/builds.scss | 2 +- app/assets/stylesheets/pages/note_form.scss | 2 +- app/assets/stylesheets/pages/notes.scss | 8 ++++---- app/assets/stylesheets/pages/pipelines.scss | 2 +- app/assets/stylesheets/pages/profile.scss | 2 +- app/assets/stylesheets/pages/search.scss | 4 ++-- app/assets/stylesheets/pages/xterm.scss | 2 +- 15 files changed, 29 insertions(+), 48 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss index d87a2620376..e6f03528d41 100644 --- a/app/assets/stylesheets/framework/buttons.scss +++ b/app/assets/stylesheets/framework/buttons.scss @@ -235,7 +235,7 @@ } .btn-transparent { - color: $btn-transparent-color; + color: $gl-gray-light; background-color: transparent; border: 0; @@ -309,7 +309,7 @@ text-align: left; padding: 6px 16px; border-color: $border-color; - color: $btn-placeholder-gray; + color: $gray-darkest; background-color: $background-color; &:hover, @@ -318,7 +318,7 @@ cursor: text; box-shadow: none; border-color: $border-color; - color: $btn-placeholder-gray; + color: $gray-darkest; background-color: $background-color; } } diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index 628e426891e..fd5f521e4a0 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -10,7 +10,7 @@ @mixin chevron-active { .fa-chevron-down { - color: $dropdown-toggle-hover-icon-color; + color: $gray-darkest; } } @@ -28,7 +28,7 @@ .dropdown-toggle, .dropdown-menu-toggle { @include chevron-active; - border-color: $dropdown-toggle-hover-border-color; + border-color: $gray-darkest; } } @@ -73,7 +73,7 @@ } .fa { - color: $dropdown-toggle-icon-color; + color: $gray-darkest; } .fa-chevron-down { @@ -85,7 +85,7 @@ &:hover { @include chevron-active; - border-color: $dropdown-toggle-hover-border-color; + border-color: $gray-darkest; } &:focus:active { @@ -210,7 +210,7 @@ } .dropdown-header { - color: $dropdown-header-color; + color: $gl-gray-light; font-size: 13px; line-height: 22px; padding: 0 10px; @@ -223,7 +223,7 @@ .unclickable { cursor: not-allowed; padding: 5px 8px; - color: $dropdown-header-color; + color: $gl-gray-light; } } @@ -602,7 +602,7 @@ th { padding: 2px 0; - color: $calendar-header-color; + color: $note-disabled-comment-color; font-weight: normal; text-transform: lowercase; border-top: 1px solid $calendar-border-color; diff --git a/app/assets/stylesheets/framework/issue_box.scss b/app/assets/stylesheets/framework/issue_box.scss index 44834a84234..298913108ee 100644 --- a/app/assets/stylesheets/framework/issue_box.scss +++ b/app/assets/stylesheets/framework/issue_box.scss @@ -41,6 +41,6 @@ } &.status-box-upcoming { - background: $issue-box-upcoming-bg; + background: $gl-gray-light; } } diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss index ed4b60faf92..389ead37366 100644 --- a/app/assets/stylesheets/framework/lists.scss +++ b/app/assets/stylesheets/framework/lists.scss @@ -224,7 +224,7 @@ ul.content-list { } .label-default { - color: $btn-transparent-color; + color: $gl-gray-light; } } diff --git a/app/assets/stylesheets/framework/markdown_area.scss b/app/assets/stylesheets/framework/markdown_area.scss index 59a30d31ac7..cf298773d58 100644 --- a/app/assets/stylesheets/framework/markdown_area.scss +++ b/app/assets/stylesheets/framework/markdown_area.scss @@ -135,7 +135,7 @@ .toolbar-btn { float: left; padding: 0 5px; - color: $note-toolbar-color; + color: $gl-gray-light; background: transparent; border: 0; outline: 0; diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index ea86961eabc..26d290976dc 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -51,7 +51,7 @@ margin-bottom: -1px; font-size: 14px; line-height: 28px; - color: $note-toolbar-color; + color: $gl-gray-light; border-bottom: 2px solid transparent; &:hover, @@ -80,7 +80,7 @@ .badge { font-weight: normal; background-color: $nav-badge-bg; - color: $btn-transparent-color; + color: $gl-gray-light; vertical-align: baseline; } } diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 4b178a75f58..00ac5e82181 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -26,7 +26,7 @@ $gray-lighter: #f9f9f9; $gray-normal: darken($gray-light, $darken-normal-factor); $gray-dark: darken($gray-light, $darken-dark-factor); $gray-darker: #eee; -$gray-darkest: #c9c9c9; +$gray-darkest: #c4c4c4; $green-light: #3cbd70; $green-normal: darken($green-light, $darken-normal-factor); @@ -116,7 +116,6 @@ $gl-gray-light: #8f8f8f; $gl-grayish-blue: #7f8fa4; $gl-gray: $gl-text-color; $gl-gray-dark: #313236; -$gl-gray-light: $gl-gray-light; $gl-header-color: #4c4e54; /* @@ -166,7 +165,6 @@ $header-height: 50px; $fixed-layout-width: 1280px; $error-exclamation-point: #e62958; $border-radius-default: 2px; -$btn-transparent-color: #8f8f8f; $settings-icon-size: 18px; $provider-btn-group-border: #e5e5e5; $provider-btn-not-active-color: #4688f1; @@ -191,7 +189,6 @@ $count-arrow-border: #dce0e5; $save-project-loader-color: #555; $divergence-graph-bar-bg: #ccc; $divergence-graph-separator-bg: #ccc; -$issue-box-upcoming-bg: #8f8f8f; /* * Common component specific colors @@ -276,7 +273,6 @@ $dropdown-empty-row-bg: rgba(#000, .04); $dropdown-border-color: $border-color; $dropdown-shadow-color: rgba(#000, .1); $dropdown-divider-color: rgba(#000, .1); -$dropdown-header-color: #959494; $dropdown-title-btn-color: #bfbfbf; $dropdown-input-color: #555; $dropdown-input-fa-color: #c7c7c7; @@ -287,18 +283,14 @@ $dropdown-chevron-size: 10px; $dropdown-toggle-bg: #fff; $dropdown-toggle-border-color: #e5e5e5; -$dropdown-toggle-hover-border-color: darken($dropdown-toggle-border-color, 13%); $dropdown-toggle-active-border-color: darken($dropdown-toggle-border-color, 14%); -$dropdown-toggle-icon-color: #c4c4c4; -$dropdown-toggle-hover-icon-color: darken($dropdown-toggle-icon-color, 7%); + /* * Buttons */ $btn-active-gray: #ececec; $btn-active-gray-light: e4e7ed; -$btn-placeholder-gray: #c7c7c7; -$btn-white-active: #848484; $btn-gray-hover: #eee; /* @@ -315,22 +307,18 @@ $award-emoji-new-btn-icon-color: #dcdcdc; $search-input-border-color: rgba(#4688f1, .8); $search-input-focus-shadow-color: $dropdown-input-focus-shadow; $search-input-width: 220px; -$location-badge-color: #aaa; $location-badge-bg: $dark-background-color; $location-badge-active-bg: #4f91f8; $location-icon-color: #e7e9ed; -$location-icon-active-color: #807e7e; /* * Notes */ $notes-light-color: #8e8e8e; -$notes-action-color: #c3c3c3; $notes-role-color: #8e8e8e; $notes-role-border-color: #e4e4e4; $note-disabled-comment-color: #b2b2b2; $note-form-border-color: #e5e5e5; -$note-toolbar-color: #959494; $note-targe3-outside: #fffff0; $note-targe3-inside: #ffffd3; $note-line2-border: #ddd; @@ -344,7 +332,6 @@ $zen-control-color: #555; /* * Calendar */ -$calendar-header-color: #b8b8b8; $calendar-hover-bg: #ecf3fe; $calendar-border-color: rgba(#000, .1); $calendar-unselectable-bg: $gray-light; @@ -360,15 +347,9 @@ $cycle-analytics-dark-text: $gl-title-color; $cycle-analytics-light-gray: #bfbfbf; $cycle-analytics-dismiss-icon-color: #b2b2b2; -/* - * Personal Access Tokens - */ -$personal-access-tokens-disabled-label-color: #bbb; - /* * CI */ -$ci-text-color: #c5c8c6; $ci-skipped-color: #888; /* diff --git a/app/assets/stylesheets/framework/zen.scss b/app/assets/stylesheets/framework/zen.scss index a1e3038b8de..84b639fabf5 100644 --- a/app/assets/stylesheets/framework/zen.scss +++ b/app/assets/stylesheets/framework/zen.scss @@ -40,7 +40,7 @@ } .zen-control-full { - color: $note-toolbar-color; + color: $gl-gray-light; &:hover { color: $gl-link-color; diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index bf00b23d787..e2d80723eff 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -97,7 +97,7 @@ .build-trace { background: $black; - color: $ci-text-color; + color: $gray-darkest; white-space: pre; overflow-x: auto; font-size: 12px; diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss index c35d71f9e7b..468f07d0534 100644 --- a/app/assets/stylesheets/pages/note_form.scss +++ b/app/assets/stylesheets/pages/note_form.scss @@ -204,7 +204,7 @@ .comment-toolbar { padding-top: $gl-padding-top; - color: $note-toolbar-color; + color: $gl-gray-light; border-top: 1px solid $border-color; } diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss index 10eb3d4203e..0d4db14dafb 100644 --- a/app/assets/stylesheets/pages/notes.scss +++ b/app/assets/stylesheets/pages/notes.scss @@ -372,7 +372,7 @@ ul.notes { .note-actions { float: right; margin-left: 10px; - color: $notes-action-color; + color: $gray-darkest; } .note-actions { @@ -411,7 +411,7 @@ ul.notes { } .fa { - color: $notes-action-color; + color: $gray-darkest; position: relative; font-size: 17px; } @@ -573,10 +573,10 @@ ul.notes { svg { position: relative; - color: $notes-action-color; + color: $gray-darkest; path { - fill: $notes-action-color; + fill: $gray-darkest; } } } diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 656dcd92a06..acc9dae4745 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -654,7 +654,7 @@ .toggle-pipeline-btn { .fa { - color: $dropdown-header-color; + color: $gl-gray-light; } } diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss index f8677f93fe0..ffbda72b00e 100644 --- a/app/assets/stylesheets/pages/profile.scss +++ b/app/assets/stylesheets/pages/profile.scss @@ -198,7 +198,7 @@ } .personal-access-tokens-never-expires-label { - color: $personal-access-tokens-disabled-label-color; + color: $note-disabled-comment-color; } .datepicker.personal-access-tokens-expires-at .ui-state-disabled span { diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss index 63d0a34e610..b027ace6a1f 100644 --- a/app/assets/stylesheets/pages/search.scss +++ b/app/assets/stylesheets/pages/search.scss @@ -51,7 +51,7 @@ border-radius: $border-radius-default; font-size: 14px; font-style: normal; - color: $location-badge-color; + color: $note-disabled-comment-color; display: inline-block; background-color: $location-badge-bg; vertical-align: top; @@ -140,7 +140,7 @@ .search-input-wrap { i { - color: $location-icon-active-color; + color: $layout-link-gray; } } } diff --git a/app/assets/stylesheets/pages/xterm.scss b/app/assets/stylesheets/pages/xterm.scss index 9f9d630978a..b085c56390d 100644 --- a/app/assets/stylesheets/pages/xterm.scss +++ b/app/assets/stylesheets/pages/xterm.scss @@ -18,7 +18,7 @@ $l-blue: #81a2be; $l-magenta: #b294bb; $l-cyan: #8abeb7; - $l-white: $ci-text-color; + $l-white: $gray-darkest; /* * xterm colors -- cgit v1.2.1 From 0b72554c1bb47c88361f9fbc6185f49767337368 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Mon, 12 Dec 2016 16:26:21 -0600 Subject: Finish refactoring grays --- app/assets/stylesheets/framework/awards.scss | 6 ++-- app/assets/stylesheets/framework/blocks.scss | 4 +-- app/assets/stylesheets/framework/buttons.scss | 14 ++++----- app/assets/stylesheets/framework/callout.scss | 2 +- app/assets/stylesheets/framework/dropdowns.scss | 4 +-- app/assets/stylesheets/framework/files.scss | 2 +- app/assets/stylesheets/framework/forms.scss | 2 +- app/assets/stylesheets/framework/header.scss | 12 ++++---- app/assets/stylesheets/framework/images.scss | 2 +- app/assets/stylesheets/framework/lists.scss | 10 +++---- .../stylesheets/framework/markdown_area.scss | 2 +- app/assets/stylesheets/framework/nav.scss | 16 +++++----- app/assets/stylesheets/framework/selects.scss | 4 +-- app/assets/stylesheets/framework/sidebar.scss | 2 +- app/assets/stylesheets/framework/tables.scss | 4 +-- app/assets/stylesheets/framework/timeline.scss | 2 +- .../framework/tw_bootstrap_variables.scss | 10 +++---- app/assets/stylesheets/framework/variables.scss | 35 ++++------------------ app/assets/stylesheets/framework/wells.scss | 4 +-- app/assets/stylesheets/highlight/white.scss | 6 ++-- .../mailers/highlighted_diff_email.scss | 6 ++-- app/assets/stylesheets/pages/boards.scss | 2 +- app/assets/stylesheets/pages/builds.scss | 2 +- app/assets/stylesheets/pages/commits.scss | 4 +-- app/assets/stylesheets/pages/diff.scss | 8 ++--- app/assets/stylesheets/pages/editor.scss | 4 +-- app/assets/stylesheets/pages/events.scss | 2 +- app/assets/stylesheets/pages/help.scss | 2 +- app/assets/stylesheets/pages/issuable.scss | 8 ++--- app/assets/stylesheets/pages/issues.scss | 8 ++--- app/assets/stylesheets/pages/merge_conflicts.scss | 2 +- app/assets/stylesheets/pages/merge_requests.scss | 4 +-- app/assets/stylesheets/pages/note_form.scss | 2 +- app/assets/stylesheets/pages/notes.scss | 12 ++++---- app/assets/stylesheets/pages/pipelines.scss | 4 +-- app/assets/stylesheets/pages/profile.scss | 8 ++--- app/assets/stylesheets/pages/projects.scss | 10 +++---- app/assets/stylesheets/pages/search.scss | 2 +- app/assets/stylesheets/pages/snippets.scss | 2 +- app/assets/stylesheets/pages/tree.scss | 10 +++---- 40 files changed, 110 insertions(+), 135 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/awards.scss b/app/assets/stylesheets/framework/awards.scss index dece5c3202b..9fc9bcebc44 100644 --- a/app/assets/stylesheets/framework/awards.scss +++ b/app/assets/stylesheets/framework/awards.scss @@ -12,8 +12,8 @@ z-index: 9; width: 300px; font-size: 14px; - background-color: $award-emoji-menu-bg; - border: 1px solid $award-emoji-menu-border; + background-color: $white-light; + border: 1px solid $border-white-light; border-radius: $border-radius-base; box-shadow: 0 6px 12px $award-emoji-menu-shadow; pointer-events: none; @@ -135,7 +135,7 @@ } .award-control-icon { - color: $award-emoji-new-btn-icon-color; + color: $border-gray-normal; margin-top: 1px; } } diff --git a/app/assets/stylesheets/framework/blocks.scss b/app/assets/stylesheets/framework/blocks.scss index 95c02499271..9f02749f5ab 100644 --- a/app/assets/stylesheets/framework/blocks.scss +++ b/app/assets/stylesheets/framework/blocks.scss @@ -24,7 +24,7 @@ .row-content-block { margin-top: 0; margin-bottom: -$gl-padding; - background-color: $background-color; + background-color: $gray-light; padding: $gl-padding; margin-bottom: 0; border-top: 1px solid $white-dark; @@ -118,7 +118,7 @@ .cover-block { text-align: center; - background: $background-color; + background: $gray-light; padding-top: 44px; position: relative; diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss index e6f03528d41..59ff17ad2c1 100644 --- a/app/assets/stylesheets/framework/buttons.scss +++ b/app/assets/stylesheets/framework/buttons.scss @@ -88,11 +88,11 @@ } @mixin btn-gray { - @include btn-color($gray-light, $border-gray-light, $gray-normal, $border-gray-normal, $gray-dark, $border-gray-dark, $gl-gray-dark); + @include btn-color($gray-light, $border-gray-normal, $gray-normal, $border-gray-normal, $gray-dark, $border-gray-dark, $gl-gray-dark); } @mixin btn-white { - @include btn-color($white-light, $border-color, $white-normal, $border-white-normal, $white-dark, $border-white-dark, $gl-text-color); + @include btn-color($white-light, $border-color, $white-normal, $border-white-normal, $white-dark, $border-gray-dark, $gl-text-color); } @mixin btn-with-margin { @@ -289,7 +289,7 @@ .active { box-shadow: $gl-btn-active-background; - border: 1px solid $border-white-dark !important; + border: 1px solid $border-gray-dark !important; background-color: $btn-active-gray-light !important; } } @@ -310,7 +310,7 @@ padding: 6px 16px; border-color: $border-color; color: $gray-darkest; - background-color: $background-color; + background-color: $gray-light; &:hover, &:active, @@ -319,7 +319,7 @@ box-shadow: none; border-color: $border-color; color: $gray-darkest; - background-color: $background-color; + background-color: $gray-light; } } @@ -344,8 +344,8 @@ } .btn-static { - background-color: $background-color !important; - border: 1px solid $border-gray-light; + background-color: $gray-light !important; + border: 1px solid $border-gray-normal; cursor: default; &:active { diff --git a/app/assets/stylesheets/framework/callout.scss b/app/assets/stylesheets/framework/callout.scss index 2a100980aca..e0e46dd73af 100644 --- a/app/assets/stylesheets/framework/callout.scss +++ b/app/assets/stylesheets/framework/callout.scss @@ -11,7 +11,7 @@ padding: $gl-padding; border-left: 3px solid $border-color; color: $text-color; - background: $background-color; + background: $gray-light; } .bs-callout h4 { diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index fd5f521e4a0..ecd540793d0 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -34,7 +34,7 @@ .dropdown-toggle { padding: 6px 8px 6px 10px; - background-color: $dropdown-toggle-bg; + background-color: $white-light; color: $gl-text-color; font-size: 14px; text-align: left; @@ -609,7 +609,7 @@ } .ui-datepicker-unselectable { - background-color: $calendar-unselectable-bg; + background-color: $gray-light; } } diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss index ab0b81f77f7..88ed0a4a17e 100644 --- a/app/assets/stylesheets/framework/files.scss +++ b/app/assets/stylesheets/framework/files.scss @@ -19,7 +19,7 @@ .file-title { position: relative; - background-color: $background-color; + background-color: $gray-light; border-bottom: 1px solid $border-color; margin: 0; text-align: left; diff --git a/app/assets/stylesheets/framework/forms.scss b/app/assets/stylesheets/framework/forms.scss index 89a51959571..940807fc399 100644 --- a/app/assets/stylesheets/framework/forms.scss +++ b/app/assets/stylesheets/framework/forms.scss @@ -22,7 +22,7 @@ input[type='text'].danger { margin-top: 0; margin-bottom: -$gl-padding; padding: $gl-padding; - background-color: $background-color; + background-color: $gray-light; border-top: 1px solid $border-color; } diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index 74fd97f811e..971940773f7 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -9,7 +9,7 @@ header { &.navbar-empty { height: $header-height; background: $white-light; - border-bottom: 1px solid $btn-gray-hover; + border-bottom: 1px solid $white-normal; .center-logo { margin: 8px 0; @@ -27,7 +27,7 @@ header { z-index: 100; margin-bottom: 0; height: $header-height; - background-color: $background-color; + background-color: $gray-light; border: none; border-bottom: 1px solid $border-color; @@ -62,7 +62,7 @@ header { &:hover, &:focus, &:active { - background-color: $background-color; + background-color: $gray-light; color: darken($gl-gray-light, 30%); .todos-pending-count { @@ -84,7 +84,7 @@ header { padding: 6px 10px; &:hover { - background-color: $btn-gray-hover; + background-color: $white-normal; } &.active { @@ -100,10 +100,10 @@ header { font-size: 18px; padding: 6px 10px; border: none; - background-color: $background-color; + background-color: $gray-light; &:hover { - background-color: $btn-gray-hover; + background-color: $white-normal; } } } diff --git a/app/assets/stylesheets/framework/images.scss b/app/assets/stylesheets/framework/images.scss index 878f44116ba..09a569ad415 100644 --- a/app/assets/stylesheets/framework/images.scss +++ b/app/assets/stylesheets/framework/images.scss @@ -4,7 +4,7 @@ } .appearance-light-logo-preview { - background-color: $background-color; + background-color: $gray-light; max-width: 72px; padding: 10px; margin-bottom: 10px; diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss index 389ead37366..e96cd671e34 100644 --- a/app/assets/stylesheets/framework/lists.scss +++ b/app/assets/stylesheets/framework/lists.scss @@ -36,7 +36,7 @@ color: $list-warning-row-color; } - &.smoke { background-color: $background-color; } + &.smoke { background-color: $gray-light; } &:not(.ui-sort-disabled):hover { background: $row-hover; @@ -46,7 +46,7 @@ border-bottom: none; &.bottom { - background: $background-color; + background: $gray-light; } } @@ -59,7 +59,7 @@ p { padding-top: 1px; margin: 0; - color: $gray-dark; + color: $white-normal; img { position: relative; @@ -113,7 +113,7 @@ ul.content-list { padding: 0; li { - border-color: $table-border-color; + border-color: $white-normal; font-size: $list-font-size; color: $list-text-color; @@ -186,7 +186,7 @@ ul.content-list { &.list-placeholder { background-color: $gray-light; - border: dotted 1px $gray-dark; + border: dotted 1px $white-normal; margin: 1px 0; min-height: 52px; } diff --git a/app/assets/stylesheets/framework/markdown_area.scss b/app/assets/stylesheets/framework/markdown_area.scss index cf298773d58..e30d81d09f0 100644 --- a/app/assets/stylesheets/framework/markdown_area.scss +++ b/app/assets/stylesheets/framework/markdown_area.scss @@ -114,7 +114,7 @@ // Border around images in issue and MR comments. img:not(.emoji) { - border: 1px solid $table-border-gray; + border: 1px solid $white-normal; padding: 5px; margin: 5px 0; // Ensure that image does not exceed viewport diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index 26d290976dc..e4affbb1be1 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -87,10 +87,10 @@ &.sub-nav { text-align: center; - background-color: $dark-background-color; + background-color: $gray-normal; .container-fluid { - background-color: $dark-background-color; + background-color: $gray-normal; margin-bottom: 0; } @@ -117,7 +117,7 @@ .top-area { @include clearfix; - border-bottom: 1px solid $btn-gray-hover; + border-bottom: 1px solid $white-normal; .nav-text { padding-top: 16px; @@ -289,7 +289,7 @@ top: $header-height; width: 100%; z-index: 11; - background: $background-color; + background: $gray-light; border-bottom: 1px solid $border-color; transition: padding $sidebar-transition-duration; text-align: center; @@ -352,7 +352,7 @@ } .fade-right { - @include fade(left, $background-color); + @include fade(left, $gray-light); right: -5px; .fa { @@ -361,7 +361,7 @@ } .fade-left { - @include fade(right, $background-color); + @include fade(right, $gray-light); left: -5px; .fa { @@ -372,7 +372,7 @@ &.sub-nav-scroll { .fade-right { - @include fade(left, $dark-background-color); + @include fade(left, $gray-normal); right: 0; .fa { @@ -381,7 +381,7 @@ } .fade-left { - @include fade(right, $dark-background-color); + @include fade(right, $gray-normal); left: 0; .fa { diff --git a/app/assets/stylesheets/framework/selects.scss b/app/assets/stylesheets/framework/selects.scss index fde1431b13e..9ab17e67d4c 100644 --- a/app/assets/stylesheets/framework/selects.scss +++ b/app/assets/stylesheets/framework/selects.scss @@ -39,7 +39,7 @@ } &:hover { - background-color: $gray-dark; + background-color: $white-normal; border-color: $border-white-normal; color: $gl-text-color; } @@ -108,7 +108,7 @@ border-color: $input-border; color: $gl-text-color; line-height: 15px; - background-color: $background-color; + background-color: $gray-light; background-image: none; .select2-search-choice-close { diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss index 0aa609b8dd5..46a06cd7eab 100644 --- a/app/assets/stylesheets/framework/sidebar.scss +++ b/app/assets/stylesheets/framework/sidebar.scss @@ -23,7 +23,7 @@ .sidebar-wrapper { z-index: 1000; - background: $background-color; + background: $gray-light; .nicescroll-rails-hr { // TODO: Figure out why nicescroll doesn't hide horizontal bar diff --git a/app/assets/stylesheets/framework/tables.scss b/app/assets/stylesheets/framework/tables.scss index 5d0ca63ea08..6d9fa74a030 100644 --- a/app/assets/stylesheets/framework/tables.scss +++ b/app/assets/stylesheets/framework/tables.scss @@ -31,7 +31,7 @@ table { } th { - background-color: $background-color; + background-color: $gray-light; font-weight: normal; border-bottom: none; @@ -41,7 +41,7 @@ table { } td { - border-color: $table-border-color; + border-color: $white-normal; } } } diff --git a/app/assets/stylesheets/framework/timeline.scss b/app/assets/stylesheets/framework/timeline.scss index 875cded8b4e..6078505807e 100644 --- a/app/assets/stylesheets/framework/timeline.scss +++ b/app/assets/stylesheets/framework/timeline.scss @@ -6,7 +6,7 @@ .timeline-entry { padding: $gl-padding $gl-btn-padding 11px; - border-color: $table-border-color; + border-color: $white-normal; color: $gl-gray; border-bottom: 1px solid $border-white-light; diff --git a/app/assets/stylesheets/framework/tw_bootstrap_variables.scss b/app/assets/stylesheets/framework/tw_bootstrap_variables.scss index c731a8f222f..876adf7f712 100644 --- a/app/assets/stylesheets/framework/tw_bootstrap_variables.scss +++ b/app/assets/stylesheets/framework/tw_bootstrap_variables.scss @@ -78,7 +78,7 @@ $pagination-active-bg: $white-light; $pagination-active-border: $border-color; $pagination-disabled-color: #cdcdcd; -$pagination-disabled-bg: $background-color; +$pagination-disabled-bg: $gray-light; $pagination-disabled-border: $border-color; @@ -117,8 +117,8 @@ $alert-border-radius: 0; $panel-border-radius: 2px; $panel-default-text: $text-color; $panel-default-border: $border-color; -$panel-default-heading-bg: $background-color; -$panel-footer-bg: $background-color; +$panel-default-heading-bg: $gray-light; +$panel-footer-bg: $gray-light; $panel-inner-border: $border-color; //== Wells @@ -153,8 +153,8 @@ $nav-link-padding: 13px $gl-padding; //== Code // //## -$pre-bg: $background-color !default; +$pre-bg: $gray-light !default; $pre-color: $gl-gray !default; $pre-border-color: $border-color; -$table-bg-accent: $background-color; +$table-bg-accent: $gray-light; diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 00ac5e82181..936aaf38254 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -17,14 +17,13 @@ $darken-dark-factor: 10%; $darken-border-factor: 5%; $white-light: #fff; -$white-normal: darken($white-light, $darken-normal-factor); -$white-dark: darken($white-light, $darken-dark-factor); +$white-normal: #f0f0f0; +$white-dark: #eaeaea; $gray-lightest: #fdfdfd; $gray-light: #fafafa; $gray-lighter: #f9f9f9; -$gray-normal: darken($gray-light, $darken-normal-factor); -$gray-dark: darken($gray-light, $darken-dark-factor); +$gray-normal: #f5f5f5; $gray-darker: #eee; $gray-darkest: #c4c4c4; @@ -55,11 +54,9 @@ $black-transparent: rgba(0, 0, 0, 0.3); $border-white-light: darken($white-light, $darken-border-factor); $border-white-normal: darken($white-normal, $darken-border-factor); -$border-white-dark: darken($white-dark, $darken-border-factor); -$border-gray-light: darken($gray-light, $darken-border-factor); $border-gray-normal: darken($gray-normal, $darken-border-factor); -$border-gray-dark: darken($gray-dark, $darken-border-factor); +$border-gray-dark: darken($white-normal, $darken-border-factor); $border-green-extra-light: #9adb84; $border-green-light: darken($green-light, $darken-border-factor); @@ -78,9 +75,6 @@ $border-red-light: darken($red-light, $darken-border-factor); $border-red-normal: darken($red-normal, $darken-border-factor); $border-red-dark: darken($red-dark, $darken-border-factor); -$help-well-bg: $gray-light; -$help-well-border: #e5e5e5; - $warning-message-bg: #fbf2d9; $warning-message-color: #9e8e60; $warning-message-border: #f0e2bb; @@ -90,9 +84,6 @@ $warning-message-border: #f0e2bb; */ $border-color: #e5e5e5; $focus-border-color: #3aabf0; -$table-border-color: #f0f0f0; -$background-color: $gray-light; -$dark-background-color: #f5f5f5; $well-expand-item: #e8f2f7; $well-inner-border: #eef0f2; $well-light-border: #f1f1f1; @@ -166,7 +157,6 @@ $fixed-layout-width: 1280px; $error-exclamation-point: #e62958; $border-radius-default: 2px; $settings-icon-size: 18px; -$provider-btn-group-border: #e5e5e5; $provider-btn-not-active-color: #4688f1; $link-underline-blue: #4a8bee; $active-item-blue: #4a8bee; @@ -241,8 +231,6 @@ $line-removed-dark: #fac5cd; $line-number-old: #f9d7dc; $line-number-new: #ddfbe6; $line-number-select: #fbf2da; -$match-line: $gray-light; -$table-border-gray: #f0f0f0; $line-target-blue: #f6faff; $line-select-yellow: #fcf8e7; $line-select-yellow-dark: #f0e2bd; @@ -252,7 +240,6 @@ $file-mode-changed: #777; $file-mode-changed: #777; $diff-image-bg: #ddd; $diff-image-info-color: grey; -$diff-image-img-bg: #e5e5e5; $diff-swipe-border: #999; $diff-view-modes-color: grey; $diff-view-modes-border: #c1c1c1; @@ -280,10 +267,7 @@ $dropdown-input-focus-border: $focus-border-color; $dropdown-input-focus-shadow: rgba($dropdown-input-focus-border, .4); $dropdown-loading-bg: rgba(#fff, .6); $dropdown-chevron-size: 10px; - -$dropdown-toggle-bg: #fff; -$dropdown-toggle-border-color: #e5e5e5; -$dropdown-toggle-active-border-color: darken($dropdown-toggle-border-color, 14%); +$dropdown-toggle-active-border-color: darken($border-color, 14%); /* @@ -291,15 +275,11 @@ $dropdown-toggle-active-border-color: darken($dropdown-toggle-border-color, 14%) */ $btn-active-gray: #ececec; $btn-active-gray-light: e4e7ed; -$btn-gray-hover: #eee; /* * Award emoji */ -$award-emoji-menu-bg: #fff; -$award-emoji-menu-border: #f1f2f4; $award-emoji-menu-shadow: rgba(0,0,0,.175); -$award-emoji-new-btn-icon-color: #dcdcdc; /* * Search Box @@ -307,7 +287,6 @@ $award-emoji-new-btn-icon-color: #dcdcdc; $search-input-border-color: rgba(#4688f1, .8); $search-input-focus-shadow-color: $dropdown-input-focus-shadow; $search-input-width: 220px; -$location-badge-bg: $dark-background-color; $location-badge-active-bg: #4f91f8; $location-icon-color: #e7e9ed; @@ -316,9 +295,7 @@ $location-icon-color: #e7e9ed; */ $notes-light-color: #8e8e8e; $notes-role-color: #8e8e8e; -$notes-role-border-color: #e4e4e4; $note-disabled-comment-color: #b2b2b2; -$note-form-border-color: #e5e5e5; $note-targe3-outside: #fffff0; $note-targe3-inside: #ffffd3; $note-line2-border: #ddd; @@ -334,7 +311,6 @@ $zen-control-color: #555; */ $calendar-hover-bg: #ecf3fe; $calendar-border-color: rgba(#000, .1); -$calendar-unselectable-bg: $gray-light; $calendar-user-contrib-text: #959494; /* @@ -445,7 +421,6 @@ $help-shortcut-header-color: #333; /* * Issues */ -$issues-border: #e5e5e5; $issues-today-bg: #f3fff2; $issues-today-border: #e1e8d5; diff --git a/app/assets/stylesheets/framework/wells.scss b/app/assets/stylesheets/framework/wells.scss index f2860dfe84d..f9c850ebdc8 100644 --- a/app/assets/stylesheets/framework/wells.scss +++ b/app/assets/stylesheets/framework/wells.scss @@ -1,5 +1,5 @@ .info-well { - background: $background-color; + background: $gray-light; color: $gl-gray; border: 1px solid $border-color; border-radius: $border-radius-default; @@ -45,7 +45,7 @@ } .light-well { - background-color: $background-color; + background-color: $gray-light; padding: 15px; } diff --git a/app/assets/stylesheets/highlight/white.scss b/app/assets/stylesheets/highlight/white.scss index 1adab3ffd94..54a5664a874 100644 --- a/app/assets/stylesheets/highlight/white.scss +++ b/app/assets/stylesheets/highlight/white.scss @@ -69,14 +69,14 @@ $white-gc-bg: #eaf2f5; @mixin matchLine { color: $black-transparent; - background-color: $match-line; + background-color: $gray-light; } .code.white { // Line numbers .line-numbers, .diff-line-num { - background-color: $background-color; + background-color: $gray-light; } .diff-line-num, @@ -87,7 +87,7 @@ $white-gc-bg: #eaf2f5; // Code itself pre.code, .diff-line-num { - border-color: $table-border-gray; + border-color: $white-normal; } &, diff --git a/app/assets/stylesheets/mailers/highlighted_diff_email.scss b/app/assets/stylesheets/mailers/highlighted_diff_email.scss index 024b4df6bd0..60ff72c703e 100644 --- a/app/assets/stylesheets/mailers/highlighted_diff_email.scss +++ b/app/assets/stylesheets/mailers/highlighted_diff_email.scss @@ -91,9 +91,9 @@ $highlighted-gc-bg: #eaf2f5; padding: 0 5px; text-align: right; width: 35px; - background-color: $background-color; + background-color: $gray-light; color: $black-transparent; - border-right: 1px solid $table-border-gray; + border-right: 1px solid $white-normal; &.old { background-color: $line-number-old; @@ -130,7 +130,7 @@ $highlighted-gc-bg: #eaf2f5; &.match { color: $black-transparent; - background-color: $match-line; + background-color: $gray-light; } } diff --git a/app/assets/stylesheets/pages/boards.scss b/app/assets/stylesheets/pages/boards.scss index 59ba0939785..c735f104c20 100644 --- a/app/assets/stylesheets/pages/boards.scss +++ b/app/assets/stylesheets/pages/boards.scss @@ -98,7 +98,7 @@ .board-inner { height: 100%; font-size: $issue-boards-font-size; - background: $background-color; + background: $gray-light; border: 1px solid $border-color; border-radius: $border-radius-default; } diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index e2d80723eff..66f7e7f97c8 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -42,7 +42,7 @@ } .environment-information { - background-color: $background-color; + background-color: $gray-light; border: 1px solid $border-color; padding: 12px $gl-padding; border-radius: $border-radius-default; diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss index c4ee9a51ed5..e76e1a73b25 100644 --- a/app/assets/stylesheets/pages/commits.scss +++ b/app/assets/stylesheets/pages/commits.scss @@ -7,7 +7,7 @@ .commit-header { padding: 5px 10px; - background-color: $background-color; + background-color: $gray-light; border-top: 1px solid $gray-darker; border-bottom: 1px solid $gray-darker; font-size: 14px; @@ -117,7 +117,7 @@ .commit-row-description { font-size: 14px; - border-left: 1px solid $btn-gray-hover; + border-left: 1px solid $white-normal; padding: 10px 15px; margin: 10px 0; background: $gray-light; diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss index 737f6e0f4be..f30795fd2c2 100644 --- a/app/assets/stylesheets/pages/diff.scss +++ b/app/assets/stylesheets/pages/diff.scss @@ -11,7 +11,7 @@ .diff-header { position: relative; - background: $background-color; + background: $gray-light; border-bottom: 1px solid $border-color; padding: 10px 16px; color: $gl-diff-text-color; @@ -38,7 +38,7 @@ cursor: pointer; &:hover { - background-color: $dark-background-color; + background-color: $gray-normal; } .diff-toggle-caret { @@ -187,8 +187,8 @@ img { border: 1px solid $white-light; - background-image: linear-gradient(45deg, $diff-image-img-bg 25%, transparent 25%, transparent 75%, $diff-image-img-bg 75%, $diff-image-img-bg 100%), - linear-gradient(45deg, $diff-image-img-bg 25%, transparent 25%, transparent 75%, $diff-image-img-bg 75%, $diff-image-img-bg 100%); + background-image: linear-gradient(45deg, $border-color 25%, transparent 25%, transparent 75%, $border-color 75%, $border-color 100%), + linear-gradient(45deg, $border-color 25%, transparent 25%, transparent 75%, $border-color 75%, $border-color 100%); background-size: 10px 10px; background-position: 0 0, 5px 5px; max-width: 100%; diff --git a/app/assets/stylesheets/pages/editor.scss b/app/assets/stylesheets/pages/editor.scss index 6cde9c592de..4b2e96dff8e 100644 --- a/app/assets/stylesheets/pages/editor.scss +++ b/app/assets/stylesheets/pages/editor.scss @@ -10,7 +10,7 @@ } .ace_gutter-cell { - background-color: $background-color; + background-color: $gray-light; } .cancel-btn { @@ -34,7 +34,7 @@ } .editor-ref { - background: $background-color; + background: $gray-light; padding-right: $gl-padding; border-right: 1px solid $border-color; display: block; diff --git a/app/assets/stylesheets/pages/events.scss b/app/assets/stylesheets/pages/events.scss index dc67d411c71..98925c2d0cb 100644 --- a/app/assets/stylesheets/pages/events.scss +++ b/app/assets/stylesheets/pages/events.scss @@ -5,7 +5,7 @@ .event-item { font-size: $gl-font-size; padding: $gl-padding-top 0 $gl-padding-top ($gl-avatar-size + $gl-padding-top); - border-bottom: 1px solid $table-border-color; + border-bottom: 1px solid $white-normal; color: $list-text-color; &.event-inline { diff --git a/app/assets/stylesheets/pages/help.scss b/app/assets/stylesheets/pages/help.scss index e2e644dc23b..dae8ccdef6c 100644 --- a/app/assets/stylesheets/pages/help.scss +++ b/app/assets/stylesheets/pages/help.scss @@ -60,7 +60,7 @@ // Border around images in the help pages. img:not(.emoji) { - border: 1px solid $table-border-gray; + border: 1px solid $white-normal; padding: 5px; margin: 5px; max-height: calc(100vh - 100px); diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 6ef7f9c2c1e..0234f2d49e7 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -7,7 +7,7 @@ // Border around images in issue and MR descriptions. .description img:not(.emoji) { - border: 1px solid $table-border-gray; + border: 1px solid $white-normal; padding: 5px; margin: 5px; max-height: calc(100vh - 100px); @@ -51,7 +51,7 @@ .block { @include clearfix; padding: $gl-padding 0; - border-bottom: 1px solid $border-gray-light; + border-bottom: 1px solid $border-gray-normal; // This prevents the mess when resizing the sidebar // of elements repositioning themselves.. width: $gutter_inner_width; @@ -178,7 +178,7 @@ .gutter-toggle { margin-top: 7px; - border-left: 1px solid $border-gray-light; + border-left: 1px solid $border-gray-normal; } .assignee .avatar { @@ -216,7 +216,7 @@ } .participants { - border-bottom: 1px solid $border-gray-light; + border-bottom: 1px solid $border-gray-normal; } .hide-collapsed { diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss index 3b47f99df2c..8734a3b1598 100644 --- a/app/assets/stylesheets/pages/issues.scss +++ b/app/assets/stylesheets/pages/issues.scss @@ -88,12 +88,12 @@ ul.related-merge-requests > li { &.closed { background: $gray-light; - border-color: $issues-border; + border-color: $border-color; } &.merged { background: $gray-light; - border-color: $issues-border; + border-color: $border-color; } } @@ -144,7 +144,7 @@ ul.related-merge-requests > li { } .btn { - background-color: $background-color; - border: 1px solid $border-gray-light; + background-color: $gray-light; + border: 1px solid $border-gray-normal; } } diff --git a/app/assets/stylesheets/pages/merge_conflicts.scss b/app/assets/stylesheets/pages/merge_conflicts.scss index 7a90713dd3f..5a9f199fb34 100644 --- a/app/assets/stylesheets/pages/merge_conflicts.scss +++ b/app/assets/stylesheets/pages/merge_conflicts.scss @@ -274,7 +274,7 @@ $colors: ( } .discard-changes-alert { - background-color: $background-color; + background-color: $gray-light; text-align: right; padding: $gl-padding-top $gl-padding; color: $gl-text-color; diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index 156724f44a8..e779e65eca3 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -3,7 +3,7 @@ * */ .mr-state-widget { - background: $background-color; + background: $gray-light; color: $gl-gray; border: 1px solid $border-color; border-radius: 2px; @@ -375,7 +375,7 @@ } .mr-version-controls { - background: $background-color; + background: $gray-light; border-bottom: 1px solid $border-color; color: $gl-text-color; diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss index 468f07d0534..074abec7692 100644 --- a/app/assets/stylesheets/pages/note_form.scss +++ b/app/assets/stylesheets/pages/note_form.scss @@ -62,7 +62,7 @@ .common-note-form { .md-area { padding: $gl-padding-top $gl-padding; - border: 1px solid $note-form-border-color; + border: 1px solid $border-color; border-radius: $border-radius-base; transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss index 0d4db14dafb..1b83b40486e 100644 --- a/app/assets/stylesheets/pages/notes.scss +++ b/app/assets/stylesheets/pages/notes.scss @@ -166,7 +166,7 @@ ul.notes { .note { display: block; position: relative; - border-bottom: 1px solid $table-border-gray; + border-bottom: 1px solid $white-normal; &.note-discussion { &.timeline-entry { @@ -291,14 +291,14 @@ ul.notes { font-family: $regular_font; td { - border: 1px solid $table-border-gray; + border: 1px solid $white-normal; border-left: none; &.notes_line { vertical-align: middle; text-align: center; padding: 10px 0; - background: $background-color; + background: $gray-light; color: $text-color; } @@ -309,7 +309,7 @@ ul.notes { } &.notes_content { - background-color: $background-color; + background-color: $gray-light; border-width: 1px 0; padding: 0; vertical-align: top; @@ -448,7 +448,7 @@ ul.notes { color: $notes-role-color; font-size: 12px; line-height: 20px; - border: 1px solid $notes-role-border-color; + border: 1px solid $border-color; border-radius: $border-radius-base; } @@ -529,7 +529,7 @@ ul.notes { .line-resolve-all { display: inline-block; padding: 5px 10px; - background-color: $background-color; + background-color: $gray-light; border: 1px solid $border-color; border-radius: $border-radius-default; diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index acc9dae4745..b9099cb6796 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -289,7 +289,7 @@ // Pipeline visualization .toggle-pipeline-btn { - background-color: $gray-dark; + background-color: $white-normal; &.graph-collapsed { background-color: $white-light; @@ -298,7 +298,7 @@ .pipeline-graph { width: 100%; - background-color: $background-color; + background-color: $gray-light; padding: $gl-padding; overflow: auto; white-space: nowrap; diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss index ffbda72b00e..8a5b0e20a86 100644 --- a/app/assets/stylesheets/pages/profile.scss +++ b/app/assets/stylesheets/pages/profile.scss @@ -60,8 +60,8 @@ .account-well { padding: 10px; - background-color: $help-well-bg; - border: 1px solid $help-well-border; + background-color: $gray-light; + border: 1px solid $border-color; border-radius: $border-radius-base; ul { @@ -136,7 +136,7 @@ .provider-btn-group { display: inline-block; margin-right: 10px; - border: 1px solid $provider-btn-group-border; + border: 1px solid $border-color; border-radius: 3px; &:last-child { @@ -147,7 +147,7 @@ .provider-btn-image { display: inline-block; padding: 5px 10px; - border-right: 1px solid $provider-btn-group-border; + border-right: 1px solid $border-color; > img { width: 20px; diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 6e0f6b1cd81..9c3dbc58ae0 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -420,13 +420,13 @@ a.deploy-project-label { width: 100px; height: 100px; background-color: $gray-light; - border: 1px solid $gray-dark; + border: 1px solid $white-normal; margin: 0 auto; border-radius: 50%; i { font-size: 100px; - color: $gray-dark; + color: $white-normal; } } @@ -536,7 +536,7 @@ a.deploy-project-label { } li.missing { - border: 1px dashed $border-gray-light; + border: 1px dashed $border-gray-normal; border-radius: $border-radius-default; a { @@ -591,7 +591,7 @@ pre.light-well { @include basic-list; .project-row { - border-color: $table-border-color; + border-color: $white-normal; .project-full-name { @include str-truncated; @@ -643,7 +643,7 @@ pre.light-well { &.container-fluid { padding-top: 12px; padding-bottom: 12px; - background-color: $background-color; + background-color: $gray-light; border: 1px solid $border-color; border-right-width: 0; border-left-width: 0; diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss index b027ace6a1f..cedd4cb2987 100644 --- a/app/assets/stylesheets/pages/search.scss +++ b/app/assets/stylesheets/pages/search.scss @@ -53,7 +53,7 @@ font-style: normal; color: $note-disabled-comment-color; display: inline-block; - background-color: $location-badge-bg; + background-color: $gray-normal; vertical-align: top; cursor: default; } diff --git a/app/assets/stylesheets/pages/snippets.scss b/app/assets/stylesheets/pages/snippets.scss index ff13b86acf0..a6037d76797 100644 --- a/app/assets/stylesheets/pages/snippets.scss +++ b/app/assets/stylesheets/pages/snippets.scss @@ -30,7 +30,7 @@ } .project-snippets .awards { - border-bottom: 1px solid $table-border-color; + border-bottom: 1px solid $white-normal; padding-bottom: $gl-padding; } diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss index 20ad63be045..c0341db7289 100644 --- a/app/assets/stylesheets/pages/tree.scss +++ b/app/assets/stylesheets/pages/tree.scss @@ -20,8 +20,8 @@ margin-bottom: 0; tr { - border-bottom: 1px solid $table-border-gray; - border-top: 1px solid $table-border-gray; + border-bottom: 1px solid $white-normal; + border-top: 1px solid $white-normal; td, th { @@ -39,7 +39,7 @@ .commit-history-link-spacer { margin: 0 10px; - color: $table-border-color; + color: $white-normal; } &:hover { @@ -53,7 +53,7 @@ &.selected { td { - background: $gray-dark; + background: $white-normal; border-top: 1px solid $border-gray-dark; border-bottom: 1px solid $border-gray-dark; } @@ -134,7 +134,7 @@ .blob-commit-info { list-style: none; padding: $gl-padding; - background: $background-color; + background: $gray-light; border: 1px solid $border-color; border-bottom: none; margin: 0; -- cgit v1.2.1 From 1fdd5d682368b6807b89e8a399d7751c519737bd Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Tue, 13 Dec 2016 19:21:30 +0000 Subject: Introduce $CI_BUILD_REF_SLUG --- app/models/ci/build.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'app') diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 88c46076df6..8a7c9e70dcf 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -184,6 +184,17 @@ module Ci project.build_timeout end + # A slugified version of the build ref, suitable for inclusion in URLs and + # domain names. Rules: + # + # * Lowercased + # * Anything not matching [a-z0-9-] is replaced with a - + # * Maximum length is 63 bytes + def ref_slug + slugified = ref.to_s.downcase + slugified.gsub(/[^a-z0-9]/, '-')[0..62] + end + def variables variables = predefined_variables variables += project.predefined_variables @@ -518,6 +529,7 @@ module Ci { key: 'CI_BUILD_REF', value: sha, public: true }, { key: 'CI_BUILD_BEFORE_SHA', value: before_sha, public: true }, { key: 'CI_BUILD_REF_NAME', value: ref, public: true }, + { key: 'CI_BUILD_REF_SLUG', value: ref_slug, public: true }, { key: 'CI_BUILD_NAME', value: name, public: true }, { key: 'CI_BUILD_STAGE', value: stage, public: true }, { key: 'CI_SERVER_NAME', value: 'GitLab', public: true }, -- cgit v1.2.1 From 01c8499a791a9179a0ae875ad26a1fa125e7fe4c Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Tue, 13 Dec 2016 22:37:16 +0000 Subject: Fix broken rspec tests --- app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 index 1c7fa994900..24640ba5fb8 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 @@ -18,7 +18,7 @@
    -- cgit v1.2.1 From 4d37b24614413e4f3e31d08296753fd07ec4bcad Mon Sep 17 00:00:00 2001 From: Jose Ivan Vargas Lopez Date: Mon, 28 Nov 2016 15:42:38 -0600 Subject: Fixed file template dropdown for the "New File" editor for smaller/zoomed screens --- app/assets/stylesheets/pages/editor.scss | 51 +++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/editor.scss b/app/assets/stylesheets/pages/editor.scss index 778126bcfb7..935f157b33d 100644 --- a/app/assets/stylesheets/pages/editor.scss +++ b/app/assets/stylesheets/pages/editor.scss @@ -51,8 +51,16 @@ .new-file-name { display: inline-block; - width: 450px; + max-width: 450px; float: left; + + @media(max-width: $screen-md-max) { + width: 280px; + } + + @media(max-width: $screen-sm-max) { + width: 180px; + } } .file-buttons { @@ -114,3 +122,44 @@ } } } + +@media(max-width: $screen-xs-max){ + .file-editor { + .file-title { + .pull-right { + height: auto; + } + } + + .new-file-name { + margin-bottom: 0; + max-width: none; + width: 100%; + } + + .file-buttons { + display: flex; + flex-direction: column; + width: 100%; + margin-bottom: 7px; + + .soft-wrap-toggle { + margin: 7px 0 0; + } + + .encoding-selector, + .license-selector, + .gitignore-selector, + .gitlab-ci-yml-selector { + margin: 7px 0 0; + + button { + width: 100%; + } + } + + } + + } + +} -- cgit v1.2.1 From 23f5865e184c1738df86893d31392faf4bc2bad7 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Tue, 13 Dec 2016 21:01:05 -0600 Subject: expand remaining non-explicit eslint-disable blocks and factor out globals when no-undef encountered --- app/assets/javascripts/abuse_reports.js.es6 | 3 +- app/assets/javascripts/blob/blob_ci_yaml.js.es6 | 4 ++- .../javascripts/blob/blob_license_selectors.js.es6 | 4 ++- .../javascripts/blob/template_selector.js.es6 | 3 +- app/assets/javascripts/boards/boards_bundle.js.es6 | 5 ++- .../javascripts/boards/components/board.js.es6 | 5 ++- .../boards/components/board_blank_state.js.es6 | 5 ++- .../boards/components/board_card.js.es6 | 4 ++- .../boards/components/board_delete.js.es6 | 4 ++- .../boards/components/board_list.js.es6 | 5 ++- .../boards/components/board_new_issue.js.es6 | 5 ++- .../boards/components/board_sidebar.js.es6 | 8 ++++- .../boards/components/new_list_dropdown.js.es6 | 11 +++--- .../boards/filters/due_date_filters.js.es6 | 3 +- .../boards/mixins/sortable_default_options.js.es6 | 4 ++- app/assets/javascripts/boards/models/issue.js.es6 | 7 +++- app/assets/javascripts/boards/models/label.js.es6 | 3 +- app/assets/javascripts/boards/models/list.js.es6 | 5 ++- .../javascripts/boards/models/milestone.js.es6 | 5 +-- app/assets/javascripts/boards/models/user.js.es6 | 5 +-- .../boards/services/board_service.js.es6 | 4 ++- .../javascripts/boards/stores/boards_store.js.es6 | 5 ++- .../boards/vue_resource_interceptor.js.es6 | 4 ++- app/assets/javascripts/build_variables.js.es6 | 3 +- app/assets/javascripts/compare_autocomplete.js.es6 | 3 +- app/assets/javascripts/create_label.js.es6 | 4 ++- .../components/comment_resolve_btn.js.es6 | 5 ++- .../components/jump_to_discussion.js.es6 | 6 +++- .../diff_notes/components/resolve_btn.js.es6 | 7 +++- .../diff_notes/components/resolve_count.js.es6 | 6 +++- .../components/resolve_discussion_btn.js.es6 | 6 +++- .../diff_notes/diff_notes_bundle.js.es6 | 5 ++- .../diff_notes/mixins/discussion.js.es6 | 3 +- .../diff_notes/models/discussion.js.es6 | 7 ++-- .../javascripts/diff_notes/models/note.js.es6 | 5 +-- .../javascripts/diff_notes/services/resolve.js.es6 | 6 +++- .../javascripts/diff_notes/stores/comments.js.es6 | 5 ++- app/assets/javascripts/dispatcher.js.es6 | 40 +++++++++++++++++++++- app/assets/javascripts/due_date_select.js.es6 | 3 +- app/assets/javascripts/gfm_auto_complete.js.es6 | 3 +- app/assets/javascripts/gl_field_errors.js.es6 | 2 +- .../javascripts/group_label_subscription.js.es6 | 3 +- app/assets/javascripts/issuable.js.es6 | 5 ++- .../javascripts/issues_bulk_assignment.js.es6 | 5 ++- app/assets/javascripts/label_manager.js.es6 | 5 +-- app/assets/javascripts/lib/ace.js | 1 - .../components/diff_file_editor.js.es6 | 6 +++- .../components/inline_conflict_lines.js.es6 | 4 ++- .../components/parallel_conflict_lines.js.es6 | 6 ++-- .../merge_conflicts/merge_conflict_service.js.es6 | 3 +- .../merge_conflicts/merge_conflict_store.js.es6 | 5 ++- .../merge_conflicts/merge_conflicts_bundle.js.es6 | 5 ++- .../mixins/line_conflict_actions.js.es6 | 3 +- .../mixins/line_conflict_utils.js.es6 | 3 +- app/assets/javascripts/merge_request_widget.js.es6 | 23 ++++++++----- app/assets/javascripts/pipelines.js.es6 | 3 +- app/assets/javascripts/profile/gl_crop.js.es6 | 3 +- app/assets/javascripts/profile/profile.js.es6 | 4 ++- .../javascripts/project_label_subscription.js.es6 | 3 +- .../protected_branch_access_dropdown.js.es6 | 3 +- .../protected_branch_create.js.es6 | 4 ++- .../protected_branch_dropdown.js.es6 | 3 +- .../protected_branch_edit.js.es6 | 6 ++-- .../protected_branch_edit_list.js.es6 | 3 +- .../protected_branches_bundle.js | 1 - app/assets/javascripts/search_autocomplete.js.es6 | 3 +- app/assets/javascripts/sidebar.js.es6 | 4 ++- app/assets/javascripts/snippets_list.js.es6 | 3 +- .../templates/issuable_template_selector.js.es6 | 4 ++- .../templates/issuable_template_selectors.js.es6 | 3 +- app/assets/javascripts/todos.js.es6 | 5 ++- app/assets/javascripts/user.js.es6 | 4 ++- app/assets/javascripts/user_tabs.js.es6 | 3 +- app/assets/javascripts/username_validator.js.es6 | 3 +- 74 files changed, 279 insertions(+), 93 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/abuse_reports.js.es6 b/app/assets/javascripts/abuse_reports.js.es6 index 82e526ae0ef..8a260aae1b1 100644 --- a/app/assets/javascripts/abuse_reports.js.es6 +++ b/app/assets/javascripts/abuse_reports.js.es6 @@ -1,4 +1,5 @@ -/* eslint-disable */ +/* eslint-disable no-param-reassign */ + ((global) => { const MAX_MESSAGE_LENGTH = 500; const MESSAGE_CELL_SELECTOR = '.abuse-reports .message'; diff --git a/app/assets/javascripts/blob/blob_ci_yaml.js.es6 b/app/assets/javascripts/blob/blob_ci_yaml.js.es6 index 37531aaec9b..57bd13eecf8 100644 --- a/app/assets/javascripts/blob/blob_ci_yaml.js.es6 +++ b/app/assets/javascripts/blob/blob_ci_yaml.js.es6 @@ -1,4 +1,6 @@ -/* eslint-disable */ +/* eslint-disable padded-blocks, no-param-reassign, comma-dangle */ +/* global Api */ + /*= require blob/template_selector */ ((global) => { diff --git a/app/assets/javascripts/blob/blob_license_selectors.js.es6 b/app/assets/javascripts/blob/blob_license_selectors.js.es6 index adeb8ba1318..268640681d4 100644 --- a/app/assets/javascripts/blob/blob_license_selectors.js.es6 +++ b/app/assets/javascripts/blob/blob_license_selectors.js.es6 @@ -1,4 +1,6 @@ -/* eslint-disable */ +/* eslint-disable no-unused-vars, no-param-reassign, padded-blocks */ +/* global BlobLicenseSelector */ + ((global) => { class BlobLicenseSelectors { constructor({ $dropdowns, editor }) { diff --git a/app/assets/javascripts/blob/template_selector.js.es6 b/app/assets/javascripts/blob/template_selector.js.es6 index 0ff5c0fab05..7a1ee9998c8 100644 --- a/app/assets/javascripts/blob/template_selector.js.es6 +++ b/app/assets/javascripts/blob/template_selector.js.es6 @@ -1,4 +1,5 @@ -/* eslint-disable */ +/* eslint-disable indent, comma-dangle, object-shorthand, func-names, space-before-function-paren, arrow-parens, no-unused-vars, class-methods-use-this, no-var, consistent-return, prefer-const, no-param-reassign, space-in-parens, max-len */ + ((global) => { class TemplateSelector { constructor({ dropdown, data, pattern, wrapper, editor, fileEndpoint, $input } = {}) { diff --git a/app/assets/javascripts/boards/boards_bundle.js.es6 b/app/assets/javascripts/boards/boards_bundle.js.es6 index 7ba918a05f8..ab2343c72fc 100644 --- a/app/assets/javascripts/boards/boards_bundle.js.es6 +++ b/app/assets/javascripts/boards/boards_bundle.js.es6 @@ -1,4 +1,7 @@ -/* eslint-disable */ +/* eslint-disable one-var, indent, quote-props, comma-dangle, space-before-function-paren */ +/* global Vue */ +/* global BoardService */ + //= require vue //= require vue-resource //= require Sortable diff --git a/app/assets/javascripts/boards/components/board.js.es6 b/app/assets/javascripts/boards/components/board.js.es6 index 31de3b25284..d1fb0ec48e0 100644 --- a/app/assets/javascripts/boards/components/board.js.es6 +++ b/app/assets/javascripts/boards/components/board.js.es6 @@ -1,4 +1,7 @@ -/* eslint-disable */ +/* eslint-disable comma-dangle, space-before-function-paren, one-var, indent, radix */ +/* global Vue */ +/* global Sortable */ + //= require ./board_blank_state //= require ./board_delete //= require ./board_list diff --git a/app/assets/javascripts/boards/components/board_blank_state.js.es6 b/app/assets/javascripts/boards/components/board_blank_state.js.es6 index 691487b272a..0a47a22fad2 100644 --- a/app/assets/javascripts/boards/components/board_blank_state.js.es6 +++ b/app/assets/javascripts/boards/components/board_blank_state.js.es6 @@ -1,4 +1,7 @@ -/* eslint-disable */ +/* eslint-disable space-before-function-paren, comma-dangle, semi */ +/* global Vue */ +/* global ListLabel */ + (() => { const Store = gl.issueBoards.BoardsStore; diff --git a/app/assets/javascripts/boards/components/board_card.js.es6 b/app/assets/javascripts/boards/components/board_card.js.es6 index 2299dafd217..5fc50280811 100644 --- a/app/assets/javascripts/boards/components/board_card.js.es6 +++ b/app/assets/javascripts/boards/components/board_card.js.es6 @@ -1,4 +1,6 @@ -/* eslint-disable */ +/* eslint-disable comma-dangle, space-before-function-paren, dot-notation */ +/* global Vue */ + (() => { const Store = gl.issueBoards.BoardsStore; diff --git a/app/assets/javascripts/boards/components/board_delete.js.es6 b/app/assets/javascripts/boards/components/board_delete.js.es6 index c45e1926c5c..861600424a5 100644 --- a/app/assets/javascripts/boards/components/board_delete.js.es6 +++ b/app/assets/javascripts/boards/components/board_delete.js.es6 @@ -1,4 +1,6 @@ -/* eslint-disable */ +/* eslint-disable comma-dangle, space-before-function-paren, no-alert */ +/* global Vue */ + (() => { window.gl = window.gl || {}; window.gl.issueBoards = window.gl.issueBoards || {}; diff --git a/app/assets/javascripts/boards/components/board_list.js.es6 b/app/assets/javascripts/boards/components/board_list.js.es6 index 43ebeef39c4..6711930622b 100644 --- a/app/assets/javascripts/boards/components/board_list.js.es6 +++ b/app/assets/javascripts/boards/components/board_list.js.es6 @@ -1,4 +1,7 @@ -/* eslint-disable */ +/* eslint-disable comma-dangle, space-before-function-paren, max-len, no-plusplus */ +/* global Vue */ +/* global Sortable */ + //= require ./board_card //= require ./board_new_issue diff --git a/app/assets/javascripts/boards/components/board_new_issue.js.es6 b/app/assets/javascripts/boards/components/board_new_issue.js.es6 index a7989a2ff4c..2386d3a613c 100644 --- a/app/assets/javascripts/boards/components/board_new_issue.js.es6 +++ b/app/assets/javascripts/boards/components/board_new_issue.js.es6 @@ -1,4 +1,7 @@ -/* eslint-disable */ +/* eslint-disable comma-dangle, no-unused-vars */ +/* global Vue */ +/* global ListIssue */ + (() => { const Store = gl.issueBoards.BoardsStore; diff --git a/app/assets/javascripts/boards/components/board_sidebar.js.es6 b/app/assets/javascripts/boards/components/board_sidebar.js.es6 index 1644a772737..02459722bbf 100644 --- a/app/assets/javascripts/boards/components/board_sidebar.js.es6 +++ b/app/assets/javascripts/boards/components/board_sidebar.js.es6 @@ -1,4 +1,10 @@ -/* eslint-disable */ +/* eslint-disable comma-dangle, space-before-function-paren, no-new */ +/* global Vue */ +/* global IssuableContext */ +/* global MilestoneSelect */ +/* global LabelsSelect */ +/* global Sidebar */ + (() => { const Store = gl.issueBoards.BoardsStore; diff --git a/app/assets/javascripts/boards/components/new_list_dropdown.js.es6 b/app/assets/javascripts/boards/components/new_list_dropdown.js.es6 index 10ce746deb5..3f5cf8420a8 100644 --- a/app/assets/javascripts/boards/components/new_list_dropdown.js.es6 +++ b/app/assets/javascripts/boards/components/new_list_dropdown.js.es6 @@ -1,4 +1,5 @@ -/* eslint-disable */ +/* eslint-disable comma-dangle, func-names, no-new, space-before-function-paren, one-var, indent */ + (() => { window.gl = window.gl || {}; window.gl.issueBoards = window.gl.issueBoards || {}; @@ -45,10 +46,10 @@ return $li.append($a.prepend($labelColor)); }, - search: { - fields: ['title'] - }, - filterable: true, + search: { + fields: ['title'] + }, + filterable: true, selectable: true, multiSelect: true, clicked (label, $el, e) { diff --git a/app/assets/javascripts/boards/filters/due_date_filters.js.es6 b/app/assets/javascripts/boards/filters/due_date_filters.js.es6 index 9eceac4eddd..7e192e90fe6 100644 --- a/app/assets/javascripts/boards/filters/due_date_filters.js.es6 +++ b/app/assets/javascripts/boards/filters/due_date_filters.js.es6 @@ -1,4 +1,5 @@ -/* eslint-disable */ +/* global Vue */ + Vue.filter('due-date', (value) => { const date = new Date(value); return $.datepicker.formatDate('M d, yy', date); diff --git a/app/assets/javascripts/boards/mixins/sortable_default_options.js.es6 b/app/assets/javascripts/boards/mixins/sortable_default_options.js.es6 index 5f99de39122..a5e62ed775d 100644 --- a/app/assets/javascripts/boards/mixins/sortable_default_options.js.es6 +++ b/app/assets/javascripts/boards/mixins/sortable_default_options.js.es6 @@ -1,4 +1,6 @@ -/* eslint-disable */ +/* eslint-disable no-unused-vars, no-mixed-operators, prefer-const, comma-dangle, semi */ +/* global DocumentTouch */ + ((w) => { window.gl = window.gl || {}; window.gl.issueBoards = window.gl.issueBoards || {}; diff --git a/app/assets/javascripts/boards/models/issue.js.es6 b/app/assets/javascripts/boards/models/issue.js.es6 index 21d735e8231..1199e022ff1 100644 --- a/app/assets/javascripts/boards/models/issue.js.es6 +++ b/app/assets/javascripts/boards/models/issue.js.es6 @@ -1,4 +1,9 @@ -/* eslint-disable */ +/* eslint-disable no-unused-vars, space-before-function-paren, arrow-body-style, space-in-parens, arrow-parens, comma-dangle, max-len */ +/* global Vue */ +/* global ListLabel */ +/* global ListMilestone */ +/* global ListUser */ + class ListIssue { constructor (obj) { this.id = obj.iid; diff --git a/app/assets/javascripts/boards/models/label.js.es6 b/app/assets/javascripts/boards/models/label.js.es6 index 0910fe9a854..8f20a1bbec7 100644 --- a/app/assets/javascripts/boards/models/label.js.es6 +++ b/app/assets/javascripts/boards/models/label.js.es6 @@ -1,4 +1,5 @@ -/* eslint-disable */ +/* eslint-disable no-unused-vars, space-before-function-paren */ + class ListLabel { constructor (obj) { this.id = obj.id; diff --git a/app/assets/javascripts/boards/models/list.js.es6 b/app/assets/javascripts/boards/models/list.js.es6 index 429bd27c3fb..a8d38c16485 100644 --- a/app/assets/javascripts/boards/models/list.js.es6 +++ b/app/assets/javascripts/boards/models/list.js.es6 @@ -1,4 +1,7 @@ -/* eslint-disable */ +/* eslint-disable space-before-function-paren, no-underscore-dangle, class-methods-use-this, consistent-return, no-plusplus, prefer-const, space-in-parens, no-shadow, no-param-reassign, max-len, no-unused-vars */ +/* global ListIssue */ +/* global ListLabel */ + class List { constructor (obj) { this.id = obj.id; diff --git a/app/assets/javascripts/boards/models/milestone.js.es6 b/app/assets/javascripts/boards/models/milestone.js.es6 index a48969e19c9..9c173c1b70b 100644 --- a/app/assets/javascripts/boards/models/milestone.js.es6 +++ b/app/assets/javascripts/boards/models/milestone.js.es6 @@ -1,6 +1,7 @@ -/* eslint-disable */ +/* eslint-disable no-unused-vars */ + class ListMilestone { - constructor (obj) { + constructor(obj) { this.id = obj.id; this.title = obj.title; } diff --git a/app/assets/javascripts/boards/models/user.js.es6 b/app/assets/javascripts/boards/models/user.js.es6 index 583a973fc46..a8a3892e2ad 100644 --- a/app/assets/javascripts/boards/models/user.js.es6 +++ b/app/assets/javascripts/boards/models/user.js.es6 @@ -1,6 +1,7 @@ -/* eslint-disable */ +/* eslint-disable no-unused-vars */ + class ListUser { - constructor (user) { + constructor(user) { this.id = user.id; this.name = user.name; this.username = user.username; diff --git a/app/assets/javascripts/boards/services/board_service.js.es6 b/app/assets/javascripts/boards/services/board_service.js.es6 index f59a2ed7937..189a8703198 100644 --- a/app/assets/javascripts/boards/services/board_service.js.es6 +++ b/app/assets/javascripts/boards/services/board_service.js.es6 @@ -1,4 +1,6 @@ -/* eslint-disable */ +/* eslint-disable space-before-function-paren, comma-dangle, no-param-reassign, camelcase, prefer-const, no-extra-semi, max-len, no-unused-vars */ +/* global Vue */ + class BoardService { constructor (root, boardId) { this.lists = Vue.resource(`${root}/${boardId}/lists{/id}`, {}, { diff --git a/app/assets/javascripts/boards/stores/boards_store.js.es6 b/app/assets/javascripts/boards/stores/boards_store.js.es6 index bb2a4de8b18..e7a14ea5bca 100644 --- a/app/assets/javascripts/boards/stores/boards_store.js.es6 +++ b/app/assets/javascripts/boards/stores/boards_store.js.es6 @@ -1,4 +1,7 @@ -/* eslint-disable */ +/* eslint-disable comma-dangle, space-before-function-paren, one-var, indent, space-in-parens, no-shadow, radix, dot-notation, semi, max-len */ +/* global Cookies */ +/* global List */ + (() => { window.gl = window.gl || {}; window.gl.issueBoards = window.gl.issueBoards || {}; diff --git a/app/assets/javascripts/boards/vue_resource_interceptor.js.es6 b/app/assets/javascripts/boards/vue_resource_interceptor.js.es6 index 80f137ca12e..3723a2039f9 100644 --- a/app/assets/javascripts/boards/vue_resource_interceptor.js.es6 +++ b/app/assets/javascripts/boards/vue_resource_interceptor.js.es6 @@ -1,4 +1,6 @@ -/* eslint-disable */ +/* eslint-disable func-names, prefer-arrow-callback, no-unused-vars, no-plusplus */ +/* global Vue */ + Vue.http.interceptors.push((request, next) => { Vue.activeResources = Vue.activeResources ? Vue.activeResources + 1 : 1; diff --git a/app/assets/javascripts/build_variables.js.es6 b/app/assets/javascripts/build_variables.js.es6 index 0ecd20bc11e..993424d422f 100644 --- a/app/assets/javascripts/build_variables.js.es6 +++ b/app/assets/javascripts/build_variables.js.es6 @@ -1,4 +1,5 @@ -/* eslint-disable */ +/* eslint-disable func-names, prefer-arrow-callback, space-before-blocks, space-before-function-paren, comma-spacing, max-len */ + $(function(){ $('.reveal-variables').off('click').on('click',function(){ $('.js-build').toggle().niceScroll(); diff --git a/app/assets/javascripts/compare_autocomplete.js.es6 b/app/assets/javascripts/compare_autocomplete.js.es6 index bd980f87e72..45c974b2b68 100644 --- a/app/assets/javascripts/compare_autocomplete.js.es6 +++ b/app/assets/javascripts/compare_autocomplete.js.es6 @@ -1,4 +1,5 @@ -/* eslint-disable */ +/* eslint-disable func-names, space-before-function-paren, one-var, no-var, one-var-declaration-per-line, object-shorthand, comma-dangle, prefer-arrow-callback, no-else-return, newline-per-chained-call, no-dupe-keys, wrap-iife, padded-blocks, max-len */ + (function() { this.CompareAutocomplete = (function() { function CompareAutocomplete() { diff --git a/app/assets/javascripts/create_label.js.es6 b/app/assets/javascripts/create_label.js.es6 index 744aa0afa03..947c129d5b5 100644 --- a/app/assets/javascripts/create_label.js.es6 +++ b/app/assets/javascripts/create_label.js.es6 @@ -1,4 +1,6 @@ -/* eslint-disable */ +/* eslint-disable func-names, space-before-function-paren, prefer-arrow-callback, comma-dangle, prefer-template, quotes, no-param-reassign, wrap-iife, max-len */ +/* global Api */ + (function (w) { class CreateLabelDropdown { constructor ($el, namespacePath, projectPath) { diff --git a/app/assets/javascripts/diff_notes/components/comment_resolve_btn.js.es6 b/app/assets/javascripts/diff_notes/components/comment_resolve_btn.js.es6 index 52e2846d279..c59d3996fab 100644 --- a/app/assets/javascripts/diff_notes/components/comment_resolve_btn.js.es6 +++ b/app/assets/javascripts/diff_notes/components/comment_resolve_btn.js.es6 @@ -1,4 +1,7 @@ -/* eslint-disable */ +/* eslint-disable comma-dangle, object-shorthand, func-names, no-else-return, quotes, no-lonely-if, semi, max-len */ +/* global Vue */ +/* global CommentsStore */ + (() => { const CommentAndResolveBtn = Vue.extend({ props: { diff --git a/app/assets/javascripts/diff_notes/components/jump_to_discussion.js.es6 b/app/assets/javascripts/diff_notes/components/jump_to_discussion.js.es6 index 983e554b9c1..fd1d1cad272 100644 --- a/app/assets/javascripts/diff_notes/components/jump_to_discussion.js.es6 +++ b/app/assets/javascripts/diff_notes/components/jump_to_discussion.js.es6 @@ -1,4 +1,8 @@ -/* eslint-disable */ +/* eslint-disable comma-dangle, object-shorthand, func-names, no-else-return, guard-for-in, no-restricted-syntax, one-var, indent, space-before-function-paren, no-plusplus, no-lonely-if, no-continue, brace-style, max-len, quotes, no-undef, semi */ +/* global Vue */ +/* global DiscussionMixins */ +/* global CommentsStore */ + (() => { JumpToDiscussion = Vue.extend({ mixins: [DiscussionMixins], diff --git a/app/assets/javascripts/diff_notes/components/resolve_btn.js.es6 b/app/assets/javascripts/diff_notes/components/resolve_btn.js.es6 index 27af9fc96ad..88a19fc6e1d 100644 --- a/app/assets/javascripts/diff_notes/components/resolve_btn.js.es6 +++ b/app/assets/javascripts/diff_notes/components/resolve_btn.js.es6 @@ -1,4 +1,9 @@ -/* eslint-disable */ +/* eslint-disable comma-dangle, object-shorthand, func-names, quote-props, no-else-return, camelcase, no-new, max-len */ +/* global Vue */ +/* global CommentsStore */ +/* global ResolveService */ +/* global Flash */ + (() => { const ResolveBtn = Vue.extend({ props: { diff --git a/app/assets/javascripts/diff_notes/components/resolve_count.js.es6 b/app/assets/javascripts/diff_notes/components/resolve_count.js.es6 index 9522ccb49da..72cdae812bc 100644 --- a/app/assets/javascripts/diff_notes/components/resolve_count.js.es6 +++ b/app/assets/javascripts/diff_notes/components/resolve_count.js.es6 @@ -1,4 +1,8 @@ -/* eslint-disable */ +/* eslint-disable comma-dangle, object-shorthand, func-names, no-param-reassign */ +/* global Vue */ +/* global DiscussionMixins */ +/* global CommentsStore */ + ((w) => { w.ResolveCount = Vue.extend({ mixins: [DiscussionMixins], diff --git a/app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js.es6 b/app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js.es6 index b945a09fcbe..ee5f62b2d9e 100644 --- a/app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js.es6 +++ b/app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js.es6 @@ -1,4 +1,8 @@ -/* eslint-disable */ +/* eslint-disable object-shorthand, func-names, space-before-function-paren, comma-dangle, no-else-return, quotes, max-len */ +/* global Vue */ +/* global CommentsStore */ +/* global ResolveService */ + (() => { const ResolveDiscussionBtn = Vue.extend({ props: { diff --git a/app/assets/javascripts/diff_notes/diff_notes_bundle.js.es6 b/app/assets/javascripts/diff_notes/diff_notes_bundle.js.es6 index bd4c20aed8b..840b5aa922e 100644 --- a/app/assets/javascripts/diff_notes/diff_notes_bundle.js.es6 +++ b/app/assets/javascripts/diff_notes/diff_notes_bundle.js.es6 @@ -1,4 +1,7 @@ -/* eslint-disable */ +/* eslint-disable func-names, comma-dangle, new-cap, no-new */ +/* global Vue */ +/* global ResolveCount */ + //= require vue //= require vue-resource //= require_directory ./models diff --git a/app/assets/javascripts/diff_notes/mixins/discussion.js.es6 b/app/assets/javascripts/diff_notes/mixins/discussion.js.es6 index 7a929017f36..a9ea18bf82b 100644 --- a/app/assets/javascripts/diff_notes/mixins/discussion.js.es6 +++ b/app/assets/javascripts/diff_notes/mixins/discussion.js.es6 @@ -1,4 +1,5 @@ -/* eslint-disable */ +/* eslint-disable object-shorthand, func-names, guard-for-in, no-restricted-syntax, comma-dangle, no-plusplus, no-param-reassign, max-len */ + ((w) => { w.DiscussionMixins = { computed: { diff --git a/app/assets/javascripts/diff_notes/models/discussion.js.es6 b/app/assets/javascripts/diff_notes/models/discussion.js.es6 index badcdccc840..efcd46680a7 100644 --- a/app/assets/javascripts/diff_notes/models/discussion.js.es6 +++ b/app/assets/javascripts/diff_notes/models/discussion.js.es6 @@ -1,4 +1,7 @@ -/* eslint-disable */ +/* eslint-disable space-before-function-paren, camelcase, guard-for-in, no-restricted-syntax, no-unused-vars, max-len */ +/* global Vue */ +/* global NoteModel */ + class DiscussionModel { constructor (discussionId) { this.id = discussionId; @@ -69,7 +72,7 @@ class DiscussionModel { gl.utils.localTimeAgo($('.js-timeago', `${discussionSelector}`)); } else { - $discussionHeadline.remove(); + $discussionHeadline.remove(); } } diff --git a/app/assets/javascripts/diff_notes/models/note.js.es6 b/app/assets/javascripts/diff_notes/models/note.js.es6 index d0541b02632..e3bce1d2038 100644 --- a/app/assets/javascripts/diff_notes/models/note.js.es6 +++ b/app/assets/javascripts/diff_notes/models/note.js.es6 @@ -1,6 +1,7 @@ -/* eslint-disable */ +/* eslint-disable camelcase, no-unused-vars */ + class NoteModel { - constructor (discussionId, noteId, canResolve, resolved, resolved_by) { + constructor(discussionId, noteId, canResolve, resolved, resolved_by) { this.discussionId = discussionId; this.id = noteId; this.canResolve = canResolve; diff --git a/app/assets/javascripts/diff_notes/services/resolve.js.es6 b/app/assets/javascripts/diff_notes/services/resolve.js.es6 index 86953ce7ffb..78c74985f78 100644 --- a/app/assets/javascripts/diff_notes/services/resolve.js.es6 +++ b/app/assets/javascripts/diff_notes/services/resolve.js.es6 @@ -1,4 +1,8 @@ -/* eslint-disable */ +/* eslint-disable class-methods-use-this, one-var, indent, camelcase, no-new, comma-dangle, semi, no-param-reassign, max-len */ +/* global Vue */ +/* global Flash */ +/* global CommentsStore */ + ((w) => { class ResolveServiceClass { constructor() { diff --git a/app/assets/javascripts/diff_notes/stores/comments.js.es6 b/app/assets/javascripts/diff_notes/stores/comments.js.es6 index f42ca406bb1..1a7abbc6f75 100644 --- a/app/assets/javascripts/diff_notes/stores/comments.js.es6 +++ b/app/assets/javascripts/diff_notes/stores/comments.js.es6 @@ -1,4 +1,7 @@ -/* eslint-disable */ +/* eslint-disable object-shorthand, func-names, camelcase, prefer-const, no-restricted-syntax, guard-for-in, comma-dangle, max-len, no-param-reassign */ +/* global Vue */ +/* global DiscussionModel */ + ((w) => { w.CommentsStore = { state: {}, diff --git a/app/assets/javascripts/dispatcher.js.es6 b/app/assets/javascripts/dispatcher.js.es6 index 413117c2226..7d588e8eee6 100644 --- a/app/assets/javascripts/dispatcher.js.es6 +++ b/app/assets/javascripts/dispatcher.js.es6 @@ -1,4 +1,42 @@ -/* eslint-disable */ +/* eslint-disable func-names, space-before-function-paren, no-var, prefer-arrow-callback, wrap-iife, no-shadow, consistent-return, one-var, one-var-declaration-per-line, camelcase, default-case, no-new, quotes, no-duplicate-case, no-case-declarations, no-fallthrough, max-len, padded-blocks */ +/* global UsernameValidator */ +/* global ActiveTabMemoizer */ +/* global ShortcutsNavigation */ +/* global Build */ +/* global Issuable */ +/* global Issue */ +/* global ShortcutsIssuable */ +/* global ZenMode */ +/* global Milestone */ +/* global GLForm */ +/* global IssuableForm */ +/* global LabelsSelect */ +/* global MilestoneSelect */ +/* global MergedButtons */ +/* global Commit */ +/* global NotificationsForm */ +/* global TreeView */ +/* global NotificationsDropdown */ +/* global UsersSelect */ +/* global GroupAvatar */ +/* global LineHighlighter */ +/* global ShortcutsBlob */ +/* global ProjectFork */ +/* global BuildArtifacts */ +/* global GroupsSelect */ +/* global Search */ +/* global Admin */ +/* global NamespaceSelects */ +/* global ShortcutsDashboardNavigation */ +/* global Project */ +/* global ProjectAvatar */ +/* global CompareAutocomplete */ +/* global ProjectNew */ +/* global Star */ +/* global ProjectShow */ +/* global Labels */ +/* global Shortcuts */ + (function() { var Dispatcher; diff --git a/app/assets/javascripts/due_date_select.js.es6 b/app/assets/javascripts/due_date_select.js.es6 index e84f5ac9183..2b7d57d86c6 100644 --- a/app/assets/javascripts/due_date_select.js.es6 +++ b/app/assets/javascripts/due_date_select.js.es6 @@ -1,4 +1,5 @@ -/* eslint-disable */ +/* eslint-disable wrap-iife, func-names, space-before-function-paren, comma-dangle, prefer-template, consistent-return, class-methods-use-this, arrow-body-style, prefer-const, padded-blocks, no-unused-vars, no-underscore-dangle, no-new, max-len, semi, no-sequences, no-unused-expressions, no-param-reassign */ + (function(global) { class DueDateSelect { constructor({ $dropdown, $loading } = {}) { diff --git a/app/assets/javascripts/gfm_auto_complete.js.es6 b/app/assets/javascripts/gfm_auto_complete.js.es6 index 2f3da745119..79501aa4ab9 100644 --- a/app/assets/javascripts/gfm_auto_complete.js.es6 +++ b/app/assets/javascripts/gfm_auto_complete.js.es6 @@ -1,4 +1,5 @@ -/* eslint-disable */ +/* eslint-disable func-names, space-before-function-paren, no-template-curly-in-string, comma-dangle, object-shorthand, quotes, dot-notation, no-else-return, one-var, no-var, no-underscore-dangle, one-var-declaration-per-line, no-param-reassign, no-useless-escape, prefer-template, consistent-return, wrap-iife, prefer-arrow-callback, camelcase, no-unused-vars, no-useless-return, padded-blocks, vars-on-top, indent, no-extra-semi, no-multi-spaces, semi, no-undef, max-len */ + // Creates the variables for setting up GFM auto-completion (function() { if (window.GitLab == null) { diff --git a/app/assets/javascripts/gl_field_errors.js.es6 b/app/assets/javascripts/gl_field_errors.js.es6 index 6ce392d2a5b..63f9cafa8d0 100644 --- a/app/assets/javascripts/gl_field_errors.js.es6 +++ b/app/assets/javascripts/gl_field_errors.js.es6 @@ -1,4 +1,4 @@ -/* eslint-disable */ +/* eslint-disable comma-dangle, class-methods-use-this, max-len, space-before-function-paren, arrow-parens, no-param-reassign, padded-blocks */ //= require gl_field_error diff --git a/app/assets/javascripts/group_label_subscription.js.es6 b/app/assets/javascripts/group_label_subscription.js.es6 index eea6cd40859..8e10e424412 100644 --- a/app/assets/javascripts/group_label_subscription.js.es6 +++ b/app/assets/javascripts/group_label_subscription.js.es6 @@ -1,4 +1,5 @@ -/* eslint-disable */ +/* eslint-disable func-names, object-shorthand, comma-dangle, wrap-iife, space-before-function-paren, no-param-reassign, padded-blocks, max-len */ + (function(global) { class GroupLabelSubscription { constructor(container) { diff --git a/app/assets/javascripts/issuable.js.es6 b/app/assets/javascripts/issuable.js.es6 index 46503c290ae..b174eb2ff96 100644 --- a/app/assets/javascripts/issuable.js.es6 +++ b/app/assets/javascripts/issuable.js.es6 @@ -1,4 +1,7 @@ -/* eslint-disable */ +/* eslint-disable func-names, no-var, camelcase, no-unused-vars, object-shorthand, space-before-function-paren, no-return-assign, comma-dangle, consistent-return, one-var, one-var-declaration-per-line, quotes, prefer-template, prefer-arrow-callback, prefer-const, padded-blocks, wrap-iife, max-len */ +/* global Issuable */ +/* global Turbolinks */ + (function() { var issuable_created; diff --git a/app/assets/javascripts/issues_bulk_assignment.js.es6 b/app/assets/javascripts/issues_bulk_assignment.js.es6 index 9697fb33566..ad25104152c 100644 --- a/app/assets/javascripts/issues_bulk_assignment.js.es6 +++ b/app/assets/javascripts/issues_bulk_assignment.js.es6 @@ -1,4 +1,7 @@ -/* eslint-disable */ +/* eslint-disable comma-dangle, quotes, consistent-return, func-names, array-callback-return, space-before-function-paren, prefer-arrow-callback, radix, max-len, padded-blocks, no-unused-expressions, no-sequences, no-underscore-dangle, no-unused-vars, no-param-reassign */ +/* global Issuable */ +/* global Flash */ + ((global) => { class IssuableBulkActions { diff --git a/app/assets/javascripts/label_manager.js.es6 b/app/assets/javascripts/label_manager.js.es6 index 175623e7448..33c5e35324d 100644 --- a/app/assets/javascripts/label_manager.js.es6 +++ b/app/assets/javascripts/label_manager.js.es6 @@ -1,4 +1,6 @@ -/* eslint-disable */ +/* eslint-disable comma-dangle, class-methods-use-this, no-underscore-dangle, no-param-reassign, no-unused-vars, consistent-return, func-names, space-before-function-paren, padded-blocks, max-len */ +/* global Flash */ + ((global) => { class LabelManager { @@ -104,4 +106,3 @@ gl.LabelManager = LabelManager; })(window.gl || (window.gl = {})); - diff --git a/app/assets/javascripts/lib/ace.js b/app/assets/javascripts/lib/ace.js index b1718e89d3d..4cdf99cae72 100644 --- a/app/assets/javascripts/lib/ace.js +++ b/app/assets/javascripts/lib/ace.js @@ -1,3 +1,2 @@ -/* eslint-disable */ /*= require ace-rails-ap */ /*= require ace/ext-searchbox */ diff --git a/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js.es6 b/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js.es6 index 9e4ffd07dbd..f95b079c972 100644 --- a/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js.es6 +++ b/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js.es6 @@ -1,4 +1,8 @@ -/* eslint-disable */ +/* eslint-disable comma-dangle, quote-props, no-useless-computed-key, object-shorthand, prefer-const, no-new, padded-blocks, no-param-reassign, semi, max-len */ +/* global Vue */ +/* global ace */ +/* global Flash */ + ((global) => { global.mergeConflicts = global.mergeConflicts || {}; diff --git a/app/assets/javascripts/merge_conflicts/components/inline_conflict_lines.js.es6 b/app/assets/javascripts/merge_conflicts/components/inline_conflict_lines.js.es6 index 23c4618af70..74544b7d0c7 100644 --- a/app/assets/javascripts/merge_conflicts/components/inline_conflict_lines.js.es6 +++ b/app/assets/javascripts/merge_conflicts/components/inline_conflict_lines.js.es6 @@ -1,4 +1,6 @@ -/* eslint-disable */ +/* eslint-disable padded-blocks, no-param-reassign, comma-dangle */ +/* global Vue */ + ((global) => { global.mergeConflicts = global.mergeConflicts || {}; diff --git a/app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js.es6 b/app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js.es6 index 4ccbdcd6daa..78c00c31c16 100644 --- a/app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js.es6 +++ b/app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js.es6 @@ -1,4 +1,6 @@ -/* eslint-disable */ +/* eslint-disable padded-blocks, no-param-reassign, comma-dangle */ +/* global Vue */ + ((global) => { global.mergeConflicts = global.mergeConflicts || {}; @@ -19,7 +21,7 @@ {{line.lineNumber}} - + `, diff --git a/app/assets/javascripts/merge_conflicts/merge_conflict_service.js.es6 b/app/assets/javascripts/merge_conflicts/merge_conflict_service.js.es6 index 8a7519b0786..8df3170edac 100644 --- a/app/assets/javascripts/merge_conflicts/merge_conflict_service.js.es6 +++ b/app/assets/javascripts/merge_conflicts/merge_conflict_service.js.es6 @@ -1,4 +1,5 @@ -/* eslint-disable */ +/* eslint-disable no-param-reassign, comma-dangle, no-extra-semi, padded-blocks */ + ((global) => { global.mergeConflicts = global.mergeConflicts || {}; diff --git a/app/assets/javascripts/merge_conflicts/merge_conflict_store.js.es6 b/app/assets/javascripts/merge_conflicts/merge_conflict_store.js.es6 index f94e51e783c..53b44007510 100644 --- a/app/assets/javascripts/merge_conflicts/merge_conflict_store.js.es6 +++ b/app/assets/javascripts/merge_conflicts/merge_conflict_store.js.es6 @@ -1,4 +1,7 @@ -/* eslint-disable */ +/* eslint-disable comma-dangle, object-shorthand, no-dupe-keys, no-param-reassign, no-plusplus, camelcase, prefer-const, no-nested-ternary, no-continue, semi, func-call-spacing, no-spaced-func, padded-blocks, max-len */ +/* global Cookies */ +/* global Vue */ + ((global) => { global.mergeConflicts = global.mergeConflicts || {}; diff --git a/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js.es6 b/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js.es6 index 815443fb54e..83520702f9b 100644 --- a/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js.es6 +++ b/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js.es6 @@ -1,4 +1,7 @@ -/* eslint-disable */ +/* eslint-disable new-cap, comma-dangle, no-new, semi */ +/* global Vue */ +/* global Flash */ + //= require vue //= require ./merge_conflict_store //= require ./merge_conflict_service diff --git a/app/assets/javascripts/merge_conflicts/mixins/line_conflict_actions.js.es6 b/app/assets/javascripts/merge_conflicts/mixins/line_conflict_actions.js.es6 index c8de586aa21..e89b35d5407 100644 --- a/app/assets/javascripts/merge_conflicts/mixins/line_conflict_actions.js.es6 +++ b/app/assets/javascripts/merge_conflicts/mixins/line_conflict_actions.js.es6 @@ -1,4 +1,5 @@ -/* eslint-disable */ +/* eslint-disable no-param-reassign, comma-dangle, padded-blocks */ + ((global) => { global.mergeConflicts = global.mergeConflicts || {}; diff --git a/app/assets/javascripts/merge_conflicts/mixins/line_conflict_utils.js.es6 b/app/assets/javascripts/merge_conflicts/mixins/line_conflict_utils.js.es6 index 88c3a20ce13..a4aca85d460 100644 --- a/app/assets/javascripts/merge_conflicts/mixins/line_conflict_utils.js.es6 +++ b/app/assets/javascripts/merge_conflicts/mixins/line_conflict_utils.js.es6 @@ -1,4 +1,5 @@ -/* eslint-disable */ +/* eslint-disable no-param-reassign, quote-props, comma-dangle, padded-blocks */ + ((global) => { global.mergeConflicts = global.mergeConflicts || {}; diff --git a/app/assets/javascripts/merge_request_widget.js.es6 b/app/assets/javascripts/merge_request_widget.js.es6 index 7022aa1263b..e47047c4cca 100644 --- a/app/assets/javascripts/merge_request_widget.js.es6 +++ b/app/assets/javascripts/merge_request_widget.js.es6 @@ -1,5 +1,10 @@ -/* eslint-disable */ - ((global) => { +/* eslint-disable max-len, no-var, func-names, space-before-function-paren, vars-on-top, no-plusplus, comma-dangle, no-return-assign, consistent-return, no-param-reassign, one-var, one-var-declaration-per-line, quotes, prefer-template, no-else-return, prefer-arrow-callback, no-unused-vars, no-underscore-dangle, no-shadow, no-mixed-operators, template-curly-spacing, camelcase, default-case, wrap-iife, semi, padded-blocks */ +/* global notify */ +/* global notifyPermissions */ +/* global merge_request_widget */ +/* global Turbolinks */ + +((global) => { var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; const DEPLOYMENT_TEMPLATE = `
    @@ -27,7 +32,7 @@
    `; - global.MergeRequestWidget = (function() { + global.MergeRequestWidget = (function() { function MergeRequestWidget(opts) { // Initialize MergeRequestWidget behavior // @@ -82,10 +87,10 @@ }; MergeRequestWidget.prototype.retrieveSuccessIcon = function() { - const $ciSuccessIcon = $('.js-success-icon'); - this.$ciSuccessIcon = $ciSuccessIcon.html(); - $ciSuccessIcon.remove(); - } + const $ciSuccessIcon = $('.js-success-icon'); + this.$ciSuccessIcon = $ciSuccessIcon.html(); + $ciSuccessIcon.remove(); + } MergeRequestWidget.prototype.mergeInProgress = function(deleteSourceBranch) { if (deleteSourceBranch == null) { @@ -204,7 +209,7 @@ const template = _.template(templateString)(environment) this.$widgetBody.before(template); } - }; + }; MergeRequestWidget.prototype.showCIStatus = function(state) { var allowed_states; @@ -246,4 +251,4 @@ })(); - })(window.gl || (window.gl = {})); +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/pipelines.js.es6 b/app/assets/javascripts/pipelines.js.es6 index fb95648e1c7..0b09ad113a3 100644 --- a/app/assets/javascripts/pipelines.js.es6 +++ b/app/assets/javascripts/pipelines.js.es6 @@ -1,6 +1,7 @@ +/* eslint-disable no-new, guard-for-in, no-restricted-syntax, no-continue, padded-blocks, no-param-reassign, max-len */ + //= require lib/utils/bootstrap_linked_tabs -/* eslint-disable */ ((global) => { class Pipelines { diff --git a/app/assets/javascripts/profile/gl_crop.js.es6 b/app/assets/javascripts/profile/gl_crop.js.es6 index 6da6c1d0295..b4b6da41f63 100644 --- a/app/assets/javascripts/profile/gl_crop.js.es6 +++ b/app/assets/javascripts/profile/gl_crop.js.es6 @@ -1,4 +1,5 @@ -/* eslint-disable */ +/* eslint-disable no-useless-escape, max-len, padded-blocks, quotes, no-var, no-underscore-dangle, func-names, space-before-function-paren, no-unused-vars, no-return-assign, object-shorthand, one-var, one-var-declaration-per-line, comma-dangle, consistent-return, class-methods-use-this, no-plusplus, new-parens, semi */ + ((global) => { // Matches everything but the file name diff --git a/app/assets/javascripts/profile/profile.js.es6 b/app/assets/javascripts/profile/profile.js.es6 index 3eb81808bd6..eb2fe3477a2 100644 --- a/app/assets/javascripts/profile/profile.js.es6 +++ b/app/assets/javascripts/profile/profile.js.es6 @@ -1,4 +1,6 @@ -/* eslint-disable */ +/* eslint-disable comma-dangle, no-unused-vars, class-methods-use-this, quotes, consistent-return, func-names, prefer-arrow-callback, space-before-function-paren, max-len, padded-blocks */ +/* global Flash */ + ((global) => { class Profile { diff --git a/app/assets/javascripts/project_label_subscription.js.es6 b/app/assets/javascripts/project_label_subscription.js.es6 index 03a115cb35b..b8d6a198996 100644 --- a/app/assets/javascripts/project_label_subscription.js.es6 +++ b/app/assets/javascripts/project_label_subscription.js.es6 @@ -1,4 +1,5 @@ -/* eslint-disable */ +/* eslint-disable wrap-iife, func-names, space-before-function-paren, object-shorthand, comma-dangle, one-var, one-var-declaration-per-line, no-restricted-syntax, prefer-const, max-len, no-param-reassign, padded-blocks */ + (function(global) { class ProjectLabelSubscription { constructor(container) { diff --git a/app/assets/javascripts/protected_branches/protected_branch_access_dropdown.js.es6 b/app/assets/javascripts/protected_branches/protected_branch_access_dropdown.js.es6 index 2d60947a666..4aef1c84b56 100644 --- a/app/assets/javascripts/protected_branches/protected_branch_access_dropdown.js.es6 +++ b/app/assets/javascripts/protected_branches/protected_branch_access_dropdown.js.es6 @@ -1,4 +1,5 @@ -/* eslint-disable */ +/* eslint-disable arrow-parens, no-param-reassign, no-irregular-whitespace, object-shorthand, no-else-return, comma-dangle, semi, padded-blocks, max-len */ + (global => { global.gl = global.gl || {}; diff --git a/app/assets/javascripts/protected_branches/protected_branch_create.js.es6 b/app/assets/javascripts/protected_branches/protected_branch_create.js.es6 index c45c9d8ff22..f26fba979a4 100644 --- a/app/assets/javascripts/protected_branches/protected_branch_create.js.es6 +++ b/app/assets/javascripts/protected_branches/protected_branch_create.js.es6 @@ -1,4 +1,6 @@ -/* eslint-disable */ +/* eslint-disable no-new, arrow-parens, no-param-reassign, no-irregular-whitespace, comma-dangle, padded-blocks, semi, max-len */ +/* global ProtectedBranchDropdown */ + (global => { global.gl = global.gl || {}; diff --git a/app/assets/javascripts/protected_branches/protected_branch_dropdown.js.es6 b/app/assets/javascripts/protected_branches/protected_branch_dropdown.js.es6 index e3f226e9a2a..08264ad3d2f 100644 --- a/app/assets/javascripts/protected_branches/protected_branch_dropdown.js.es6 +++ b/app/assets/javascripts/protected_branches/protected_branch_dropdown.js.es6 @@ -1,4 +1,5 @@ -/* eslint-disable */ +/* eslint-disable comma-dangle, no-unused-vars */ + class ProtectedBranchDropdown { constructor(options) { this.onSelect = options.onSelect; diff --git a/app/assets/javascripts/protected_branches/protected_branch_edit.js.es6 b/app/assets/javascripts/protected_branches/protected_branch_edit.js.es6 index ac3142ffb07..4ff2fa5a80f 100644 --- a/app/assets/javascripts/protected_branches/protected_branch_edit.js.es6 +++ b/app/assets/javascripts/protected_branches/protected_branch_edit.js.es6 @@ -1,4 +1,6 @@ -/* eslint-disable */ +/* eslint-disable no-new, arrow-parens, no-param-reassign, no-irregular-whitespace, padded-blocks, comma-dangle, no-trailing-spaces, semi, max-len */ +/* global Flash */ + (global => { global.gl = global.gl || {}; @@ -33,7 +35,7 @@ const $allowedToPushInput = this.$wrap.find(`input[name="${this.$allowedToPushDropdown.data('fieldName')}"]`); // Do not update if one dropdown has not selected any option - if (!($allowedToMergeInput.length && $allowedToPushInput.length)) return; + if (!($allowedToMergeInput.length && $allowedToPushInput.length)) return; $.ajax({ type: 'POST', diff --git a/app/assets/javascripts/protected_branches/protected_branch_edit_list.js.es6 b/app/assets/javascripts/protected_branches/protected_branch_edit_list.js.es6 index 705378a364d..b6972ef2e16 100644 --- a/app/assets/javascripts/protected_branches/protected_branch_edit_list.js.es6 +++ b/app/assets/javascripts/protected_branches/protected_branch_edit_list.js.es6 @@ -1,4 +1,5 @@ -/* eslint-disable */ +/* eslint-disable arrow-parens, no-param-reassign, no-irregular-whitespace, no-new, comma-dangle, semi, padded-blocks, max-len */ + (global => { global.gl = global.gl || {}; diff --git a/app/assets/javascripts/protected_branches/protected_branches_bundle.js b/app/assets/javascripts/protected_branches/protected_branches_bundle.js index 17e34163831..15b3affd469 100644 --- a/app/assets/javascripts/protected_branches/protected_branches_bundle.js +++ b/app/assets/javascripts/protected_branches/protected_branches_bundle.js @@ -1,2 +1 @@ -/* eslint-disable */ /*= require_tree . */ diff --git a/app/assets/javascripts/search_autocomplete.js.es6 b/app/assets/javascripts/search_autocomplete.js.es6 index 5fa94556501..437f5dbbf7d 100644 --- a/app/assets/javascripts/search_autocomplete.js.es6 +++ b/app/assets/javascripts/search_autocomplete.js.es6 @@ -1,4 +1,5 @@ -/* eslint-disable */ +/* eslint-disable comma-dangle, no-return-assign, one-var, no-var, no-underscore-dangle, one-var-declaration-per-line, no-unused-vars, no-cond-assign, consistent-return, object-shorthand, prefer-arrow-callback, func-names, space-before-function-paren, no-plusplus, prefer-template, quotes, class-methods-use-this, no-unused-expressions, no-sequences, wrap-iife, no-lonely-if, no-else-return, no-param-reassign, vars-on-top, padded-blocks, no-extra-semi, indent, max-len */ + ((global) => { const KEYCODE = { diff --git a/app/assets/javascripts/sidebar.js.es6 b/app/assets/javascripts/sidebar.js.es6 index a23ca449c4b..9790a44972d 100644 --- a/app/assets/javascripts/sidebar.js.es6 +++ b/app/assets/javascripts/sidebar.js.es6 @@ -1,4 +1,6 @@ -/* eslint-disable */ +/* eslint-disable arrow-parens, class-methods-use-this, no-param-reassign, padded-blocks */ +/* global Cookies */ + ((global) => { let singleton; diff --git a/app/assets/javascripts/snippets_list.js.es6 b/app/assets/javascripts/snippets_list.js.es6 index c3afc3f2246..6f913326a3a 100644 --- a/app/assets/javascripts/snippets_list.js.es6 +++ b/app/assets/javascripts/snippets_list.js.es6 @@ -1,4 +1,5 @@ -/* eslint-disable */ +/* eslint-disable arrow-parens, no-param-reassign, space-before-function-paren, func-names, no-var, semi, max-len */ + (global => { global.gl = global.gl || {}; diff --git a/app/assets/javascripts/templates/issuable_template_selector.js.es6 b/app/assets/javascripts/templates/issuable_template_selector.js.es6 index 93a3d67ee9f..d2b152045b4 100644 --- a/app/assets/javascripts/templates/issuable_template_selector.js.es6 +++ b/app/assets/javascripts/templates/issuable_template_selector.js.es6 @@ -1,4 +1,6 @@ -/* eslint-disable */ +/* eslint-disable prefer-const, comma-dangle, max-len, no-useless-return, object-curly-spacing, no-param-reassign, max-len */ +/* global Api */ + /*= require ../blob/template_selector */ ((global) => { diff --git a/app/assets/javascripts/templates/issuable_template_selectors.js.es6 b/app/assets/javascripts/templates/issuable_template_selectors.js.es6 index 0a3890e85fe..7310b9de074 100644 --- a/app/assets/javascripts/templates/issuable_template_selectors.js.es6 +++ b/app/assets/javascripts/templates/issuable_template_selectors.js.es6 @@ -1,4 +1,5 @@ -/* eslint-disable */ +/* eslint-disable no-new, comma-dangle, class-methods-use-this, prefer-const, no-param-reassign */ + ((global) => { class IssuableTemplateSelectors { constructor({ $dropdowns, editor } = {}) { diff --git a/app/assets/javascripts/todos.js.es6 b/app/assets/javascripts/todos.js.es6 index 213e80825b7..b777d966a43 100644 --- a/app/assets/javascripts/todos.js.es6 +++ b/app/assets/javascripts/todos.js.es6 @@ -1,4 +1,7 @@ -/* eslint-disable */ +/* eslint-disable padded-blocks, class-methods-use-this, no-new, func-names, prefer-template, no-unneeded-ternary, object-shorthand, space-before-function-paren, comma-dangle, quote-props, consistent-return, no-else-return, semi, no-param-reassign, max-len, no-undef */ +/* global UsersSelect */ +/* global Turbolinks */ + ((global) => { class Todos { diff --git a/app/assets/javascripts/user.js.es6 b/app/assets/javascripts/user.js.es6 index 5e869e99fdb..0a2db7c05fe 100644 --- a/app/assets/javascripts/user.js.es6 +++ b/app/assets/javascripts/user.js.es6 @@ -1,4 +1,6 @@ -/* eslint-disable */ +/* eslint-disable class-methods-use-this, comma-dangle, arrow-parens, no-param-reassign, semi */ +/* global Cookies */ + ((global) => { global.User = class { constructor({ action }) { diff --git a/app/assets/javascripts/user_tabs.js.es6 b/app/assets/javascripts/user_tabs.js.es6 index 5a625611987..b9c23b51b4d 100644 --- a/app/assets/javascripts/user_tabs.js.es6 +++ b/app/assets/javascripts/user_tabs.js.es6 @@ -1,4 +1,5 @@ -/* eslint-disable */ +/* eslint-disable max-len, space-before-function-paren, no-underscore-dangle, array-bracket-spacing, consistent-return, comma-dangle, no-unused-vars, dot-notation, no-new, no-return-assign, camelcase, semi, no-param-reassign */ + /* UserTabs diff --git a/app/assets/javascripts/username_validator.js.es6 b/app/assets/javascripts/username_validator.js.es6 index c4dde575c6e..26c64caf68a 100644 --- a/app/assets/javascripts/username_validator.js.es6 +++ b/app/assets/javascripts/username_validator.js.es6 @@ -1,4 +1,5 @@ -/* eslint-disable */ +/* eslint-disable comma-dangle, consistent-return, class-methods-use-this, arrow-parens, no-param-reassign, max-len */ + ((global) => { const debounceTimeoutDuration = 1000; const invalidInputClass = 'gl-field-error-outline'; -- cgit v1.2.1 From 8e0e902b133f33b38ffaa743ac3f3297b4bceb2d Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Tue, 13 Dec 2016 23:26:26 -0600 Subject: resolve all instances of no-undef eslint rule violations --- app/assets/javascripts/admin.js | 4 +++- app/assets/javascripts/api.js | 6 ++++-- app/assets/javascripts/application.js | 9 ++++++++- app/assets/javascripts/awards_handler.js | 4 +++- app/assets/javascripts/behaviors/autosize.js | 3 ++- app/assets/javascripts/behaviors/quick_submit.js | 3 ++- app/assets/javascripts/blob/blob_file_dropzone.js | 4 +++- app/assets/javascripts/blob/blob_gitignore_selector.js | 3 ++- app/assets/javascripts/blob/blob_gitignore_selectors.js | 4 +++- app/assets/javascripts/blob/blob_license_selector.js | 3 ++- app/assets/javascripts/blob_edit/blob_edit_bundle.js | 5 ++++- app/assets/javascripts/blob_edit/edit_blob.js | 5 ++++- app/assets/javascripts/breakpoints.js | 6 ++++-- app/assets/javascripts/build.js | 6 +++++- app/assets/javascripts/commit.js | 4 +++- app/assets/javascripts/commit/file.js | 4 +++- app/assets/javascripts/commits.js | 8 +++++--- app/assets/javascripts/copy_to_clipboard.js | 3 ++- .../diff_notes/components/jump_to_discussion.js.es6 | 4 ++-- app/assets/javascripts/dropzone_input.js | 3 ++- app/assets/javascripts/files_comment_button.js | 4 +++- app/assets/javascripts/gfm_auto_complete.js.es6 | 6 +++--- app/assets/javascripts/gl_dropdown.js | 7 +++++-- app/assets/javascripts/gl_form.js | 6 +++++- app/assets/javascripts/graphs/stat_graph_contributors.js | 7 ++++++- app/assets/javascripts/graphs/stat_graph_contributors_graph.js | 4 +++- app/assets/javascripts/groups_select.js | 6 ++++-- app/assets/javascripts/importer_status.js | 7 ++++--- app/assets/javascripts/issuable_context.js | 4 +++- app/assets/javascripts/issuable_form.js | 7 ++++++- app/assets/javascripts/issue.js | 3 ++- app/assets/javascripts/labels_select.js | 5 ++++- app/assets/javascripts/lib/utils/notify.js | 3 ++- app/assets/javascripts/line_highlighter.js | 3 ++- app/assets/javascripts/merge_request.js | 3 ++- app/assets/javascripts/merged_buttons.js | 3 ++- app/assets/javascripts/milestone.js | 4 +++- app/assets/javascripts/milestone_select.js | 6 +++++- app/assets/javascripts/namespace_select.js | 10 ++++++---- app/assets/javascripts/network/branch_graph.js | 4 +++- app/assets/javascripts/network/network.js | 4 +++- app/assets/javascripts/network/network_bundle.js | 5 ++++- app/assets/javascripts/notes.js | 8 ++++++-- app/assets/javascripts/notifications_dropdown.js | 4 +++- app/assets/javascripts/preview_markdown.js | 7 ++++--- app/assets/javascripts/project.js | 6 +++++- app/assets/javascripts/project_find_file.js | 4 +++- app/assets/javascripts/project_import.js | 4 +++- app/assets/javascripts/project_select.js | 4 +++- app/assets/javascripts/projects_list.js | 7 ++++--- app/assets/javascripts/right_sidebar.js | 4 +++- app/assets/javascripts/search.js | 4 +++- app/assets/javascripts/shortcuts.js | 6 +++++- app/assets/javascripts/shortcuts_blob.js | 4 +++- app/assets/javascripts/shortcuts_dashboard_navigation.js | 4 +++- app/assets/javascripts/shortcuts_find_file.js | 4 +++- app/assets/javascripts/shortcuts_issuable.js | 6 +++++- app/assets/javascripts/shortcuts_navigation.js | 4 +++- app/assets/javascripts/shortcuts_network.js | 4 +++- app/assets/javascripts/single_file_diff.js | 7 ++++--- app/assets/javascripts/snippet/snippet_bundle.js | 4 +++- app/assets/javascripts/star.js | 4 +++- app/assets/javascripts/syntax_highlight.js | 3 ++- app/assets/javascripts/todos.js.es6 | 4 ++-- app/assets/javascripts/u2f/authenticate.js | 6 +++++- app/assets/javascripts/u2f/error.js | 4 +++- app/assets/javascripts/u2f/register.js | 6 +++++- app/assets/javascripts/users/calendar.js | 5 ++++- app/assets/javascripts/users_select.js | 6 +++++- app/assets/javascripts/zen_mode.js | 5 ++++- app/views/shared/issuable/_sidebar.html.haml | 2 +- 71 files changed, 249 insertions(+), 93 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/admin.js b/app/assets/javascripts/admin.js index 31852e4750c..5a7d823e84c 100644 --- a/app/assets/javascripts/admin.js +++ b/app/assets/javascripts/admin.js @@ -1,4 +1,6 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, one-var, no-var, one-var-declaration-per-line, no-unused-vars, no-else-return, prefer-arrow-callback, camelcase, quotes, comma-dangle, no-undef, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, wrap-iife, one-var, no-var, one-var-declaration-per-line, no-unused-vars, no-else-return, prefer-arrow-callback, camelcase, quotes, comma-dangle, padded-blocks, max-len */ +/* global Turbolinks */ + (function() { this.Admin = (function() { function Admin() { diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js index 1c625e2f2b1..81c1e01901e 100644 --- a/app/assets/javascripts/api.js +++ b/app/assets/javascripts/api.js @@ -1,6 +1,7 @@ -/* eslint-disable func-names, space-before-function-paren, quotes, object-shorthand, camelcase, no-var, no-undef, comma-dangle, prefer-arrow-callback, indent, object-curly-spacing, quote-props, no-param-reassign, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, quotes, object-shorthand, camelcase, no-var, comma-dangle, prefer-arrow-callback, indent, object-curly-spacing, quote-props, no-param-reassign, padded-blocks, max-len */ + (function() { - this.Api = { + var Api = { groupsPath: "/api/:version/groups.json", groupPath: "/api/:version/groups/:id.json", namespacesPath: "/api/:version/namespaces.json", @@ -140,4 +141,5 @@ } }; + window.Api = Api; }).call(this); diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index b7c4673c8e3..043c6a11c4f 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -1,4 +1,11 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, no-undef, quotes, consistent-return, prefer-arrow-callback, comma-dangle, object-shorthand, no-new, max-len */ +/* eslint-disable func-names, space-before-function-paren, no-var, quotes, consistent-return, prefer-arrow-callback, comma-dangle, object-shorthand, no-new, max-len */ +/* global bp */ +/* global Cookies */ +/* global Flash */ +/* global ConfirmDangerModal */ +/* global AwardsHandler */ +/* global Aside */ + // This is a manifest file that'll be compiled into including all the files listed below. // Add new JavaScript code in separate files in this directory and they'll automatically // be included in the compiled file accessible from http://example.com/assets/application.js diff --git a/app/assets/javascripts/awards_handler.js b/app/assets/javascripts/awards_handler.js index f4302e2e9f6..107a7978a87 100644 --- a/app/assets/javascripts/awards_handler.js +++ b/app/assets/javascripts/awards_handler.js @@ -1,4 +1,6 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, max-len, no-var, spaced-comment, prefer-arrow-callback, consistent-return, one-var, one-var-declaration-per-line, no-unused-vars, no-else-return, prefer-template, quotes, comma-dangle, no-param-reassign, no-void, radix, keyword-spacing, space-before-blocks, brace-style, no-underscore-dangle, no-undef, no-plusplus, no-return-assign, camelcase, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, wrap-iife, max-len, no-var, spaced-comment, prefer-arrow-callback, consistent-return, one-var, one-var-declaration-per-line, no-unused-vars, no-else-return, prefer-template, quotes, comma-dangle, no-param-reassign, no-void, radix, keyword-spacing, space-before-blocks, brace-style, no-underscore-dangle, no-plusplus, no-return-assign, camelcase, padded-blocks */ +/* global Cookies */ + (function() { this.AwardsHandler = (function() { var FROM_SENTENCE_REGEX = /(?:, and | and |, )/; //For separating lists produced by ruby's Array#toSentence diff --git a/app/assets/javascripts/behaviors/autosize.js b/app/assets/javascripts/behaviors/autosize.js index a5d62f881fe..c62a4c5a456 100644 --- a/app/assets/javascripts/behaviors/autosize.js +++ b/app/assets/javascripts/behaviors/autosize.js @@ -1,4 +1,5 @@ -/* eslint-disable func-names, space-before-function-paren, prefer-arrow-callback, no-var, consistent-return, no-undef, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, prefer-arrow-callback, no-var, consistent-return, padded-blocks, max-len */ +/* global autosize */ /*= require jquery.ba-resize */ /*= require autosize */ diff --git a/app/assets/javascripts/behaviors/quick_submit.js b/app/assets/javascripts/behaviors/quick_submit.js index 4edcaa15fe5..586f941a6e3 100644 --- a/app/assets/javascripts/behaviors/quick_submit.js +++ b/app/assets/javascripts/behaviors/quick_submit.js @@ -1,4 +1,5 @@ -/* eslint-disable func-names, space-before-function-paren, one-var, no-var, one-var-declaration-per-line, no-undef, prefer-arrow-callback, camelcase, max-len, consistent-return, quotes, object-shorthand, comma-dangle, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, one-var, no-var, one-var-declaration-per-line, prefer-arrow-callback, camelcase, consistent-return, quotes, object-shorthand, comma-dangle, padded-blocks, max-len */ + // Quick Submit behavior // // When a child field of a form with a `js-quick-submit` class receives a diff --git a/app/assets/javascripts/blob/blob_file_dropzone.js b/app/assets/javascripts/blob/blob_file_dropzone.js index e0a2e8ac12e..eab686c45c3 100644 --- a/app/assets/javascripts/blob/blob_file_dropzone.js +++ b/app/assets/javascripts/blob/blob_file_dropzone.js @@ -1,4 +1,6 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, one-var, no-var, one-var-declaration-per-line, camelcase, no-undef, object-shorthand, quotes, comma-dangle, prefer-arrow-callback, no-unused-vars, prefer-template, no-useless-escape, no-alert, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, wrap-iife, one-var, no-var, one-var-declaration-per-line, camelcase, object-shorthand, quotes, comma-dangle, prefer-arrow-callback, no-unused-vars, prefer-template, no-useless-escape, no-alert, padded-blocks, max-len */ +/* global Dropzone */ + (function() { this.BlobFileDropzone = (function() { function BlobFileDropzone(form, method) { diff --git a/app/assets/javascripts/blob/blob_gitignore_selector.js b/app/assets/javascripts/blob/blob_gitignore_selector.js index 7e8f1062ab3..15563e429a0 100644 --- a/app/assets/javascripts/blob/blob_gitignore_selector.js +++ b/app/assets/javascripts/blob/blob_gitignore_selector.js @@ -1,4 +1,5 @@ -/* eslint-disable func-names, space-before-function-paren, max-len, one-var, no-var, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, prefer-rest-params, no-undef, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, max-len, one-var, no-var, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, prefer-rest-params, padded-blocks */ +/* global Api */ /*= require blob/template_selector */ diff --git a/app/assets/javascripts/blob/blob_gitignore_selectors.js b/app/assets/javascripts/blob/blob_gitignore_selectors.js index 9a694daa010..d7f95093688 100644 --- a/app/assets/javascripts/blob/blob_gitignore_selectors.js +++ b/app/assets/javascripts/blob/blob_gitignore_selectors.js @@ -1,4 +1,6 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, no-unused-expressions, no-cond-assign, no-sequences, no-undef, comma-dangle, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, no-unused-expressions, no-cond-assign, no-sequences, comma-dangle, padded-blocks, max-len */ +/* global BlobGitignoreSelector */ + (function() { this.BlobGitignoreSelectors = (function() { function BlobGitignoreSelectors(opts) { diff --git a/app/assets/javascripts/blob/blob_license_selector.js b/app/assets/javascripts/blob/blob_license_selector.js index 9a77fe35d55..d9c6f65a083 100644 --- a/app/assets/javascripts/blob/blob_license_selector.js +++ b/app/assets/javascripts/blob/blob_license_selector.js @@ -1,4 +1,5 @@ -/* eslint-disable func-names, space-before-function-paren, max-len, one-var, no-var, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, prefer-rest-params, comma-dangle, no-undef, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, max-len, one-var, no-var, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, prefer-rest-params, comma-dangle, padded-blocks */ +/* global Api */ /*= require blob/template_selector */ diff --git a/app/assets/javascripts/blob_edit/blob_edit_bundle.js b/app/assets/javascripts/blob_edit/blob_edit_bundle.js index b8eb0f60a8e..8c40e36a80a 100644 --- a/app/assets/javascripts/blob_edit/blob_edit_bundle.js +++ b/app/assets/javascripts/blob_edit/blob_edit_bundle.js @@ -1,4 +1,7 @@ -/* eslint-disable func-names, space-before-function-paren, prefer-arrow-callback, no-var, quotes, vars-on-top, no-unused-vars, no-undef, no-new, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, prefer-arrow-callback, no-var, quotes, vars-on-top, no-unused-vars, no-new, padded-blocks, max-len */ +/* global EditBlob */ +/* global NewCommitForm */ + /*= require_tree . */ (function() { diff --git a/app/assets/javascripts/blob_edit/edit_blob.js b/app/assets/javascripts/blob_edit/edit_blob.js index 0c74aaaa852..33a1ddcaf09 100644 --- a/app/assets/javascripts/blob_edit/edit_blob.js +++ b/app/assets/javascripts/blob_edit/edit_blob.js @@ -1,4 +1,7 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, camelcase, no-param-reassign, no-undef, quotes, prefer-template, no-new, comma-dangle, one-var, one-var-declaration-per-line, prefer-arrow-callback, no-else-return, no-unused-vars, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, camelcase, no-param-reassign, quotes, prefer-template, no-new, comma-dangle, one-var, one-var-declaration-per-line, prefer-arrow-callback, no-else-return, no-unused-vars, padded-blocks, max-len */ +/* global ace */ +/* global BlobGitignoreSelectors */ + (function() { var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; diff --git a/app/assets/javascripts/breakpoints.js b/app/assets/javascripts/breakpoints.js index e7ceb602601..a7e72430141 100644 --- a/app/assets/javascripts/breakpoints.js +++ b/app/assets/javascripts/breakpoints.js @@ -1,6 +1,7 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, one-var, no-var, one-var-declaration-per-line, quotes, no-shadow, prefer-arrow-callback, prefer-template, consistent-return, padded-blocks, no-return-assign, new-parens, no-param-reassign, no-undef, max-len */ +/* eslint-disable func-names, space-before-function-paren, wrap-iife, one-var, no-var, one-var-declaration-per-line, quotes, no-shadow, prefer-arrow-callback, prefer-template, consistent-return, padded-blocks, no-return-assign, new-parens, no-param-reassign, max-len */ + (function() { - this.Breakpoints = (function() { + var Breakpoints = (function() { var BreakpointInstance, instance; function Breakpoints() {} @@ -68,4 +69,5 @@ }; })(this)); + window.Breakpoints = Breakpoints; }).call(this); diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index 116a47b0907..824febe3fd3 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -1,4 +1,7 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, no-use-before-define, no-param-reassign, no-undef, quotes, yoda, no-else-return, consistent-return, comma-dangle, semi, object-shorthand, prefer-template, one-var, one-var-declaration-per-line, no-unused-vars, max-len, vars-on-top, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, no-use-before-define, no-param-reassign, quotes, yoda, no-else-return, consistent-return, comma-dangle, semi, object-shorthand, prefer-template, one-var, one-var-declaration-per-line, no-unused-vars, max-len, vars-on-top, padded-blocks */ +/* global Breakpoints */ +/* global Turbolinks */ + (function() { var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; @@ -193,6 +196,7 @@ }; Build.prototype.stepTrace = function(e) { + var $currentTarget; e.preventDefault(); $currentTarget = $(e.currentTarget); $.scrollTo($currentTarget.attr('href'), { diff --git a/app/assets/javascripts/commit.js b/app/assets/javascripts/commit.js index 67509ea7d91..67b33a4d7ee 100644 --- a/app/assets/javascripts/commit.js +++ b/app/assets/javascripts/commit.js @@ -1,4 +1,6 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-undef, padded-blocks */ +/* eslint-disable func-names, space-before-function-paren, wrap-iife, padded-blocks */ +/* global CommitFile */ + (function() { this.Commit = (function() { function Commit() { diff --git a/app/assets/javascripts/commit/file.js b/app/assets/javascripts/commit/file.js index 600bac8834a..27512312c7c 100644 --- a/app/assets/javascripts/commit/file.js +++ b/app/assets/javascripts/commit/file.js @@ -1,4 +1,6 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-new, no-undef, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-new, padded-blocks */ +/* global ImageFile */ + (function() { this.CommitFile = (function() { function CommitFile(file) { diff --git a/app/assets/javascripts/commits.js b/app/assets/javascripts/commits.js index 3627aaf5080..24a6e4ff0e9 100644 --- a/app/assets/javascripts/commits.js +++ b/app/assets/javascripts/commits.js @@ -1,4 +1,6 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, quotes, consistent-return, no-undef, no-return-assign, no-param-reassign, one-var, no-var, one-var-declaration-per-line, no-unused-vars, prefer-template, object-shorthand, comma-dangle, padded-blocks, max-len, prefer-arrow-callback */ +/* eslint-disable func-names, space-before-function-paren, wrap-iife, quotes, consistent-return, no-return-assign, no-param-reassign, one-var, no-var, one-var-declaration-per-line, no-unused-vars, prefer-template, object-shorthand, comma-dangle, padded-blocks, max-len, prefer-arrow-callback */ +/* global Pager */ + (function() { this.CommitsList = (function() { function CommitsList() {} @@ -6,8 +8,8 @@ CommitsList.timer = null; CommitsList.init = function(limit) { - $("body").on("click", ".day-commits-table li.commit", function(event) { - if (event.target.nodeName !== "A") { + $("body").on("click", ".day-commits-table li.commit", function(e) { + if (e.target.nodeName !== "A") { location.href = $(this).attr("url"); e.stopPropagation(); return false; diff --git a/app/assets/javascripts/copy_to_clipboard.js b/app/assets/javascripts/copy_to_clipboard.js index efa228a75d9..6a13f38588d 100644 --- a/app/assets/javascripts/copy_to_clipboard.js +++ b/app/assets/javascripts/copy_to_clipboard.js @@ -1,4 +1,5 @@ -/* eslint-disable func-names, space-before-function-paren, one-var, no-var, one-var-declaration-per-line, no-undef, prefer-template, quotes, no-unused-vars, prefer-arrow-callback, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, one-var, no-var, one-var-declaration-per-line, prefer-template, quotes, no-unused-vars, prefer-arrow-callback, padded-blocks, max-len */ +/* global Clipboard */ /*= require clipboard */ diff --git a/app/assets/javascripts/diff_notes/components/jump_to_discussion.js.es6 b/app/assets/javascripts/diff_notes/components/jump_to_discussion.js.es6 index fd1d1cad272..f47867fc3b0 100644 --- a/app/assets/javascripts/diff_notes/components/jump_to_discussion.js.es6 +++ b/app/assets/javascripts/diff_notes/components/jump_to_discussion.js.es6 @@ -1,10 +1,10 @@ -/* eslint-disable comma-dangle, object-shorthand, func-names, no-else-return, guard-for-in, no-restricted-syntax, one-var, indent, space-before-function-paren, no-plusplus, no-lonely-if, no-continue, brace-style, max-len, quotes, no-undef, semi */ +/* eslint-disable comma-dangle, object-shorthand, func-names, no-else-return, guard-for-in, no-restricted-syntax, one-var, indent, space-before-function-paren, no-plusplus, no-lonely-if, no-continue, brace-style, max-len, quotes, semi */ /* global Vue */ /* global DiscussionMixins */ /* global CommentsStore */ (() => { - JumpToDiscussion = Vue.extend({ + const JumpToDiscussion = Vue.extend({ mixins: [DiscussionMixins], props: { discussionId: String diff --git a/app/assets/javascripts/dropzone_input.js b/app/assets/javascripts/dropzone_input.js index e1e76bca6ad..56cb39be642 100644 --- a/app/assets/javascripts/dropzone_input.js +++ b/app/assets/javascripts/dropzone_input.js @@ -1,4 +1,5 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, max-len, one-var, no-var, one-var-declaration-per-line, no-unused-vars, camelcase, no-undef, quotes, no-useless-concat, prefer-template, quote-props, comma-dangle, object-shorthand, consistent-return, no-plusplus, prefer-arrow-callback, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, wrap-iife, max-len, one-var, no-var, one-var-declaration-per-line, no-unused-vars, camelcase, quotes, no-useless-concat, prefer-template, quote-props, comma-dangle, object-shorthand, consistent-return, no-plusplus, prefer-arrow-callback, padded-blocks */ +/* global Dropzone */ /*= require preview_markdown */ diff --git a/app/assets/javascripts/files_comment_button.js b/app/assets/javascripts/files_comment_button.js index 0122e847161..785f2869970 100644 --- a/app/assets/javascripts/files_comment_button.js +++ b/app/assets/javascripts/files_comment_button.js @@ -1,4 +1,6 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, max-len, one-var, one-var-declaration-per-line, quotes, prefer-template, newline-per-chained-call, comma-dangle, new-cap, no-else-return, padded-blocks, consistent-return, no-undef, max-len */ +/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, max-len, one-var, one-var-declaration-per-line, quotes, prefer-template, newline-per-chained-call, comma-dangle, new-cap, no-else-return, padded-blocks, consistent-return */ +/* global FilesCommentButton */ + (function() { var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; diff --git a/app/assets/javascripts/gfm_auto_complete.js.es6 b/app/assets/javascripts/gfm_auto_complete.js.es6 index 79501aa4ab9..245383438d1 100644 --- a/app/assets/javascripts/gfm_auto_complete.js.es6 +++ b/app/assets/javascripts/gfm_auto_complete.js.es6 @@ -1,4 +1,4 @@ -/* eslint-disable func-names, space-before-function-paren, no-template-curly-in-string, comma-dangle, object-shorthand, quotes, dot-notation, no-else-return, one-var, no-var, no-underscore-dangle, one-var-declaration-per-line, no-param-reassign, no-useless-escape, prefer-template, consistent-return, wrap-iife, prefer-arrow-callback, camelcase, no-unused-vars, no-useless-return, padded-blocks, vars-on-top, indent, no-extra-semi, no-multi-spaces, semi, no-undef, max-len */ +/* eslint-disable func-names, space-before-function-paren, no-template-curly-in-string, comma-dangle, object-shorthand, quotes, dot-notation, no-else-return, one-var, no-var, no-underscore-dangle, one-var-declaration-per-line, no-param-reassign, no-useless-escape, prefer-template, consistent-return, wrap-iife, prefer-arrow-callback, camelcase, no-unused-vars, no-useless-return, padded-blocks, vars-on-top, indent, no-extra-semi, no-multi-spaces, semi, max-len */ // Creates the variables for setting up GFM auto-completion (function() { @@ -10,7 +10,7 @@ return str.replace(/<(?:.|\n)*?>/gm, ''); } - GitLab.GfmAutoComplete = { + window.GitLab.GfmAutoComplete = { dataLoading: false, dataLoaded: false, cachedData: {}, @@ -57,7 +57,7 @@ var withoutAt = value.substring(1); if (withoutAt && /[^\w\d]/.test(withoutAt)) value = value.charAt() + '"' + withoutAt + '"'; } - if (!GitLab.GfmAutoComplete.dataLoaded) { + if (!window.GitLab.GfmAutoComplete.dataLoaded) { return this.at; } else { return value; diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index 9a91018a8e4..68a345d83f9 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -1,4 +1,7 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, one-var, one-var-declaration-per-line, space-before-blocks, prefer-rest-params, max-len, vars-on-top, no-plusplus, wrap-iife, no-unused-vars, quotes, no-shadow, no-cond-assign, prefer-arrow-callback, semi, no-return-assign, no-else-return, camelcase, no-undef, comma-dangle, no-lonely-if, guard-for-in, no-restricted-syntax, consistent-return, padded-blocks, prefer-template, no-param-reassign, no-loop-func, no-extra-semi, keyword-spacing, no-mixed-operators, max-len */ +/* eslint-disable func-names, space-before-function-paren, no-var, one-var, one-var-declaration-per-line, space-before-blocks, prefer-rest-params, max-len, vars-on-top, no-plusplus, wrap-iife, no-unused-vars, quotes, no-shadow, no-cond-assign, prefer-arrow-callback, semi, no-return-assign, no-else-return, camelcase, comma-dangle, no-lonely-if, guard-for-in, no-restricted-syntax, consistent-return, padded-blocks, prefer-template, no-param-reassign, no-loop-func, no-extra-semi, keyword-spacing, no-mixed-operators */ +/* global fuzzaldrinPlus */ +/* global Turbolinks */ + (function() { var GitLabDropdown, GitLabDropdownFilter, GitLabDropdownRemote, bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, @@ -188,7 +191,7 @@ })(); GitLabDropdown = (function() { - var ACTIVE_CLASS, FILTER_INPUT, INDETERMINATE_CLASS, LOADING_CLASS, PAGE_TWO_CLASS, NON_SELECTABLE_CLASSES, SELECTABLE_CLASSES, currentIndex; + var ACTIVE_CLASS, FILTER_INPUT, INDETERMINATE_CLASS, LOADING_CLASS, PAGE_TWO_CLASS, NON_SELECTABLE_CLASSES, SELECTABLE_CLASSES, CURSOR_SELECT_SCROLL_PADDING, currentIndex; LOADING_CLASS = "is-loading"; diff --git a/app/assets/javascripts/gl_form.js b/app/assets/javascripts/gl_form.js index db5d9e75b3a..56a33eeaad5 100644 --- a/app/assets/javascripts/gl_form.js +++ b/app/assets/javascripts/gl_form.js @@ -1,4 +1,8 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, no-undef, no-new, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, no-new, padded-blocks, max-len */ +/* global GitLab */ +/* global DropzoneInput */ +/* global autosize */ + (function() { this.GLForm = (function() { function GLForm(form) { diff --git a/app/assets/javascripts/graphs/stat_graph_contributors.js b/app/assets/javascripts/graphs/stat_graph_contributors.js index c3a132b3c75..2d08a7c6ac3 100644 --- a/app/assets/javascripts/graphs/stat_graph_contributors.js +++ b/app/assets/javascripts/graphs/stat_graph_contributors.js @@ -1,4 +1,9 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, one-var, camelcase, one-var-declaration-per-line, no-undef, quotes, no-param-reassign, quote-props, comma-dangle, prefer-template, max-len, no-return-assign, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, one-var, camelcase, one-var-declaration-per-line, quotes, no-param-reassign, quote-props, comma-dangle, prefer-template, max-len, no-return-assign, padded-blocks */ +/* global ContributorsGraph */ +/* global ContributorsAuthorGraph */ +/* global ContributorsMasterGraph */ +/* global ContributorsStatGraphUtil */ +/* global d3 */ /*= require d3 */ diff --git a/app/assets/javascripts/graphs/stat_graph_contributors_graph.js b/app/assets/javascripts/graphs/stat_graph_contributors_graph.js index cb2448e8cc7..9c5e9381e52 100644 --- a/app/assets/javascripts/graphs/stat_graph_contributors_graph.js +++ b/app/assets/javascripts/graphs/stat_graph_contributors_graph.js @@ -1,4 +1,6 @@ -/* eslint-disable func-names, space-before-function-paren, one-var, no-var, space-before-blocks, prefer-rest-params, max-len, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, comma-dangle, no-return-assign, prefer-arrow-callback, quotes, prefer-template, padded-blocks, no-undef, newline-per-chained-call, no-else-return, max-len */ +/* eslint-disable func-names, space-before-function-paren, one-var, no-var, space-before-blocks, prefer-rest-params, max-len, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, comma-dangle, no-return-assign, prefer-arrow-callback, quotes, prefer-template, padded-blocks, newline-per-chained-call, no-else-return */ +/* global d3 */ +/* global ContributorsGraph */ /*= require d3 */ diff --git a/app/assets/javascripts/groups_select.js b/app/assets/javascripts/groups_select.js index 3dc6f05ca20..99700e7562a 100644 --- a/app/assets/javascripts/groups_select.js +++ b/app/assets/javascripts/groups_select.js @@ -1,4 +1,6 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, wrap-iife, one-var, camelcase, one-var-declaration-per-line, quotes, object-shorthand, no-undef, prefer-arrow-callback, comma-dangle, consistent-return, yoda, prefer-rest-params, prefer-spread, no-unused-vars, prefer-template, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, no-var, wrap-iife, one-var, camelcase, one-var-declaration-per-line, quotes, object-shorthand, prefer-arrow-callback, comma-dangle, consistent-return, yoda, prefer-rest-params, prefer-spread, no-unused-vars, prefer-template, padded-blocks, max-len */ +/* global Api */ + (function() { var slice = [].slice; @@ -14,7 +16,7 @@ multiple: $(select).hasClass('multiselect'), minimumInputLength: 0, query: function(query) { - options = { all_available: all_available, skip_groups: skip_groups }; + var options = { all_available: all_available, skip_groups: skip_groups }; return Api.groups(query.term, options, function(groups) { var data; data = { diff --git a/app/assets/javascripts/importer_status.js b/app/assets/javascripts/importer_status.js index 9425b6ed9d4..fa795be07ed 100644 --- a/app/assets/javascripts/importer_status.js +++ b/app/assets/javascripts/importer_status.js @@ -1,6 +1,7 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, camelcase, no-var, one-var, one-var-declaration-per-line, prefer-template, quotes, object-shorthand, comma-dangle, no-unused-vars, prefer-arrow-callback, no-else-return, padded-blocks, vars-on-top, no-new, no-undef, max-len */ +/* eslint-disable func-names, space-before-function-paren, wrap-iife, camelcase, no-var, one-var, one-var-declaration-per-line, prefer-template, quotes, object-shorthand, comma-dangle, no-unused-vars, prefer-arrow-callback, no-else-return, padded-blocks, vars-on-top, no-new, max-len */ + (function() { - this.ImporterStatus = (function() { + window.ImporterStatus = (function() { function ImporterStatus(jobs_url, import_url) { this.jobs_url = jobs_url; this.import_url = import_url; @@ -75,7 +76,7 @@ var jobsImportPath = $('.js-importer-status').data('jobs-import-path'); var importPath = $('.js-importer-status').data('import-path'); - new ImporterStatus(jobsImportPath, importPath); + new window.ImporterStatus(jobsImportPath, importPath); } }); }).call(this); diff --git a/app/assets/javascripts/issuable_context.js b/app/assets/javascripts/issuable_context.js index 317818951fd..4aaad111082 100644 --- a/app/assets/javascripts/issuable_context.js +++ b/app/assets/javascripts/issuable_context.js @@ -1,4 +1,6 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-new, no-undef, comma-dangle, quotes, prefer-arrow-callback, consistent-return, one-var, no-var, one-var-declaration-per-line, no-underscore-dangle, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-new, comma-dangle, quotes, prefer-arrow-callback, consistent-return, one-var, no-var, one-var-declaration-per-line, no-underscore-dangle, padded-blocks, max-len */ +/* global UsersSelect */ + (function() { this.IssuableContext = (function() { function IssuableContext(currentUser) { diff --git a/app/assets/javascripts/issuable_form.js b/app/assets/javascripts/issuable_form.js index 50fdbc89c7c..2f3cad13cc0 100644 --- a/app/assets/javascripts/issuable_form.js +++ b/app/assets/javascripts/issuable_form.js @@ -1,4 +1,9 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, no-use-before-define, no-useless-escape, no-undef, no-new, quotes, object-shorthand, no-unused-vars, comma-dangle, radix, no-alert, consistent-return, no-else-return, prefer-template, one-var, one-var-declaration-per-line, curly, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, no-use-before-define, no-useless-escape, no-new, quotes, object-shorthand, no-unused-vars, comma-dangle, radix, no-alert, consistent-return, no-else-return, prefer-template, one-var, one-var-declaration-per-line, curly, padded-blocks, max-len */ +/* global GitLab */ +/* global UsersSelect */ +/* global ZenMode */ +/* global Autosave */ + (function() { var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; diff --git a/app/assets/javascripts/issue.js b/app/assets/javascripts/issue.js index 8540b199aba..63b70d4be17 100644 --- a/app/assets/javascripts/issue.js +++ b/app/assets/javascripts/issue.js @@ -1,4 +1,5 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, one-var, no-underscore-dangle, one-var-declaration-per-line, object-shorthand, no-unused-vars, no-undef, no-new, comma-dangle, consistent-return, quotes, dot-notation, quote-props, prefer-arrow-callback, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, one-var, no-underscore-dangle, one-var-declaration-per-line, object-shorthand, no-unused-vars, no-new, comma-dangle, consistent-return, quotes, dot-notation, quote-props, prefer-arrow-callback, padded-blocks, max-len */ +/* global Flash */ /*= require flash */ /*= require jquery.waitforimages */ diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js index f334f35594d..d29a5edb9ad 100644 --- a/app/assets/javascripts/labels_select.js +++ b/app/assets/javascripts/labels_select.js @@ -1,4 +1,7 @@ -/* eslint-disable no-useless-return, func-names, space-before-function-paren, wrap-iife, no-var, no-underscore-dangle, prefer-arrow-callback, max-len, one-var, no-unused-vars, one-var-declaration-per-line, prefer-template, no-new, consistent-return, object-shorthand, comma-dangle, no-shadow, no-param-reassign, brace-style, vars-on-top, quotes, no-lonely-if, no-else-return, no-undef, semi, dot-notation, no-empty, no-return-assign, camelcase, prefer-spread, padded-blocks, max-len */ +/* eslint-disable no-useless-return, func-names, space-before-function-paren, wrap-iife, no-var, no-underscore-dangle, prefer-arrow-callback, max-len, one-var, no-unused-vars, one-var-declaration-per-line, prefer-template, no-new, consistent-return, object-shorthand, comma-dangle, no-shadow, no-param-reassign, brace-style, vars-on-top, quotes, no-lonely-if, no-else-return, semi, dot-notation, no-empty, no-return-assign, camelcase, prefer-spread, padded-blocks */ +/* global Issuable */ +/* global ListLabel */ + (function() { this.LabelsSelect = (function() { function LabelsSelect() { diff --git a/app/assets/javascripts/lib/utils/notify.js b/app/assets/javascripts/lib/utils/notify.js index d0fe69260a5..3c9ad0e67c8 100644 --- a/app/assets/javascripts/lib/utils/notify.js +++ b/app/assets/javascripts/lib/utils/notify.js @@ -1,4 +1,5 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, one-var, one-var-declaration-per-line, consistent-return, no-undef, prefer-arrow-callback, no-return-assign, object-shorthand, comma-dangle, no-param-reassign, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, one-var, one-var-declaration-per-line, consistent-return, prefer-arrow-callback, no-return-assign, object-shorthand, comma-dangle, no-param-reassign, padded-blocks, max-len */ + (function() { (function(w) { var notificationGranted, notifyMe, notifyPermissions; diff --git a/app/assets/javascripts/line_highlighter.js b/app/assets/javascripts/line_highlighter.js index b0f834705c3..9af89b79f84 100644 --- a/app/assets/javascripts/line_highlighter.js +++ b/app/assets/javascripts/line_highlighter.js @@ -1,4 +1,5 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, no-use-before-define, no-underscore-dangle, no-param-reassign, no-undef, prefer-template, quotes, comma-dangle, prefer-arrow-callback, consistent-return, one-var, one-var-declaration-per-line, spaced-comment, radix, no-else-return, max-len, no-plusplus, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, no-use-before-define, no-underscore-dangle, no-param-reassign, prefer-template, quotes, comma-dangle, prefer-arrow-callback, consistent-return, one-var, one-var-declaration-per-line, spaced-comment, radix, no-else-return, max-len, no-plusplus, padded-blocks */ + // LineHighlighter // // Handles single- and multi-line selection and highlight for blob views. diff --git a/app/assets/javascripts/merge_request.js b/app/assets/javascripts/merge_request.js index 88c3636be6c..70f9a8d1955 100644 --- a/app/assets/javascripts/merge_request.js +++ b/app/assets/javascripts/merge_request.js @@ -1,4 +1,5 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, quotes, no-undef, no-underscore-dangle, one-var, one-var-declaration-per-line, consistent-return, dot-notation, quote-props, comma-dangle, object-shorthand, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, quotes, no-underscore-dangle, one-var, one-var-declaration-per-line, consistent-return, dot-notation, quote-props, comma-dangle, object-shorthand, padded-blocks, max-len */ +/* global MergeRequestTabs */ /*= require jquery.waitforimages */ /*= require task_list */ diff --git a/app/assets/javascripts/merged_buttons.js b/app/assets/javascripts/merged_buttons.js index 15a12c3d985..9f8af46c715 100644 --- a/app/assets/javascripts/merged_buttons.js +++ b/app/assets/javascripts/merged_buttons.js @@ -1,4 +1,5 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, no-undef, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, padded-blocks, max-len */ + (function() { var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; diff --git a/app/assets/javascripts/milestone.js b/app/assets/javascripts/milestone.js index db7561a3a75..42152362e60 100644 --- a/app/assets/javascripts/milestone.js +++ b/app/assets/javascripts/milestone.js @@ -1,4 +1,6 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-use-before-define, camelcase, quotes, object-shorthand, no-shadow, no-unused-vars, no-undef, comma-dangle, no-var, prefer-template, no-underscore-dangle, consistent-return, one-var, one-var-declaration-per-line, default-case, prefer-arrow-callback, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-use-before-define, camelcase, quotes, object-shorthand, no-shadow, no-unused-vars, comma-dangle, no-var, prefer-template, no-underscore-dangle, consistent-return, one-var, one-var-declaration-per-line, default-case, prefer-arrow-callback, padded-blocks, max-len */ +/* global Flash */ + (function() { this.Milestone = (function() { Milestone.updateIssue = function(li, issue_url, data) { diff --git a/app/assets/javascripts/milestone_select.js b/app/assets/javascripts/milestone_select.js index 67796083790..28054b78249 100644 --- a/app/assets/javascripts/milestone_select.js +++ b/app/assets/javascripts/milestone_select.js @@ -1,4 +1,8 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, no-underscore-dangle, prefer-arrow-callback, max-len, one-var, one-var-declaration-per-line, no-unused-vars, object-shorthand, comma-dangle, no-else-return, no-self-compare, consistent-return, no-undef, no-param-reassign, no-shadow, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, no-underscore-dangle, prefer-arrow-callback, max-len, one-var, one-var-declaration-per-line, no-unused-vars, object-shorthand, comma-dangle, no-else-return, no-self-compare, consistent-return, no-param-reassign, no-shadow, padded-blocks */ +/* global Vue */ +/* global Issuable */ +/* global ListMilestone */ + (function() { this.MilestoneSelect = (function() { function MilestoneSelect(currentProject) { diff --git a/app/assets/javascripts/namespace_select.js b/app/assets/javascripts/namespace_select.js index 87c903ec576..6633f2c2709 100644 --- a/app/assets/javascripts/namespace_select.js +++ b/app/assets/javascripts/namespace_select.js @@ -1,8 +1,10 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, one-var, vars-on-top, one-var-declaration-per-line, comma-dangle, object-shorthand, no-else-return, prefer-template, quotes, no-undef, prefer-arrow-callback, padded-blocks, no-param-reassign, no-cond-assign, max-len */ +/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, one-var, vars-on-top, one-var-declaration-per-line, comma-dangle, object-shorthand, no-else-return, prefer-template, quotes, prefer-arrow-callback, padded-blocks, no-param-reassign, no-cond-assign, max-len */ +/* global Api */ + (function() { var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; - this.NamespaceSelect = (function() { + window.NamespaceSelect = (function() { function NamespaceSelect(opts) { this.onSelectItem = bind(this.onSelectItem, this); var fieldName, showAny; @@ -64,7 +66,7 @@ })(); - this.NamespaceSelects = (function() { + window.NamespaceSelects = (function() { function NamespaceSelects(opts) { var ref; if (opts == null) { @@ -74,7 +76,7 @@ this.$dropdowns.each(function(i, dropdown) { var $dropdown; $dropdown = $(dropdown); - return new NamespaceSelect({ + return new window.NamespaceSelect({ dropdown: $dropdown }); }); diff --git a/app/assets/javascripts/network/branch_graph.js b/app/assets/javascripts/network/branch_graph.js index e3dc599b90a..64b19a54893 100644 --- a/app/assets/javascripts/network/branch_graph.js +++ b/app/assets/javascripts/network/branch_graph.js @@ -1,4 +1,6 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, quotes, comma-dangle, one-var, one-var-declaration-per-line, no-mixed-operators, new-cap, no-undef, no-plusplus, no-loop-func, no-floating-decimal, consistent-return, no-unused-vars, prefer-template, prefer-arrow-callback, camelcase, max-len, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, quotes, comma-dangle, one-var, one-var-declaration-per-line, no-mixed-operators, new-cap, no-plusplus, no-loop-func, no-floating-decimal, consistent-return, no-unused-vars, prefer-template, prefer-arrow-callback, camelcase, max-len, padded-blocks */ +/* global Raphael */ + (function() { var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; diff --git a/app/assets/javascripts/network/network.js b/app/assets/javascripts/network/network.js index 5a8f723a27b..2367d2497b2 100644 --- a/app/assets/javascripts/network/network.js +++ b/app/assets/javascripts/network/network.js @@ -1,4 +1,6 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, quotes, no-undef, quote-props, prefer-template, comma-dangle, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, quotes, quote-props, prefer-template, comma-dangle, padded-blocks, max-len */ +/* global BranchGraph */ + (function() { this.Network = (function() { function Network(opts) { diff --git a/app/assets/javascripts/network/network_bundle.js b/app/assets/javascripts/network/network_bundle.js index 732d92845cb..17833d3419a 100644 --- a/app/assets/javascripts/network/network_bundle.js +++ b/app/assets/javascripts/network/network_bundle.js @@ -1,4 +1,7 @@ -/* eslint-disable func-names, space-before-function-paren, prefer-arrow-callback, quotes, no-var, vars-on-top, camelcase, no-undef, comma-dangle, consistent-return, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, prefer-arrow-callback, quotes, no-var, vars-on-top, camelcase, comma-dangle, consistent-return, padded-blocks, max-len */ +/* global Network */ +/* global ShortcutsNetwork */ + // This is a manifest file that'll be compiled into including all the files listed below. // Add new JavaScript code in separate files in this directory and they'll automatically // be included in the compiled file accessible from http://example.com/assets/application.js diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js index 0ca0e255595..fca9b8f6c91 100644 --- a/app/assets/javascripts/notes.js +++ b/app/assets/javascripts/notes.js @@ -1,4 +1,8 @@ -/* eslint-disable no-restricted-properties, func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, no-use-before-define, camelcase, no-unused-expressions, quotes, max-len, one-var, one-var-declaration-per-line, default-case, prefer-template, no-undef, consistent-return, no-alert, no-return-assign, no-param-reassign, prefer-arrow-callback, no-else-return, comma-dangle, no-new, brace-style, no-lonely-if, vars-on-top, no-unused-vars, semi, indent, no-sequences, no-shadow, newline-per-chained-call, no-useless-escape, radix, padded-blocks, max-len */ +/* eslint-disable no-restricted-properties, func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, no-use-before-define, camelcase, no-unused-expressions, quotes, max-len, one-var, one-var-declaration-per-line, default-case, prefer-template, consistent-return, no-alert, no-return-assign, no-param-reassign, prefer-arrow-callback, no-else-return, comma-dangle, no-new, brace-style, no-lonely-if, vars-on-top, no-unused-vars, semi, indent, no-sequences, no-shadow, newline-per-chained-call, no-useless-escape, radix, padded-blocks */ +/* global Flash */ +/* global GLForm */ +/* global Autosave */ +/* global ResolveService */ /*= require autosave */ /*= require autosize */ @@ -671,7 +675,7 @@ */ Notes.prototype.addDiffNote = function(e) { - var $link, addForm, hasNotes, lineType, newForm, nextRow, noteForm, notesContent, replyButton, row, rowCssToAdd, targetContent; + var $link, addForm, hasNotes, lineType, newForm, nextRow, noteForm, notesContent, notesContentSelector, replyButton, row, rowCssToAdd, targetContent; e.preventDefault(); $link = $(e.currentTarget); row = $link.closest("tr"); diff --git a/app/assets/javascripts/notifications_dropdown.js b/app/assets/javascripts/notifications_dropdown.js index b152d26733f..324b68a7efc 100644 --- a/app/assets/javascripts/notifications_dropdown.js +++ b/app/assets/javascripts/notifications_dropdown.js @@ -1,4 +1,6 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, one-var, no-var, one-var-declaration-per-line, no-unused-vars, consistent-return, prefer-arrow-callback, no-else-return, no-undef, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, wrap-iife, one-var, no-var, one-var-declaration-per-line, no-unused-vars, consistent-return, prefer-arrow-callback, no-else-return, padded-blocks, max-len */ +/* global Flash */ + (function() { this.NotificationsDropdown = (function() { function NotificationsDropdown() { diff --git a/app/assets/javascripts/preview_markdown.js b/app/assets/javascripts/preview_markdown.js index 3723aa24942..2dc8eb8b2de 100644 --- a/app/assets/javascripts/preview_markdown.js +++ b/app/assets/javascripts/preview_markdown.js @@ -1,4 +1,5 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, one-var, one-var-declaration-per-line, wrap-iife, no-else-return, consistent-return, object-shorthand, comma-dangle, no-param-reassign, padded-blocks, no-undef, camelcase, prefer-arrow-callback, max-len */ +/* eslint-disable func-names, space-before-function-paren, no-var, one-var, one-var-declaration-per-line, wrap-iife, no-else-return, consistent-return, object-shorthand, comma-dangle, no-param-reassign, padded-blocks, camelcase, prefer-arrow-callback, max-len */ + // MarkdownPreview // // Handles toggling the "Write" and "Preview" tab clicks, rendering the preview, @@ -7,7 +8,7 @@ (function() { var lastTextareaPreviewed, markdownPreview, previewButtonSelector, writeButtonSelector; - this.MarkdownPreview = (function() { + window.MarkdownPreview = (function() { function MarkdownPreview() {} // Minimum number of users referenced before triggering a warning @@ -83,7 +84,7 @@ })(); - markdownPreview = new MarkdownPreview(); + markdownPreview = new window.MarkdownPreview(); previewButtonSelector = '.js-md-preview-button'; diff --git a/app/assets/javascripts/project.js b/app/assets/javascripts/project.js index 016d999d77e..fcf3a4af956 100644 --- a/app/assets/javascripts/project.js +++ b/app/assets/javascripts/project.js @@ -1,4 +1,8 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, quotes, consistent-return, no-undef, no-new, prefer-arrow-callback, no-return-assign, one-var, one-var-declaration-per-line, object-shorthand, comma-dangle, no-else-return, newline-per-chained-call, no-shadow, semi, vars-on-top, indent, prefer-template, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, quotes, consistent-return, no-new, prefer-arrow-callback, no-return-assign, one-var, one-var-declaration-per-line, object-shorthand, comma-dangle, no-else-return, newline-per-chained-call, no-shadow, semi, vars-on-top, indent, prefer-template, padded-blocks, max-len */ +/* global Cookies */ +/* global Turbolinks */ +/* global ProjectSelect */ + (function() { this.Project = (function() { function Project() { diff --git a/app/assets/javascripts/project_find_file.js b/app/assets/javascripts/project_find_file.js index 804306a3293..1bd232314d0 100644 --- a/app/assets/javascripts/project_find_file.js +++ b/app/assets/javascripts/project_find_file.js @@ -1,4 +1,6 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, quotes, consistent-return, one-var, one-var-declaration-per-line, no-cond-assign, max-len, no-undef, object-shorthand, no-param-reassign, comma-dangle, no-plusplus, prefer-template, no-unused-vars, no-return-assign, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, quotes, consistent-return, one-var, one-var-declaration-per-line, no-cond-assign, max-len, object-shorthand, no-param-reassign, comma-dangle, no-plusplus, prefer-template, no-unused-vars, no-return-assign, padded-blocks */ +/* global fuzzaldrinPlus */ + (function() { var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; diff --git a/app/assets/javascripts/project_import.js b/app/assets/javascripts/project_import.js index c99e55234cf..02dafcfb865 100644 --- a/app/assets/javascripts/project_import.js +++ b/app/assets/javascripts/project_import.js @@ -1,4 +1,6 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, prefer-arrow-callback, no-undef, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, wrap-iife, prefer-arrow-callback, padded-blocks, max-len */ +/* global Turbolinks */ + (function() { this.ProjectImport = (function() { function ProjectImport() { diff --git a/app/assets/javascripts/project_select.js b/app/assets/javascripts/project_select.js index fe1f96872f3..650996700ba 100644 --- a/app/assets/javascripts/project_select.js +++ b/app/assets/javascripts/project_select.js @@ -1,4 +1,6 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, prefer-arrow-callback, no-var, comma-dangle, object-shorthand, one-var, one-var-declaration-per-line, no-undef, no-else-return, quotes, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, wrap-iife, prefer-arrow-callback, no-var, comma-dangle, object-shorthand, one-var, one-var-declaration-per-line, no-else-return, quotes, padded-blocks, max-len */ +/* global Api */ + (function() { this.ProjectSelect = (function() { function ProjectSelect() { diff --git a/app/assets/javascripts/projects_list.js b/app/assets/javascripts/projects_list.js index dbf530bed41..4548dc68fe1 100644 --- a/app/assets/javascripts/projects_list.js +++ b/app/assets/javascripts/projects_list.js @@ -1,6 +1,7 @@ -/* eslint-disable func-names, space-before-function-paren, object-shorthand, quotes, no-var, one-var, one-var-declaration-per-line, no-undef, prefer-arrow-callback, consistent-return, no-unused-vars, camelcase, prefer-template, comma-dangle, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, object-shorthand, quotes, no-var, one-var, one-var-declaration-per-line, prefer-arrow-callback, consistent-return, no-unused-vars, camelcase, prefer-template, comma-dangle, padded-blocks, max-len */ + (function() { - this.ProjectsList = { + window.ProjectsList = { init: function() { $(".projects-list-filter").off('keyup'); this.initSearch(); @@ -9,7 +10,7 @@ initSearch: function() { var debounceFilter, projectsListFilter; projectsListFilter = $('.projects-list-filter'); - debounceFilter = _.debounce(ProjectsList.filterResults, 500); + debounceFilter = _.debounce(window.ProjectsList.filterResults, 500); return projectsListFilter.on('keyup', function(e) { if (projectsListFilter.val() !== '') { return debounceFilter(); diff --git a/app/assets/javascripts/right_sidebar.js b/app/assets/javascripts/right_sidebar.js index 440b5da756d..b1e844b7302 100644 --- a/app/assets/javascripts/right_sidebar.js +++ b/app/assets/javascripts/right_sidebar.js @@ -1,4 +1,6 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, no-unused-vars, semi, consistent-return, one-var, one-var-declaration-per-line, no-undef, quotes, prefer-template, object-shorthand, comma-dangle, no-else-return, no-param-reassign, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, no-unused-vars, semi, consistent-return, one-var, one-var-declaration-per-line, quotes, prefer-template, object-shorthand, comma-dangle, no-else-return, no-param-reassign, padded-blocks, max-len */ +/* global Cookies */ + (function() { var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; diff --git a/app/assets/javascripts/search.js b/app/assets/javascripts/search.js index 1d208f1494c..4b6ebadeac7 100644 --- a/app/assets/javascripts/search.js +++ b/app/assets/javascripts/search.js @@ -1,4 +1,6 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, one-var, one-var-declaration-per-line, object-shorthand, no-undef, prefer-arrow-callback, comma-dangle, prefer-template, quotes, no-else-return, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, one-var, one-var-declaration-per-line, object-shorthand, prefer-arrow-callback, comma-dangle, prefer-template, quotes, no-else-return, padded-blocks, max-len */ +/* global Api */ + (function() { this.Search = (function() { function Search() { diff --git a/app/assets/javascripts/shortcuts.js b/app/assets/javascripts/shortcuts.js index fa2168723be..5ea00f408f4 100644 --- a/app/assets/javascripts/shortcuts.js +++ b/app/assets/javascripts/shortcuts.js @@ -1,4 +1,8 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, quotes, no-undef, prefer-arrow-callback, consistent-return, object-shorthand, no-unused-vars, one-var, one-var-declaration-per-line, no-plusplus, no-else-return, comma-dangle, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, quotes, prefer-arrow-callback, consistent-return, object-shorthand, no-unused-vars, one-var, one-var-declaration-per-line, no-plusplus, no-else-return, comma-dangle, padded-blocks, max-len */ +/* global Mousetrap */ +/* global Turbolinks */ +/* global findFileURL */ + (function() { var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; diff --git a/app/assets/javascripts/shortcuts_blob.js b/app/assets/javascripts/shortcuts_blob.js index 65305b8c22f..c26903038b4 100644 --- a/app/assets/javascripts/shortcuts_blob.js +++ b/app/assets/javascripts/shortcuts_blob.js @@ -1,4 +1,6 @@ -/* eslint-disable func-names, space-before-function-paren, max-len, one-var, no-var, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, consistent-return, padded-blocks, no-undef, max-len */ +/* eslint-disable func-names, space-before-function-paren, max-len, one-var, no-var, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, consistent-return, padded-blocks */ +/* global Shortcuts */ +/* global Mousetrap */ /*= require shortcuts */ diff --git a/app/assets/javascripts/shortcuts_dashboard_navigation.js b/app/assets/javascripts/shortcuts_dashboard_navigation.js index 1b9a265ba39..4549742bbcb 100644 --- a/app/assets/javascripts/shortcuts_dashboard_navigation.js +++ b/app/assets/javascripts/shortcuts_dashboard_navigation.js @@ -1,4 +1,6 @@ -/* eslint-disable func-names, space-before-function-paren, max-len, one-var, no-var, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, prefer-arrow-callback, consistent-return, no-return-assign, padded-blocks, no-undef, max-len */ +/* eslint-disable func-names, space-before-function-paren, max-len, one-var, no-var, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, prefer-arrow-callback, consistent-return, no-return-assign, padded-blocks */ +/* global Mousetrap */ +/* global Shortcuts */ /*= require shortcuts */ diff --git a/app/assets/javascripts/shortcuts_find_file.js b/app/assets/javascripts/shortcuts_find_file.js index 68cd6fad04e..3a81380eef0 100644 --- a/app/assets/javascripts/shortcuts_find_file.js +++ b/app/assets/javascripts/shortcuts_find_file.js @@ -1,4 +1,6 @@ -/* eslint-disable func-names, space-before-function-paren, max-len, one-var, no-var, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, padded-blocks, no-undef, max-len */ +/* eslint-disable func-names, space-before-function-paren, max-len, one-var, no-var, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, padded-blocks */ +/* global Mousetrap */ +/* global ShortcutsNavigation */ /*= require shortcuts_navigation */ diff --git a/app/assets/javascripts/shortcuts_issuable.js b/app/assets/javascripts/shortcuts_issuable.js index c4899f3566a..b892fbc3393 100644 --- a/app/assets/javascripts/shortcuts_issuable.js +++ b/app/assets/javascripts/shortcuts_issuable.js @@ -1,4 +1,8 @@ -/* eslint-disable func-names, space-before-function-paren, max-len, no-var, one-var, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, one-var-declaration-per-line, quotes, prefer-arrow-callback, consistent-return, prefer-template, no-mixed-operators, no-undef, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, max-len, no-var, one-var, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, one-var-declaration-per-line, quotes, prefer-arrow-callback, consistent-return, prefer-template, no-mixed-operators, padded-blocks */ +/* global Mousetrap */ +/* global Turbolinks */ +/* global ShortcutsNavigation */ +/* global sidebar */ /*= require mousetrap */ /*= require shortcuts_navigation */ diff --git a/app/assets/javascripts/shortcuts_navigation.js b/app/assets/javascripts/shortcuts_navigation.js index 7d4d6364c70..0776d0a9b67 100644 --- a/app/assets/javascripts/shortcuts_navigation.js +++ b/app/assets/javascripts/shortcuts_navigation.js @@ -1,4 +1,6 @@ -/* eslint-disable func-names, space-before-function-paren, max-len, no-var, one-var, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, prefer-arrow-callback, consistent-return, no-return-assign, padded-blocks, no-undef, max-len */ +/* eslint-disable func-names, space-before-function-paren, max-len, no-var, one-var, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, prefer-arrow-callback, consistent-return, no-return-assign, padded-blocks */ +/* global Mousetrap */ +/* global Shortcuts */ /*= require shortcuts */ diff --git a/app/assets/javascripts/shortcuts_network.js b/app/assets/javascripts/shortcuts_network.js index a4095d2c06b..ecc3fab84c3 100644 --- a/app/assets/javascripts/shortcuts_network.js +++ b/app/assets/javascripts/shortcuts_network.js @@ -1,4 +1,6 @@ -/* eslint-disable func-names, space-before-function-paren, max-len, no-var, one-var, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, padded-blocks, no-undef, max-len */ +/* eslint-disable func-names, space-before-function-paren, max-len, no-var, one-var, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, padded-blocks, max-len */ +/* global Mousetrap */ +/* global ShortcutsNavigation */ /*= require shortcuts_navigation */ diff --git a/app/assets/javascripts/single_file_diff.js b/app/assets/javascripts/single_file_diff.js index 0d48e69cce9..ac8603ccd10 100644 --- a/app/assets/javascripts/single_file_diff.js +++ b/app/assets/javascripts/single_file_diff.js @@ -1,8 +1,9 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, one-var, one-var-declaration-per-line, consistent-return, no-param-reassign, padded-blocks, no-undef, max-len */ +/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, one-var, one-var-declaration-per-line, consistent-return, no-param-reassign, padded-blocks, max-len */ + (function() { var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; - this.SingleFileDiff = (function() { + window.SingleFileDiff = (function() { var COLLAPSED_HTML, ERROR_HTML, LOADING_HTML, WRAPPER; WRAPPER = '
    '; @@ -93,7 +94,7 @@ $.fn.singleFileDiff = function(forceLoad, cb) { return this.each(function() { if (!$.data(this, 'singleFileDiff') || forceLoad) { - return $.data(this, 'singleFileDiff', new SingleFileDiff(this, forceLoad, cb)); + return $.data(this, 'singleFileDiff', new window.SingleFileDiff(this, forceLoad, cb)); } }); }; diff --git a/app/assets/javascripts/snippet/snippet_bundle.js b/app/assets/javascripts/snippet/snippet_bundle.js index 2c8ecba7de4..18512d179b3 100644 --- a/app/assets/javascripts/snippet/snippet_bundle.js +++ b/app/assets/javascripts/snippet/snippet_bundle.js @@ -1,4 +1,6 @@ -/* eslint-disable func-names, space-before-function-paren, prefer-arrow-callback, no-var, no-undef, quotes, semi, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, prefer-arrow-callback, no-var, quotes, semi, padded-blocks, max-len */ +/* global ace */ + /*= require_tree . */ (function() { diff --git a/app/assets/javascripts/star.js b/app/assets/javascripts/star.js index 32803fa790b..f1fc526bf2e 100644 --- a/app/assets/javascripts/star.js +++ b/app/assets/javascripts/star.js @@ -1,4 +1,6 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-unused-vars, one-var, no-var, one-var-declaration-per-line, prefer-arrow-callback, no-new, no-undef, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-unused-vars, one-var, no-var, one-var-declaration-per-line, prefer-arrow-callback, no-new, padded-blocks, max-len */ +/* global Flash */ + (function() { this.Star = (function() { function Star() { diff --git a/app/assets/javascripts/syntax_highlight.js b/app/assets/javascripts/syntax_highlight.js index bd37d69165f..fabeb44f4b3 100644 --- a/app/assets/javascripts/syntax_highlight.js +++ b/app/assets/javascripts/syntax_highlight.js @@ -1,4 +1,5 @@ -/* eslint-disable func-names, space-before-function-paren, consistent-return, no-var, no-undef, no-else-return, prefer-arrow-callback, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, consistent-return, no-var, no-else-return, prefer-arrow-callback, padded-blocks, max-len */ + // Syntax Highlighter // // Applies a syntax highlighting color scheme CSS class to any element with the diff --git a/app/assets/javascripts/todos.js.es6 b/app/assets/javascripts/todos.js.es6 index b777d966a43..d8713600030 100644 --- a/app/assets/javascripts/todos.js.es6 +++ b/app/assets/javascripts/todos.js.es6 @@ -1,4 +1,4 @@ -/* eslint-disable padded-blocks, class-methods-use-this, no-new, func-names, prefer-template, no-unneeded-ternary, object-shorthand, space-before-function-paren, comma-dangle, quote-props, consistent-return, no-else-return, semi, no-param-reassign, max-len, no-undef */ +/* eslint-disable padded-blocks, class-methods-use-this, no-new, func-names, prefer-template, no-unneeded-ternary, object-shorthand, space-before-function-paren, comma-dangle, quote-props, consistent-return, no-else-return, semi, no-param-reassign, max-len */ /* global UsersSelect */ /* global Turbolinks */ @@ -75,7 +75,7 @@ allDoneClicked(e) { e.preventDefault(); e.stopImmediatePropagation(); - $target = $(e.currentTarget); + const $target = $(e.currentTarget); $target.disable(); return $.ajax({ type: 'POST', diff --git a/app/assets/javascripts/u2f/authenticate.js b/app/assets/javascripts/u2f/authenticate.js index 5d991542b51..d2aa3c7a841 100644 --- a/app/assets/javascripts/u2f/authenticate.js +++ b/app/assets/javascripts/u2f/authenticate.js @@ -1,4 +1,8 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, prefer-arrow-callback, no-undef, no-else-return, quotes, quote-props, comma-dangle, one-var, one-var-declaration-per-line, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, prefer-arrow-callback, no-else-return, quotes, quote-props, comma-dangle, one-var, one-var-declaration-per-line, padded-blocks, max-len */ +/* global u2f */ +/* global U2FError */ +/* global U2FUtil */ + // Authenticate U2F (universal 2nd factor) devices for users to authenticate with. // // State Flow #1: setup -> in_progress -> authenticated -> POST to server diff --git a/app/assets/javascripts/u2f/error.js b/app/assets/javascripts/u2f/error.js index 4c70a6e9bb6..69f98c9c0ad 100644 --- a/app/assets/javascripts/u2f/error.js +++ b/app/assets/javascripts/u2f/error.js @@ -1,4 +1,6 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, no-console, quotes, prefer-template, no-undef, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, no-console, quotes, prefer-template, padded-blocks, max-len */ +/* global u2f */ + (function() { var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; diff --git a/app/assets/javascripts/u2f/register.js b/app/assets/javascripts/u2f/register.js index 97d8993cac2..4f5d68f546b 100644 --- a/app/assets/javascripts/u2f/register.js +++ b/app/assets/javascripts/u2f/register.js @@ -1,4 +1,8 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, no-undef, no-else-return, quotes, quote-props, comma-dangle, one-var, one-var-declaration-per-line, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, no-else-return, quotes, quote-props, comma-dangle, one-var, one-var-declaration-per-line, padded-blocks, max-len */ +/* global u2f */ +/* global U2FError */ +/* global U2FUtil */ + // Register U2F (universal 2nd factor) devices for users to authenticate with. // // State Flow #1: setup -> in_progress -> registered -> POST to server diff --git a/app/assets/javascripts/users/calendar.js b/app/assets/javascripts/users/calendar.js index ba7f533c349..578be7c3590 100644 --- a/app/assets/javascripts/users/calendar.js +++ b/app/assets/javascripts/users/calendar.js @@ -1,4 +1,7 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, camelcase, vars-on-top, semi, keyword-spacing, no-plusplus, no-undef, object-shorthand, comma-dangle, eqeqeq, no-mixed-operators, no-return-assign, newline-per-chained-call, prefer-arrow-callback, consistent-return, one-var, one-var-declaration-per-line, prefer-template, quotes, no-unused-vars, no-else-return, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, camelcase, vars-on-top, semi, keyword-spacing, no-plusplus, object-shorthand, comma-dangle, eqeqeq, no-mixed-operators, no-return-assign, newline-per-chained-call, prefer-arrow-callback, consistent-return, one-var, one-var-declaration-per-line, prefer-template, quotes, no-unused-vars, no-else-return, padded-blocks, max-len */ +/* global d3 */ +/* global dateFormat */ + (function() { var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; diff --git a/app/assets/javascripts/users_select.js b/app/assets/javascripts/users_select.js index c6e18fad832..d4b5e03aa35 100644 --- a/app/assets/javascripts/users_select.js +++ b/app/assets/javascripts/users_select.js @@ -1,4 +1,8 @@ -/* eslint-disable func-names, space-before-function-paren, one-var, no-var, space-before-blocks, prefer-rest-params, wrap-iife, quotes, max-len, one-var-declaration-per-line, vars-on-top, prefer-arrow-callback, consistent-return, no-undef, comma-dangle, object-shorthand, no-shadow, no-unused-vars, no-plusplus, no-else-return, no-self-compare, prefer-template, no-unused-expressions, no-lonely-if, yoda, prefer-spread, no-void, camelcase, keyword-spacing, no-param-reassign, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, one-var, no-var, space-before-blocks, prefer-rest-params, wrap-iife, quotes, max-len, one-var-declaration-per-line, vars-on-top, prefer-arrow-callback, consistent-return, comma-dangle, object-shorthand, no-shadow, no-unused-vars, no-plusplus, no-else-return, no-self-compare, prefer-template, no-unused-expressions, no-lonely-if, yoda, prefer-spread, no-void, camelcase, keyword-spacing, no-param-reassign, padded-blocks */ +/* global Vue */ +/* global Issuable */ +/* global ListUser */ + (function() { var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, slice = [].slice; diff --git a/app/assets/javascripts/zen_mode.js b/app/assets/javascripts/zen_mode.js index 82eb761442a..e09b59dd5aa 100644 --- a/app/assets/javascripts/zen_mode.js +++ b/app/assets/javascripts/zen_mode.js @@ -1,4 +1,7 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, prefer-arrow-callback, no-unused-vars, consistent-return, no-undef, camelcase, comma-dangle, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, wrap-iife, prefer-arrow-callback, no-unused-vars, consistent-return, camelcase, comma-dangle, padded-blocks, max-len */ +/* global Dropzone */ +/* global Mousetrap */ + // Zen Mode (full screen) textarea // /*= provides zen_mode:enter */ diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index 958f8413e1d..9fe1be5a597 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -167,4 +167,4 @@ new IssuableContext('#{escape_javascript(current_user.to_json(only: [:username, :id, :name]))}'); gl.Subscription.bindAll('.subscription'); new gl.DueDateSelectors(); - sidebar = new Sidebar(); + window.sidebar = new Sidebar(); -- cgit v1.2.1 From 6757aaa120c375f15e09f4c428286e5dc1d95f84 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 14 Dec 2016 11:36:19 +0100 Subject: Improve build status specs contexts descriptions --- app/views/ci/status/_badge.html.haml | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app') diff --git a/app/views/ci/status/_badge.html.haml b/app/views/ci/status/_badge.html.haml index c00ddd183fb..f2135af2686 100644 --- a/app/views/ci/status/_badge.html.haml +++ b/app/views/ci/status/_badge.html.haml @@ -1,3 +1,5 @@ +- status = local_assigns.fetch(:status) + - if status.has_details? = link_to status.details_path, class: "ci-status ci-#{status}" do = custom_icon(status.icon) -- cgit v1.2.1 From 863146d42ed8fd44ab0c0f11c873fcdbbfcb28fc Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 14 Dec 2016 14:16:28 +0000 Subject: Remove unused file --- app/views/ci/status/_icon_with_description.html.haml | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 app/views/ci/status/_icon_with_description.html.haml (limited to 'app') diff --git a/app/views/ci/status/_icon_with_description.html.haml b/app/views/ci/status/_icon_with_description.html.haml deleted file mode 100644 index 34c923440d0..00000000000 --- a/app/views/ci/status/_icon_with_description.html.haml +++ /dev/null @@ -1,12 +0,0 @@ -- detailed_status = subject.detailed_status(current_user) -- details_path = detailed_status.details_path if detailed_status.has_details? -- klass = "ci-status ci-#{detailed_status}" - -- if details_path - = link_to details_path, class: klass do - = custom_icon(detailed_status.icon) - = detailed_status.text -- else - %span{ class: klass } - = custom_icon(detailed_status.icon) - = detailed_status.text -- cgit v1.2.1 From 4ba48d6b05f66dfccc829db588312109b8b015a1 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 14 Dec 2016 14:17:02 +0000 Subject: Merge two partials into one. Rename it to match the other partials --- .../_badge_graph_icon_with_name_and_action.html.haml | 18 ++++++++++++++++++ app/views/ci/status/_icon_with_name.html.haml | 11 ----------- .../ci/status/_icon_with_name_and_action.html.haml | 8 -------- app/views/projects/stage/_graph.html.haml | 2 +- app/views/projects/stage/_in_stage_group.html.haml | 2 +- 5 files changed, 20 insertions(+), 21 deletions(-) create mode 100644 app/views/ci/status/_badge_graph_icon_with_name_and_action.html.haml delete mode 100644 app/views/ci/status/_icon_with_name.html.haml delete mode 100644 app/views/ci/status/_icon_with_name_and_action.html.haml (limited to 'app') diff --git a/app/views/ci/status/_badge_graph_icon_with_name_and_action.html.haml b/app/views/ci/status/_badge_graph_icon_with_name_and_action.html.haml new file mode 100644 index 00000000000..12a55735559 --- /dev/null +++ b/app/views/ci/status/_badge_graph_icon_with_name_and_action.html.haml @@ -0,0 +1,18 @@ +- detailed_status = subject.detailed_status(current_user) +- details_path = detailed_status.details_path if detailed_status.has_details? +- klass = "ci-status-icon ci-status-icon-#{detailed_status}" + +- if details_path + = link_to details_path, class: klass, + data: { toggle: 'tooltip', title: "#{subject.name} - #{detailed_status}" } do + %span{ class: klass }= custom_icon(detailed_status.icon) + .ci-status-text= subject.name +- else + %span{ class: klass }= custom_icon(detailed_status.icon) + .ci-status-text= subject.name + +- if detailed_status.has_action? + = link_to detailed_status.action_path, method: detailed_status.action_method, + title: "#{subject.name}: #{detailed_status.action_title}", class: 'ci-action-icon-container' do + %i.ci-action-icon-wrapper + = icon(detailed_status.action_icon, class: detailed_status.action_class) diff --git a/app/views/ci/status/_icon_with_name.html.haml b/app/views/ci/status/_icon_with_name.html.haml deleted file mode 100644 index 028e1fe9402..00000000000 --- a/app/views/ci/status/_icon_with_name.html.haml +++ /dev/null @@ -1,11 +0,0 @@ -- detailed_status = subject.detailed_status(current_user) -- details_path = detailed_status.details_path if detailed_status.has_details? -- klass = "ci-status-icon ci-status-icon-#{detailed_status}" - -- if details_path - = link_to details_path, class: klass, data: { toggle: 'tooltip', title: "#{subject.name} - #{detailed_status}" } do - %span{ class: klass }= custom_icon(detailed_status.icon) - .ci-status-text= subject.name -- else - %span{ class: klass }= custom_icon(detailed_status.icon) - .ci-status-text= subject.name diff --git a/app/views/ci/status/_icon_with_name_and_action.html.haml b/app/views/ci/status/_icon_with_name_and_action.html.haml deleted file mode 100644 index 76db3b7f38a..00000000000 --- a/app/views/ci/status/_icon_with_name_and_action.html.haml +++ /dev/null @@ -1,8 +0,0 @@ -= render "ci/status/icon_with_name", subject: subject - -- detailed_status = subject.detailed_status(current_user) -- if detailed_status.has_action? - = link_to detailed_status.action_path, method: detailed_status.action_method, - title: "#{subject.name}: #{detailed_status.action_title}", class: 'ci-action-icon-container' do - %i.ci-action-icon-wrapper - = icon(detailed_status.action_icon, class: detailed_status.action_class) diff --git a/app/views/projects/stage/_graph.html.haml b/app/views/projects/stage/_graph.html.haml index 6d280468262..ff86d93f354 100644 --- a/app/views/projects/stage/_graph.html.haml +++ b/app/views/projects/stage/_graph.html.haml @@ -13,7 +13,7 @@ %li.build .curve .build-content - = render 'ci/status/icon_with_name_and_action', subject: status + = render 'ci/status/bagde_graph_icon_with_name_and_action', subject: status - else %li.build .curve diff --git a/app/views/projects/stage/_in_stage_group.html.haml b/app/views/projects/stage/_in_stage_group.html.haml index 5c9b6549b37..e4a7613998d 100644 --- a/app/views/projects/stage/_in_stage_group.html.haml +++ b/app/views/projects/stage/_in_stage_group.html.haml @@ -10,4 +10,4 @@ %ul - subject.each do |status| %li.dropdown-build - = render 'ci/status/icon_with_name_and_action', subject: status + = render 'ci/status/bagde_graph_icon_with_name_and_action', subject: status -- cgit v1.2.1 From 5b1a38564efdba1850d7195b01146c6b49ffb29a Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 14 Dec 2016 14:19:18 +0000 Subject: Fix scss error --- app/assets/stylesheets/pages/pipelines.scss | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 23312259f73..26487b2acf9 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -665,14 +665,15 @@ color: $gl-text-color; } - .stage { - max-width: 100px; - width: 100px; - } + .stage { + max-width: 100px; + width: 100px; + } - .ci-status-icon svg { - height: 18px; - width: 18px; + .ci-status-icon svg { + height: 18px; + width: 18px; + } } } } -- cgit v1.2.1 From 268a201cce4da7225841b651336835876be43fc2 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 14 Dec 2016 14:24:25 +0000 Subject: Rename file according to review --- .../_badge_graph_icon_with_name_and_action.html.haml | 18 ------------------ app/views/ci/status/_graph_badge.haml | 20 ++++++++++++++++++++ app/views/projects/stage/_graph.html.haml | 2 +- app/views/projects/stage/_in_stage_group.html.haml | 2 +- 4 files changed, 22 insertions(+), 20 deletions(-) delete mode 100644 app/views/ci/status/_badge_graph_icon_with_name_and_action.html.haml create mode 100644 app/views/ci/status/_graph_badge.haml (limited to 'app') diff --git a/app/views/ci/status/_badge_graph_icon_with_name_and_action.html.haml b/app/views/ci/status/_badge_graph_icon_with_name_and_action.html.haml deleted file mode 100644 index 12a55735559..00000000000 --- a/app/views/ci/status/_badge_graph_icon_with_name_and_action.html.haml +++ /dev/null @@ -1,18 +0,0 @@ -- detailed_status = subject.detailed_status(current_user) -- details_path = detailed_status.details_path if detailed_status.has_details? -- klass = "ci-status-icon ci-status-icon-#{detailed_status}" - -- if details_path - = link_to details_path, class: klass, - data: { toggle: 'tooltip', title: "#{subject.name} - #{detailed_status}" } do - %span{ class: klass }= custom_icon(detailed_status.icon) - .ci-status-text= subject.name -- else - %span{ class: klass }= custom_icon(detailed_status.icon) - .ci-status-text= subject.name - -- if detailed_status.has_action? - = link_to detailed_status.action_path, method: detailed_status.action_method, - title: "#{subject.name}: #{detailed_status.action_title}", class: 'ci-action-icon-container' do - %i.ci-action-icon-wrapper - = icon(detailed_status.action_icon, class: detailed_status.action_class) diff --git a/app/views/ci/status/_graph_badge.haml b/app/views/ci/status/_graph_badge.haml new file mode 100644 index 00000000000..7c6d36217f0 --- /dev/null +++ b/app/views/ci/status/_graph_badge.haml @@ -0,0 +1,20 @@ +-# Renders the graph node with both the status icon, status name and action icon + +- detailed_status = subject.detailed_status(current_user) +- details_path = detailed_status.details_path if detailed_status.has_details? +- klass = "ci-status-icon ci-status-icon-#{detailed_status}" + +- if details_path + = link_to details_path, class: klass, + data: { toggle: 'tooltip', title: "#{subject.name} - #{detailed_status}" } do + %span{ class: klass }= custom_icon(detailed_status.icon) + .ci-status-text= subject.name +- else + %span{ class: klass }= custom_icon(detailed_status.icon) + .ci-status-text= subject.name + +- if detailed_status.has_action? + = link_to detailed_status.action_path, method: detailed_status.action_method, + title: "#{subject.name}: #{detailed_status.action_title}", class: 'ci-action-icon-container' do + %i.ci-action-icon-wrapper + = icon(detailed_status.action_icon, class: detailed_status.action_class) diff --git a/app/views/projects/stage/_graph.html.haml b/app/views/projects/stage/_graph.html.haml index ff86d93f354..b70b574e687 100644 --- a/app/views/projects/stage/_graph.html.haml +++ b/app/views/projects/stage/_graph.html.haml @@ -13,7 +13,7 @@ %li.build .curve .build-content - = render 'ci/status/bagde_graph_icon_with_name_and_action', subject: status + = render 'ci/status/graph_badge', subject: status - else %li.build .curve diff --git a/app/views/projects/stage/_in_stage_group.html.haml b/app/views/projects/stage/_in_stage_group.html.haml index e4a7613998d..b03837d1211 100644 --- a/app/views/projects/stage/_in_stage_group.html.haml +++ b/app/views/projects/stage/_in_stage_group.html.haml @@ -10,4 +10,4 @@ %ul - subject.each do |status| %li.dropdown-build - = render 'ci/status/bagde_graph_icon_with_name_and_action', subject: status + = render 'ci/status/graph_badge', subject: status -- cgit v1.2.1 From 262fc28a7d1015b0e1349d665d5527ccee29592f Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Tue, 29 Nov 2016 02:47:02 -0500 Subject: Improve issuable's bulk assignment implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes the case when the user wants to add a label. The user has to use the dropdown’s filter input to look for a label and click it in order to see the bug. Step to reproduce - Select at least two issues, one label should be present in all issues, other label should be present in at least one. - On the label dropdown: Deselect label that is present in all issues, look for another issue using the filter input and click it. - Click on `Update issues` Before: Unmarked label were kept on selected issues. Now: Unmarked label is removed from selected issues --- app/assets/javascripts/dispatcher.js.es6 | 4 +- app/assets/javascripts/gl_dropdown.js | 26 ++-- app/assets/javascripts/issuable.js.es6 | 4 +- .../javascripts/issues_bulk_assignment.js.es6 | 92 ++++++++------ app/assets/javascripts/labels_select.js | 138 ++++++++++++--------- .../merge_requests/_merge_request.html.haml | 2 +- 6 files changed, 144 insertions(+), 122 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/dispatcher.js.es6 b/app/assets/javascripts/dispatcher.js.es6 index 413117c2226..b2ad3d763f6 100644 --- a/app/assets/javascripts/dispatcher.js.es6 +++ b/app/assets/javascripts/dispatcher.js.es6 @@ -36,7 +36,9 @@ case 'projects:merge_requests:index': case 'projects:issues:index': Issuable.init(); - new gl.IssuableBulkActions(); + new gl.IssuableBulkActions({ + page + }); shortcut_handler = new ShortcutsNavigation(); break; case 'projects:issues:show': diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index 9a91018a8e4..c35e8e93d72 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -20,7 +20,6 @@ this.filterInputBlur = (ref = this.options.filterInputBlur) != null ? ref : true; $inputContainer = this.input.parent(); $clearButton = $inputContainer.find('.js-dropdown-input-clear'); - this.indeterminateIds = []; $clearButton.on('click', (function(_this) { // Clear click return function(e) { @@ -345,12 +344,12 @@ $el = $(this); selected = self.rowClicked($el); if (self.options.clicked) { - self.options.clicked(selected, $el, e); + self.options.clicked(selected[0], $el, e, selected[1]); } // Update label right after all modifications in dropdown has been done if (self.options.toggleLabel) { - self.updateLabel(selected, $el, self); + self.updateLabel(selected[0], $el, self); } $el.trigger('blur'); @@ -441,12 +440,6 @@ this.resetRows(); this.addArrowKeyEvent(); - if (this.options.setIndeterminateIds) { - this.options.setIndeterminateIds.call(this); - } - if (this.options.setActiveIds) { - this.options.setActiveIds.call(this); - } // Makes indeterminate items effective if (this.fullData && this.dropdown.find('.dropdown-menu-toggle').hasClass('js-filter-bulk-update')) { this.parseData(this.fullData); @@ -480,11 +473,6 @@ if (this.options.filterable) { $input.blur().val(""); } - // Triggering 'keyup' will re-render the dropdown which is not always required - // specially if we want to keep the state of the dropdown needed for bulk-assignment - if (!this.options.persistWhenHide) { - $input.trigger("input"); - } if (this.dropdown.find(".dropdown-toggle-page").length) { $('.dropdown-menu', this.dropdown).removeClass(PAGE_TWO_CLASS); } @@ -617,7 +605,8 @@ }; GitLabDropdown.prototype.rowClicked = function(el) { - var field, fieldName, groupName, isInput, selectedIndex, selectedObject, value; + var field, fieldName, groupName, isInput, selectedIndex, selectedObject, value, markedIds, unmarkedIds, i, isMarking; + fieldName = this.options.fieldName; isInput = $(this.el).is('input'); if (this.renderedData) { @@ -638,7 +627,7 @@ el.addClass(ACTIVE_CLASS); } - return selectedObject; + return [selectedObject]; } field = []; @@ -656,6 +645,7 @@ } if (el.hasClass(ACTIVE_CLASS)) { + isMarking = false; el.removeClass(ACTIVE_CLASS); if (field && field.length) { if (isInput) { @@ -665,6 +655,7 @@ } } } else if (el.hasClass(INDETERMINATE_CLASS)) { + isMarking = true; el.addClass(ACTIVE_CLASS); el.removeClass(INDETERMINATE_CLASS); if (field && field.length && value == null) { @@ -674,6 +665,7 @@ this.addInput(fieldName, value, selectedObject); } } else { + isMarking = true; if (!this.options.multiSelect || el.hasClass('dropdown-clear-active')) { this.dropdown.find("." + ACTIVE_CLASS).removeClass(ACTIVE_CLASS); if (!isInput) { @@ -694,7 +686,7 @@ } } - return selectedObject; + return [selectedObject, isMarking]; }; GitLabDropdown.prototype.focusTextInput = function() { diff --git a/app/assets/javascripts/issuable.js.es6 b/app/assets/javascripts/issuable.js.es6 index 46503c290ae..5f6c1bbdc90 100644 --- a/app/assets/javascripts/issuable.js.es6 +++ b/app/assets/javascripts/issuable.js.es6 @@ -141,6 +141,9 @@ const $issuesOtherFilters = $('.issues-other-filters'); const $issuesBulkUpdate = $('.issues_bulk_update'); + this.issuableBulkActions.willUpdateLabels = false; + this.issuableBulkActions.setOriginalDropdownData(); + if ($checkedIssues.length > 0) { let ids = $.map($checkedIssues, function(value) { return $(value).data('id'); @@ -152,7 +155,6 @@ $updateIssuesIds.val([]); $issuesBulkUpdate.hide(); $issuesOtherFilters.show(); - this.issuableBulkActions.willUpdateLabels = false; } return true; }, diff --git a/app/assets/javascripts/issues_bulk_assignment.js.es6 b/app/assets/javascripts/issues_bulk_assignment.js.es6 index 9697fb33566..8c0eaac8924 100644 --- a/app/assets/javascripts/issues_bulk_assignment.js.es6 +++ b/app/assets/javascripts/issues_bulk_assignment.js.es6 @@ -2,9 +2,10 @@ ((global) => { class IssuableBulkActions { - constructor({ container, form, issues } = {}) { - this.container = container || $('.content'), + constructor({ container, form, issues, page } = {}) { + this.prefixId = page === 'projects:merge_requests:index' ? 'merge_request_' : 'issue_'; this.form = form || this.getElement('.bulk-update'); + this.$labelDropdown = this.form.find('.js-label-select'); this.issues = issues || this.getElement('.issues-list .issue'); this.form.data('bulkActions', this); this.willUpdateLabels = false; @@ -13,10 +14,6 @@ Issuable.initChecks(); } - getElement(selector) { - return this.container.find(selector); - } - bindEvents() { return this.form.off('submit').on('submit', this.onFormSubmit.bind(this)); } @@ -70,10 +67,7 @@ getUnmarkedIndeterminedLabels() { const result = []; - const labelsToKeep = []; - - this.getElement('.labels-filter .is-indeterminate') - .each((i, el) => labelsToKeep.push($(el).data('labelId'))); + const labelsToKeep = this.$labelDropdown.data('indeterminate'); this.getLabelsFromSelection().forEach((id) => { if (labelsToKeep.indexOf(id) === -1) { @@ -103,45 +97,63 @@ } }; if (this.willUpdateLabels) { - this.getLabelsToApply().map(function(id) { - return formData.update.add_label_ids.push(id); - }); - this.getLabelsToRemove().map(function(id) { - return formData.update.remove_label_ids.push(id); - }); + formData.update.add_label_ids = this.$labelDropdown.data('marked'); + formData.update.remove_label_ids = this.$labelDropdown.data('unmarked'); } return formData; } - getLabelsToApply() { - const labelIds = []; - const $labels = this.form.find('.labels-filter input[name="update[label_ids][]"]'); - $labels.each(function(k, label) { - if (label) { - return labelIds.push(parseInt($(label).val())); - } - }); - return labelIds; + setOriginalDropdownData() { + $('.bulk-update .js-label-select').data('common', this.getOriginalCommonIds()); + $('.bulk-update .js-label-select').data('marked', this.getOriginalMarkedIds()); + $('.bulk-update .js-label-select').data('indeterminate', this.getOriginalIndeterminateIds()); } + // From issuable's initial bulk selection + getOriginalCommonIds() { + let labelIds = []; - /** - * Returns Label IDs that will be removed from issue selection - * @return {Array} Array of labels IDs - */ + this.getElement('.selected_issue:checked').each((i, el) => { + labelIds.push(this.getElement(`#${this.prefixId}${el.dataset.id}`).data('labels')); + }); + return _.intersection.apply(this, labelIds); + } - getLabelsToRemove() { - const result = []; - const indeterminatedLabels = this.getUnmarkedIndeterminedLabels(); - const labelsToApply = this.getLabelsToApply(); - indeterminatedLabels.map(function(id) { - // We need to exclude label IDs that will be applied - // By not doing this will cause issues from selection to not add labels at all - if (labelsToApply.indexOf(id) === -1) { - return result.push(id); - } + // From issuable's initial bulk selection + getOriginalMarkedIds() { + var labelIds = []; + this.getElement('.selected_issue:checked').each((i, el) => { + labelIds.push(this.getElement(`#${this.prefixId}${el.dataset.id}`).data('labels')); }); - return result; + return _.intersection.apply(_, labelIds); + } + + // From issuable's initial bulk selection + getOriginalIndeterminateIds() { + let uniqueIds = []; + let labelIds = []; + let issuableLabels = []; + + // Collect unique label IDs for all checked issues + this.getElement('.selected_issue:checked').each((i, el) => { + issuableLabels = this.getElement(`#${this.prefixId}${el.dataset.id}`).data('labels'); + issuableLabels.forEach((labelId) => { + // Store unique IDs + if (uniqueIds.indexOf(labelId) === -1) { + uniqueIds.push(labelId); + } + }); + // Store array of IDs per issuable + labelIds.push(issuableLabels); + }); + // Add uniqueIds to add it as argument for _.intersection + labelIds.unshift(uniqueIds); + // Return IDs that are present but not in all selected issueables + return _.difference(uniqueIds, _.intersection.apply(this, labelIds)); + } + + getElement(selector) { + return $('.content').find(selector); } } diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js index f334f35594d..1d79807785f 100644 --- a/app/assets/javascripts/labels_select.js +++ b/app/assets/javascripts/labels_select.js @@ -5,8 +5,9 @@ var _this; _this = this; $('.js-label-select').each(function(i, dropdown) { - var $block, $colorPreview, $dropdown, $form, $loading, $selectbox, $sidebarCollapsedValue, $value, abilityName, defaultLabel, enableLabelCreateButton, issueURLSplit, issueUpdateURL, labelHTMLTemplate, labelNoneHTMLTemplate, labelUrl, namespacePath, projectPath, saveLabelData, selectedLabel, showAny, showNo, $sidebarLabelTooltip, initialSelected, $toggleText, fieldName, useId, propertyName, showMenuAbove; + var $block, $colorPreview, $dropdown, $form, $loading, $selectbox, $sidebarCollapsedValue, $value, abilityName, defaultLabel, enableLabelCreateButton, issueURLSplit, issueUpdateURL, labelHTMLTemplate, labelNoneHTMLTemplate, labelUrl, namespacePath, projectPath, saveLabelData, selectedLabel, showAny, showNo, $sidebarLabelTooltip, initialSelected, $toggleText, fieldName, useId, propertyName, showMenuAbove, $container; $dropdown = $(dropdown); + $dropdownContainer = $dropdown.closest('.labels-filter') $toggleText = $dropdown.find('.dropdown-toggle-text'); namespacePath = $dropdown.data('namespace-path'); projectPath = $dropdown.data('project-path'); @@ -122,7 +123,7 @@ }); }); }; - return $dropdown.glDropdown({ + $dropdown.glDropdown({ showMenuAbove: showMenuAbove, data: function(term, callback) { return $.ajax({ @@ -169,33 +170,35 @@ }); }, renderRow: function(label, instance) { - var $a, $li, active, color, colorEl, indeterminate, removesAll, selectedClass, spacing; + var $a, $li, color, colorEl, indeterminate, removesAll, selectedClass, spacing, i, marked; $li = $('
  • '); $a = $(''); selectedClass = []; removesAll = label.id <= 0 || (label.id == null); if ($dropdown.hasClass('js-filter-bulk-update')) { - indeterminate = instance.indeterminateIds; - active = instance.activeIds; + indeterminate = $dropdown.data('indeterminate') || []; + marked = $dropdown.data('marked') || []; + if (indeterminate.indexOf(label.id) !== -1) { selectedClass.push('is-indeterminate'); } - if (active.indexOf(label.id) !== -1) { + + if (marked.indexOf(label.id) !== -1) { // Remove is-indeterminate class if the item will be marked as active i = selectedClass.indexOf('is-indeterminate'); if (i !== -1) { selectedClass.splice(i, 1); } selectedClass.push('is-active'); - // Add input manually - instance.addInput(this.fieldName, label.id); } - } - if (this.id(label) && $form.find("input[type='hidden'][name='" + ($dropdown.data('fieldName')) + "'][value='" + this.id(label).toString().replace(/'/g, '\\\'') + "']").length) { - selectedClass.push('is-active'); - } - if ($dropdown.hasClass('js-multiselect') && removesAll) { - selectedClass.push('dropdown-clear-active'); + } else { + if (this.id(label) && $form.find("input[type='hidden'][name='" + ($dropdown.data('fieldName')) + "'][value='" + this.id(label).toString().replace(/'/g, '\\\'') + "']").length) { + selectedClass.push('is-active'); + } + + if ($dropdown.hasClass('js-multiselect') && removesAll) { + selectedClass.push('dropdown-clear-active'); + } } if (label.duplicate) { spacing = 100 / label.color.length; @@ -231,7 +234,6 @@ // Return generated html return $li.html($a).prop('outerHTML'); }, - persistWhenHide: $dropdown.data('persistWhenHide'), search: { fields: ['title'] }, @@ -310,18 +312,15 @@ } } } - if ($dropdown.hasClass('js-filter-bulk-update')) { - // If we are persisting state we need the classes - if (!this.options.persistWhenHide) { - return $dropdown.parent().find('.is-active, .is-indeterminate').removeClass(); - } - } }, multiSelect: $dropdown.hasClass('js-multiselect'), vue: $dropdown.hasClass('js-issue-board-sidebar'), - clicked: function(label, $el, e) { + clicked: function(label, $el, e, isMarking) { var isIssueIndex, isMRIndex, page; - _this.enableBulkLabelDropdown(); + + page = $('body').data('page'); + isIssueIndex = page === 'projects:issues:index'; + isMRIndex = page === 'projects:merge_requests:index'; if ($dropdown.parent().find('.is-active:not(.dropdown-clear-active)').length) { $dropdown.parent() @@ -330,12 +329,11 @@ } if ($dropdown.hasClass('js-filter-bulk-update') || $dropdown.hasClass('js-issuable-form-dropdown')) { + _this.enableBulkLabelDropdown(); + _this.setDropdownData($dropdown, isMarking, this.id(label)); return; } - page = $('body').data('page'); - isIssueIndex = page === 'projects:issues:index'; - isMRIndex = page === 'projects:merge_requests:index'; if ($('html').hasClass('issue-boards-page') && !$dropdown.hasClass('js-issue-board-sidebar')) { if (label.isAny) { gl.issueBoards.BoardsStore.state.filters['label_name'] = []; @@ -397,17 +395,10 @@ } } }, - setIndeterminateIds: function() { - if (this.dropdown.find('.dropdown-menu-toggle').hasClass('js-filter-bulk-update')) { - return this.indeterminateIds = _this.getIndeterminateIds(); - } - }, - setActiveIds: function() { - if (this.dropdown.find('.dropdown-menu-toggle').hasClass('js-filter-bulk-update')) { - return this.activeIds = _this.getActiveIds(); - } - } }); + + // Set dropdown data + _this.setOriginalDropdownData($dropdownContainer, $dropdown); }); this.bindEvents(); } @@ -420,34 +411,9 @@ if ($('.selected_issue:checked').length) { return; } - // Remove inputs - $('.issues_bulk_update .labels-filter input[type="hidden"]').remove(); - // Also restore button text return $('.issues_bulk_update .labels-filter .dropdown-toggle-text').text('Label'); }; - LabelsSelect.prototype.getIndeterminateIds = function() { - var label_ids; - label_ids = []; - $('.selected_issue:checked').each(function(i, el) { - var issue_id; - issue_id = $(el).data('id'); - return label_ids.push($("#issue_" + issue_id).data('labels')); - }); - return _.flatten(label_ids); - }; - - LabelsSelect.prototype.getActiveIds = function() { - var label_ids; - label_ids = []; - $('.selected_issue:checked').each(function(i, el) { - var issue_id; - issue_id = $(el).data('id'); - return label_ids.push($("#issue_" + issue_id).data('labels')); - }); - return _.intersection.apply(_, label_ids); - }; - LabelsSelect.prototype.enableBulkLabelDropdown = function() { var issuableBulkActions; if ($('.selected_issue:checked').length) { @@ -456,8 +422,56 @@ } }; - return LabelsSelect; + LabelsSelect.prototype.setDropdownData = function($dropdown, isMarking, value) { + var issuableBulkActions = $('.bulk-update').data('bulkActions'); + markedIds = $dropdown.data('marked') || []; + unmarkedIds = $dropdown.data('unmarked') || []; + indeterminateIds = $dropdown.data('indeterminate') || []; + + if (isMarking) { + markedIds.push(value); + + i = indeterminateIds.indexOf(value); + if (i > -1) { + indeterminateIds.splice(i, 1); + } + + i = unmarkedIds.indexOf(value); + if (i > -1) { + unmarkedIds.splice(i, 1); + } + } else { + // If marked item (not common) is unmarked + i = markedIds.indexOf(value); + if (i > -1) { + markedIds.splice(i, 1); + } + + // If an indeterminate item is being unmarked + if (issuableBulkActions.getOriginalIndeterminateIds().indexOf(value) > -1) { + unmarkedIds.push(value); + } + + // If a marked item is being unmarked + // (a marked item could also be a label that is present in all selection) + if (issuableBulkActions.getOriginalCommonIds().indexOf(value) > -1) { + unmarkedIds.push(value); + } + } + + $dropdown.data('marked', markedIds); + $dropdown.data('unmarked', unmarkedIds); + $dropdown.data('indeterminate', indeterminateIds); + }; + + LabelsSelect.prototype.setOriginalDropdownData = function($container, $dropdown) { + var labels = []; + $container.find('[name="label_name[]"]').map(function() { return labels.push(this.value); }); + $dropdown.data('marked', labels); + }; + + return LabelsSelect; })(); }).call(this); diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml index fa189ae62d8..53ba124b65e 100644 --- a/app/views/projects/merge_requests/_merge_request.html.haml +++ b/app/views/projects/merge_requests/_merge_request.html.haml @@ -1,4 +1,4 @@ -%li{ class: mr_css_classes(merge_request) } +%li{ id: dom_id(merge_request), class: mr_css_classes(merge_request), data: { labels: merge_request.label_ids, id: merge_request.id } } - if @bulk_edit .issue-check = check_box_tag dom_id(merge_request, "selected"), nil, false, 'data-id' => merge_request.id, class: "selected_issue" -- cgit v1.2.1 From 51b2ffaf7ecbfbc7604a38b66576af008aa8599f Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Tue, 13 Dec 2016 16:38:21 -0500 Subject: Address feedback --- app/assets/javascripts/dispatcher.js.es6 | 6 +----- app/assets/javascripts/gl_dropdown.js | 2 +- app/assets/javascripts/issues_bulk_assignment.js.es6 | 14 ++++++++------ app/assets/javascripts/labels_select.js | 18 +++++++++++++----- 4 files changed, 23 insertions(+), 17 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/dispatcher.js.es6 b/app/assets/javascripts/dispatcher.js.es6 index b2ad3d763f6..359c869cb9a 100644 --- a/app/assets/javascripts/dispatcher.js.es6 +++ b/app/assets/javascripts/dispatcher.js.es6 @@ -37,7 +37,7 @@ case 'projects:issues:index': Issuable.init(); new gl.IssuableBulkActions({ - page + prefixId: page === 'projects:merge_requests:index' ? 'merge_request_' : 'issue_' }); shortcut_handler = new ShortcutsNavigation(); break; @@ -108,10 +108,6 @@ new ZenMode(); new MergedButtons(); break; - case 'projects:merge_requests:index': - shortcut_handler = new ShortcutsNavigation(); - Issuable.init(); - break; case 'dashboard:activity': new gl.Activities(); break; diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index c35e8e93d72..ef5bfb709c0 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -605,7 +605,7 @@ }; GitLabDropdown.prototype.rowClicked = function(el) { - var field, fieldName, groupName, isInput, selectedIndex, selectedObject, value, markedIds, unmarkedIds, i, isMarking; + var field, fieldName, groupName, isInput, selectedIndex, selectedObject, value, isMarking; fieldName = this.options.fieldName; isInput = $(this.el).is('input'); diff --git a/app/assets/javascripts/issues_bulk_assignment.js.es6 b/app/assets/javascripts/issues_bulk_assignment.js.es6 index 8c0eaac8924..b95c0ffb5f4 100644 --- a/app/assets/javascripts/issues_bulk_assignment.js.es6 +++ b/app/assets/javascripts/issues_bulk_assignment.js.es6 @@ -2,8 +2,8 @@ ((global) => { class IssuableBulkActions { - constructor({ container, form, issues, page } = {}) { - this.prefixId = page === 'projects:merge_requests:index' ? 'merge_request_' : 'issue_'; + constructor({ container, form, issues, prefixId } = {}) { + this.prefixId = prefixId || 'issue_'; this.form = form || this.getElement('.bulk-update'); this.$labelDropdown = this.form.find('.js-label-select'); this.issues = issues || this.getElement('.issues-list .issue'); @@ -104,9 +104,10 @@ } setOriginalDropdownData() { - $('.bulk-update .js-label-select').data('common', this.getOriginalCommonIds()); - $('.bulk-update .js-label-select').data('marked', this.getOriginalMarkedIds()); - $('.bulk-update .js-label-select').data('indeterminate', this.getOriginalIndeterminateIds()); + let $labelSelect = $('.bulk-update .js-label-select'); + $labelSelect.data('common', this.getOriginalCommonIds()); + $labelSelect.data('marked', this.getOriginalMarkedIds()); + $labelSelect.data('indeterminate', this.getOriginalIndeterminateIds()); } // From issuable's initial bulk selection @@ -153,7 +154,8 @@ } getElement(selector) { - return $('.content').find(selector); + this.scopeEl = this.scopeEl || $('.content'); + return this.scopeEl.find(selector); } } diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js index 1d79807785f..2022a2f286f 100644 --- a/app/assets/javascripts/labels_select.js +++ b/app/assets/javascripts/labels_select.js @@ -7,7 +7,7 @@ $('.js-label-select').each(function(i, dropdown) { var $block, $colorPreview, $dropdown, $form, $loading, $selectbox, $sidebarCollapsedValue, $value, abilityName, defaultLabel, enableLabelCreateButton, issueURLSplit, issueUpdateURL, labelHTMLTemplate, labelNoneHTMLTemplate, labelUrl, namespacePath, projectPath, saveLabelData, selectedLabel, showAny, showNo, $sidebarLabelTooltip, initialSelected, $toggleText, fieldName, useId, propertyName, showMenuAbove, $container; $dropdown = $(dropdown); - $dropdownContainer = $dropdown.closest('.labels-filter') + $dropdownContainer = $dropdown.closest('.labels-filter'); $toggleText = $dropdown.find('.dropdown-toggle-text'); namespacePath = $dropdown.data('namespace-path'); projectPath = $dropdown.data('project-path'); @@ -170,7 +170,7 @@ }); }, renderRow: function(label, instance) { - var $a, $li, color, colorEl, indeterminate, removesAll, selectedClass, spacing, i, marked; + var $a, $li, color, colorEl, indeterminate, removesAll, selectedClass, spacing, i, marked, dropdownName, dropdownValue; $li = $('
  • '); $a = $(''); selectedClass = []; @@ -192,8 +192,13 @@ selectedClass.push('is-active'); } } else { - if (this.id(label) && $form.find("input[type='hidden'][name='" + ($dropdown.data('fieldName')) + "'][value='" + this.id(label).toString().replace(/'/g, '\\\'') + "']").length) { - selectedClass.push('is-active'); + if (this.id(label)) { + dropdownName = $dropdown.data('fieldName'); + dropdownValue = this.id(label).toString().replace(/'/g, '\\\''); + + if ($form.find("input[type='hidden'][name='" + dropdownName + "'][value='" + dropdownValue + "']").length) { + selectedClass.push('is-active'); + } } if ($dropdown.hasClass('js-multiselect') && removesAll) { @@ -423,6 +428,7 @@ }; LabelsSelect.prototype.setDropdownData = function($dropdown, isMarking, value) { + var i, markedIds, unmarkedIds, indeterminateIds; var issuableBulkActions = $('.bulk-update').data('bulkActions'); markedIds = $dropdown.data('marked') || []; @@ -467,7 +473,9 @@ LabelsSelect.prototype.setOriginalDropdownData = function($container, $dropdown) { var labels = []; - $container.find('[name="label_name[]"]').map(function() { return labels.push(this.value); }); + $container.find('[name="label_name[]"]').map(function() { + return labels.push(this.value); + }); $dropdown.data('marked', labels); }; -- cgit v1.2.1 From 281237d7731cfa6669dd650fdfabfe612082d47f Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 14 Dec 2016 15:04:26 +0000 Subject: Changes after review Remove empty line --- app/models/ability.rb | 6 ------ app/views/ci/status/_graph_badge.haml | 3 +-- 2 files changed, 1 insertion(+), 8 deletions(-) (limited to 'app') diff --git a/app/models/ability.rb b/app/models/ability.rb index ce461caf686..fa8f8bc3a5f 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -1,10 +1,4 @@ class Ability - module Allowable - def can?(user, action, subject) - Ability.allowed?(user, action, subject) - end - end - class << self # Given a list of users and a project this method returns the users that can # read the given project. diff --git a/app/views/ci/status/_graph_badge.haml b/app/views/ci/status/_graph_badge.haml index 7c6d36217f0..839b4334713 100644 --- a/app/views/ci/status/_graph_badge.haml +++ b/app/views/ci/status/_graph_badge.haml @@ -5,8 +5,7 @@ - klass = "ci-status-icon ci-status-icon-#{detailed_status}" - if details_path - = link_to details_path, class: klass, - data: { toggle: 'tooltip', title: "#{subject.name} - #{detailed_status}" } do + = link_to details_path, data: { toggle: 'tooltip', title: "#{subject.name} - #{detailed_status}" } do %span{ class: klass }= custom_icon(detailed_status.icon) .ci-status-text= subject.name - else -- cgit v1.2.1 From 8a6b4c1f7aadd948b5ab5c3525eca67e298c8df4 Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Tue, 13 Dec 2016 18:01:40 -0500 Subject: Remove white space between nav items --- .../javascripts/environments/components/environment.js.es6 | 3 +-- app/views/admin/logs/show.html.haml | 2 +- app/views/dashboard/_activity_head.html.haml | 4 ++-- app/views/dashboard/todos/index.html.haml | 4 ++-- app/views/projects/pipelines/index.html.haml | 8 ++++---- app/views/shared/_milestones_filter.html.haml | 6 +++--- app/views/shared/builds/_tabs.html.haml | 8 ++++---- app/views/shared/issuable/_nav.html.haml | 10 +++++----- 8 files changed, 22 insertions(+), 23 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/environments/components/environment.js.es6 b/app/assets/javascripts/environments/components/environment.js.es6 index 1db29dd47fb..88c3d257cea 100644 --- a/app/assets/javascripts/environments/components/environment.js.es6 +++ b/app/assets/javascripts/environments/components/environment.js.es6 @@ -164,8 +164,7 @@ {{state.availableCounter}} -
  • -
  • +
  • Stopped diff --git a/app/views/admin/logs/show.html.haml b/app/views/admin/logs/show.html.haml index 824edd171f3..0a954c20fcd 100644 --- a/app/views/admin/logs/show.html.haml +++ b/app/views/admin/logs/show.html.haml @@ -8,7 +8,7 @@ %div{ class: container_class } %ul.nav-links.log-tabs - loggers.each do |klass| - %li{ class: (klass == Gitlab::GitLogger ? 'active' : '') } + %li{ class: (klass == Gitlab::GitLogger ? 'active' : '') }> = link_to klass::file_name, "##{klass::file_name_noext}", 'data-toggle' => 'tab' .row-content-block diff --git a/app/views/dashboard/_activity_head.html.haml b/app/views/dashboard/_activity_head.html.haml index b78e70ebc1e..02b94beee92 100644 --- a/app/views/dashboard/_activity_head.html.haml +++ b/app/views/dashboard/_activity_head.html.haml @@ -1,7 +1,7 @@ %ul.nav-links - %li{ class: ("active" unless params[:filter]) } + %li{ class: ("active" unless params[:filter]) }> = link_to activity_dashboard_path, class: 'shortcuts-activity', data: {placement: 'right'} do Your Projects - %li{ class: ("active" if params[:filter] == 'starred') } + %li{ class: ("active" if params[:filter] == 'starred') }> = link_to activity_dashboard_path(filter: 'starred'), data: {placement: 'right'} do Starred Projects diff --git a/app/views/dashboard/todos/index.html.haml b/app/views/dashboard/todos/index.html.haml index 62f52086be4..ea95e91eada 100644 --- a/app/views/dashboard/todos/index.html.haml +++ b/app/views/dashboard/todos/index.html.haml @@ -5,14 +5,14 @@ .top-area %ul.nav-links - todo_pending_active = ('active' if params[:state].blank? || params[:state] == 'pending') - %li{class: "todos-pending #{todo_pending_active}"} + %li{class: "todos-pending #{todo_pending_active}"}> = link_to todos_filter_path(state: 'pending') do %span To do %span.badge = number_with_delimiter(todos_pending_count) - todo_done_active = ('active' if params[:state] == 'done') - %li{class: "todos-done #{todo_done_active}"} + %li{class: "todos-done #{todo_done_active}"}> = link_to todos_filter_path(state: 'done') do %span Done diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index e1e787dbde4..030cd8ef78f 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -5,23 +5,23 @@ %div{ class: container_class } .top-area %ul.nav-links - %li{class: ('active' if @scope.nil?)} + %li{class: ('active' if @scope.nil?)}> = link_to project_pipelines_path(@project) do All %span.badge.js-totalbuilds-count = number_with_delimiter(@pipelines_count) - %li{class: ('active' if @scope == 'running')} + %li{class: ('active' if @scope == 'running')}> = link_to project_pipelines_path(@project, scope: :running) do Running %span.badge.js-running-count = number_with_delimiter(@running_or_pending_count) - %li{class: ('active' if @scope == 'branches')} + %li{class: ('active' if @scope == 'branches')}> = link_to project_pipelines_path(@project, scope: :branches) do Branches - %li{class: ('active' if @scope == 'tags')} + %li{class: ('active' if @scope == 'tags')}> = link_to project_pipelines_path(@project, scope: :tags) do Tags diff --git a/app/views/shared/_milestones_filter.html.haml b/app/views/shared/_milestones_filter.html.haml index 73d288e2236..186ed4a7c8b 100644 --- a/app/views/shared/_milestones_filter.html.haml +++ b/app/views/shared/_milestones_filter.html.haml @@ -2,17 +2,17 @@ - counts = milestone_counts(@project.milestones) %ul.nav-links - %li{class: milestone_class_for_state(params[:state], 'opened', true)} + %li{class: milestone_class_for_state(params[:state], 'opened', true)}> = link_to milestones_filter_path(state: 'opened') do Open - if @project %span.badge #{counts[:opened]} - %li{class: milestone_class_for_state(params[:state], 'closed')} + %li{class: milestone_class_for_state(params[:state], 'closed')}> = link_to milestones_filter_path(state: 'closed') do Closed - if @project %span.badge #{counts[:closed]} - %li{class: milestone_class_for_state(params[:state], 'all')} + %li{class: milestone_class_for_state(params[:state], 'all')}> = link_to milestones_filter_path(state: 'all') do All - if @project diff --git a/app/views/shared/builds/_tabs.html.haml b/app/views/shared/builds/_tabs.html.haml index 60353aee7f1..b6047ece592 100644 --- a/app/views/shared/builds/_tabs.html.haml +++ b/app/views/shared/builds/_tabs.html.haml @@ -1,23 +1,23 @@ %ul.nav-links - %li{ class: ('active' if scope.nil?) } + %li{ class: ('active' if scope.nil?) }> = link_to build_path_proc.call(nil) do All %span.badge.js-totalbuilds-count = number_with_delimiter(all_builds.count(:id)) - %li{ class: ('active' if scope == 'pending') } + %li{ class: ('active' if scope == 'pending') }> = link_to build_path_proc.call('pending') do Pending %span.badge = number_with_delimiter(all_builds.pending.count(:id)) - %li{ class: ('active' if scope == 'running') } + %li{ class: ('active' if scope == 'running') }> = link_to build_path_proc.call('running') do Running %span.badge = number_with_delimiter(all_builds.running.count(:id)) - %li{ class: ('active' if scope == 'finished') } + %li{ class: ('active' if scope == 'finished') }> = link_to build_path_proc.call('finished') do Finished %span.badge diff --git a/app/views/shared/issuable/_nav.html.haml b/app/views/shared/issuable/_nav.html.haml index 0af92b59584..d938edf4dbd 100644 --- a/app/views/shared/issuable/_nav.html.haml +++ b/app/views/shared/issuable/_nav.html.haml @@ -3,23 +3,23 @@ - issuables = @issues || @merge_requests %ul.nav-links.issues-state-filters - %li{class: ("active" if params[:state] == 'opened')} + %li{class: ("active" if params[:state] == 'opened')}> = link_to page_filter_path(state: 'opened', label: true), id: 'state-opened', title: "Filter by #{page_context_word} that are currently opened." do #{issuables_state_counter_text(type, :opened)} - if type == :merge_requests - %li{class: ("active" if params[:state] == 'merged')} + %li{class: ("active" if params[:state] == 'merged')}> = link_to page_filter_path(state: 'merged', label: true), id: 'state-merged', title: 'Filter by merge requests that are currently merged.' do #{issuables_state_counter_text(type, :merged)} - %li{class: ("active" if params[:state] == 'closed')} + %li{class: ("active" if params[:state] == 'closed')}> = link_to page_filter_path(state: 'closed', label: true), id: 'state-closed', title: 'Filter by merge requests that are currently closed and unmerged.' do #{issuables_state_counter_text(type, :closed)} - else - %li{class: ("active" if params[:state] == 'closed')} + %li{class: ("active" if params[:state] == 'closed')}> = link_to page_filter_path(state: 'closed', label: true), id: 'state-all', title: 'Filter by issues that are currently closed.' do #{issuables_state_counter_text(type, :closed)} - %li{class: ("active" if params[:state] == 'all')} + %li{class: ("active" if params[:state] == 'all')}> = link_to page_filter_path(state: 'all', label: true), id: 'state-all', title: "Show all #{page_context_word}." do #{issuables_state_counter_text(type, :all)} -- cgit v1.2.1 From 7cced60069c248156decf6ceabc4d1f447e47ff7 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 14 Dec 2016 21:00:06 +0800 Subject: Introduce latest_status and add a few tests Feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7333#note_20003268 --- app/models/ci/pipeline.rb | 4 ++++ app/models/commit.rb | 4 ++-- app/services/ci/image_for_build_service.rb | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index aa0367227a8..9edfc75eac7 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -98,6 +98,10 @@ module Ci end.where(id: max_id.group(:ref, :sha)) end + def self.latest_status(ref = nil) + latest(ref).status + end + def self.latest_successful_for(ref) success.latest(ref).first end diff --git a/app/models/commit.rb b/app/models/commit.rb index 91c7970fca6..69cfc47f5bf 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -230,7 +230,7 @@ class Commit return @statuses[ref] if @statuses.key?(ref) - @statuses[ref] = pipelines.latest(ref).status + @statuses[ref] = pipelines.latest_status(ref) end def revert_branch_name @@ -266,7 +266,7 @@ class Commit @merged_merge_request_hash ||= Hash.new do |hash, user| hash[user] = merged_merge_request_no_cache(user) end - + @merged_merge_request_hash[current_user] end diff --git a/app/services/ci/image_for_build_service.rb b/app/services/ci/image_for_build_service.rb index 1eeb0e2363a..240ddabec36 100644 --- a/app/services/ci/image_for_build_service.rb +++ b/app/services/ci/image_for_build_service.rb @@ -5,7 +5,7 @@ module Ci sha = opts[:sha] || ref_sha(project, ref) pipelines = project.pipelines.where(sha: sha) - image_name = image_for_status(pipelines.latest(ref).status) + image_name = image_for_status(pipelines.latest_status(ref)) image_path = Rails.root.join('public/ci', image_name) OpenStruct.new(path: image_path, name: image_name) -- cgit v1.2.1 From 7f9d1ad378e9d00dce8882231e8476faf7067f61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Iv=C3=A1n=20Vargas=20L=C3=B3pez?= Date: Wed, 14 Dec 2016 09:44:04 -0600 Subject: Fixed the use of display:flex to display:block --- app/assets/stylesheets/pages/editor.scss | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/editor.scss b/app/assets/stylesheets/pages/editor.scss index 935f157b33d..fea9a6b5009 100644 --- a/app/assets/stylesheets/pages/editor.scss +++ b/app/assets/stylesheets/pages/editor.scss @@ -132,26 +132,25 @@ } .new-file-name { - margin-bottom: 0; max-width: none; width: 100%; } .file-buttons { - display: flex; - flex-direction: column; + display: block; width: 100%; - margin-bottom: 7px; .soft-wrap-toggle { - margin: 7px 0 0; + width: 100%; + margin: 7px 0; } .encoding-selector, .license-selector, .gitignore-selector, .gitlab-ci-yml-selector { - margin: 7px 0 0; + display: block; + margin: 7px 0; button { width: 100%; -- cgit v1.2.1 From f796840fd33d7df2c1de8f965596b5486b1fbf24 Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Wed, 14 Dec 2016 11:40:45 -0500 Subject: Add Object.assign polyfill --- app/assets/javascripts/extensions/object.js.es6 | 27 +++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 app/assets/javascripts/extensions/object.js.es6 (limited to 'app') diff --git a/app/assets/javascripts/extensions/object.js.es6 b/app/assets/javascripts/extensions/object.js.es6 new file mode 100644 index 00000000000..f8cdedd507b --- /dev/null +++ b/app/assets/javascripts/extensions/object.js.es6 @@ -0,0 +1,27 @@ +/* eslint-disable */ + +// Taken from https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Polyfill +if (typeof Object.assign != 'function') { + Object.assign = function (target, varArgs) { // .length of function is 2 + 'use strict'; + if (target == null) { // TypeError if undefined or null + throw new TypeError('Cannot convert undefined or null to object'); + } + + var to = Object(target); + + for (var index = 1; index < arguments.length; index++) { + var nextSource = arguments[index]; + + if (nextSource != null) { // Skip over if undefined or null + for (var nextKey in nextSource) { + // Avoid bugs when hasOwnProperty is shadowed + if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { + to[nextKey] = nextSource[nextKey]; + } + } + } + } + return to; + }; +} -- cgit v1.2.1 From 2d170a20dc4cd3423ac7994c797cae8fbed263ba Mon Sep 17 00:00:00 2001 From: Munken Date: Fri, 9 Dec 2016 00:15:08 +0000 Subject: Render math in Asciidoc and Markdown with KaTeX using code blocks --- app/assets/javascripts/blob_edit/edit_blob.js | 2 +- app/assets/javascripts/notes.js | 6 +- app/assets/javascripts/preview_markdown.js | 2 +- app/assets/javascripts/render_gfm.js | 16 ++++++ app/assets/javascripts/render_math.js | 55 ++++++++++++++++++ app/assets/javascripts/syntax_highlight.js | 28 +++++++++ app/assets/javascripts/syntax_highlight.js.erb | 79 -------------------------- 7 files changed, 104 insertions(+), 84 deletions(-) create mode 100644 app/assets/javascripts/render_gfm.js create mode 100644 app/assets/javascripts/render_math.js create mode 100644 app/assets/javascripts/syntax_highlight.js delete mode 100644 app/assets/javascripts/syntax_highlight.js.erb (limited to 'app') diff --git a/app/assets/javascripts/blob_edit/edit_blob.js b/app/assets/javascripts/blob_edit/edit_blob.js index 0c74aaaa852..51e2094d26a 100644 --- a/app/assets/javascripts/blob_edit/edit_blob.js +++ b/app/assets/javascripts/blob_edit/edit_blob.js @@ -57,7 +57,7 @@ content: this.editor.getValue() }, function(response) { currentPane.empty().append(response); - return currentPane.syntaxHighlight(); + return currentPane.renderGFM(); }); } else { this.$toggleButton.show(); diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js index 0ca0e255595..327dbd2878c 100644 --- a/app/assets/javascripts/notes.js +++ b/app/assets/javascripts/notes.js @@ -305,7 +305,7 @@ } row = form.closest("tr"); note_html = $(note.html); - note_html.syntaxHighlight(); + note_html.renderGFM(); // is this the first note of discussion? discussionContainer = $(".notes[data-discussion-id='" + note.discussion_id + "']"); if ((note.original_discussion_id != null) && discussionContainer.length === 0) { @@ -322,7 +322,7 @@ discussionContainer.append(note_html); // Init discussion on 'Discussion' page if it is merge request page if ($('body').attr('data-page').indexOf('projects:merge_request') === 0) { - $('ul.main-notes-list').append(note.discussion_html).syntaxHighlight(); + $('ul.main-notes-list').append(note.discussion_html).renderGFM(); } } else { // append new note to all matching discussions @@ -463,7 +463,7 @@ // Convert returned HTML to a jQuery object so we can modify it further $html = $(note.html); gl.utils.localTimeAgo($('.js-timeago', $html)); - $html.syntaxHighlight(); + $html.renderGFM(); $html.find('.js-task-list-container').taskList('enable'); // Find the note's `li` element by ID and replace it with the updated HTML $note_li = $('.note-row-' + note.id); diff --git a/app/assets/javascripts/preview_markdown.js b/app/assets/javascripts/preview_markdown.js index 3723aa24942..b2574e8c0cd 100644 --- a/app/assets/javascripts/preview_markdown.js +++ b/app/assets/javascripts/preview_markdown.js @@ -27,7 +27,7 @@ return this.renderMarkdown(mdText, (function(_this) { return function(response) { preview.html(response.body); - preview.syntaxHighlight(); + preview.renderGFM(); return _this.renderReferencedUsers(response.references.users, form); }; })(this)); diff --git a/app/assets/javascripts/render_gfm.js b/app/assets/javascripts/render_gfm.js new file mode 100644 index 00000000000..bbb2f186655 --- /dev/null +++ b/app/assets/javascripts/render_gfm.js @@ -0,0 +1,16 @@ +/* eslint-disable func-names, space-before-function-paren, consistent-return, no-var, no-undef, no-else-return, prefer-arrow-callback, padded-blocks, max-len */ +// Render Gitlab flavoured Markdown +// +// Delegates to syntax highlight and render math +// +(function() { + $.fn.renderGFM = function() { + this.find('.js-syntax-highlight').syntaxHighlight(); + this.find('.js-render-math').renderMath(); + }; + + $(document).on('ready page:load', function() { + return $('body').renderGFM(); + }); + +}).call(this); diff --git a/app/assets/javascripts/render_math.js b/app/assets/javascripts/render_math.js new file mode 100644 index 00000000000..a8a56430f88 --- /dev/null +++ b/app/assets/javascripts/render_math.js @@ -0,0 +1,55 @@ +/* eslint-disable func-names, space-before-function-paren, consistent-return, no-var, no-undef, no-else-return, prefer-arrow-callback, padded-blocks, max-len */ +// Renders math using KaTeX in any element with the +// `js-render-math` class +// +// ### Example Markup +// +//
  • +// +(function() { + // Only load once + var katexLoaded = false; + + // Loop over all math elements and render math + var renderWithKaTeX = function (elements) { + elements.each(function () { + var mathNode = $(''); + var $this = $(this); + + var display = $this.attr('data-math-style') === 'display'; + try { + katex.render($this.text(), mathNode.get(0), { displayMode: display }); + mathNode.insertAfter($this); + $this.remove(); + } catch (err) { + // What can we do?? + console.log(err.message); + } + }); + }; + + $.fn.renderMath = function() { + var $this = this; + if ($this.length === 0) return; + + if (katexLoaded) renderWithKaTeX($this); + else { + // Request CSS file so it is in the cache + $.get(gon.katex_css_url, function() { + var css = $('', + { rel: 'stylesheet', + type: 'text/css', + href: gon.katex_css_url, + }); + css.appendTo('head'); + + // Load KaTeX js + $.getScript(gon.katex_js_url, function() { + katexLoaded = true; + renderWithKaTeX($this); // Run KaTeX + }); + }); + } + }; + +}).call(this); diff --git a/app/assets/javascripts/syntax_highlight.js b/app/assets/javascripts/syntax_highlight.js new file mode 100644 index 00000000000..f4e9d5af74f --- /dev/null +++ b/app/assets/javascripts/syntax_highlight.js @@ -0,0 +1,28 @@ +/* eslint-disable func-names, space-before-function-paren, consistent-return, no-var, no-undef, no-else-return, prefer-arrow-callback, padded-blocks, max-len */ +// Syntax Highlighter +// +// Applies a syntax highlighting color scheme CSS class to any element with the +// `js-syntax-highlight` class +// +// ### Example Markup +// +//
    +// +(function() { + + $.fn.syntaxHighlight = function() { + var $children; + + if ($(this).hasClass('js-syntax-highlight')) { + // Given the element itself, apply highlighting + return $(this).addClass(gon.user_color_scheme); + } else { + // Given a parent element, recurse to any of its applicable children + $children = $(this).find('.js-syntax-highlight'); + if ($children.length) { + return $children.syntaxHighlight(); + } + } + }; + +}).call(this); diff --git a/app/assets/javascripts/syntax_highlight.js.erb b/app/assets/javascripts/syntax_highlight.js.erb deleted file mode 100644 index ea79e82d887..00000000000 --- a/app/assets/javascripts/syntax_highlight.js.erb +++ /dev/null @@ -1,79 +0,0 @@ -/* eslint-disable func-names, space-before-function-paren, consistent-return, no-var, no-undef, no-else-return, prefer-arrow-callback, padded-blocks, max-len */ -// Syntax Highlighter -// -// Applies a syntax highlighting color scheme CSS class to any element with the -// `js-syntax-highlight` class -// -// ### Example Markup -// -//
    -// -(function() { - // CSS and JS for KaTeX - CSS_PATH = "<%= asset_path('katex.css') %>"; - JS_PATH = "<%= asset_path('katex.js') %>"; - - // Only load once - var katexLoaded = false; - - // Loop over all math elements and render math - var renderWithKaTeX = function (elements) { - elements.each(function () { - if (!!$(this).attr('rendered')) return; - - $(this).attr('rendered', true); - $(this).hide(); - var mathNode = $( "Test" ); - mathNode.insertAfter($(this)); - - var display = $(this).hasClass('highlight'); - katex.render($(this).text(), mathNode.get(0), { displayMode: display }) - }) - }; - var handleMath = function () { - var mathElements = $('.code.math'); - - if (mathElements.length == 0) return; - - if (katexLoaded) renderWithKaTeX(mathElements); - else { - // Request CSS file so it is in the cache - $.get(CSS_PATH, function(){ - var css = $('', - {rel:'stylesheet', - type:'text/css', - href: CSS_PATH - }); - css.appendTo('head'); - - // Load KaTeX js - $.getScript(JS_PATH, function() { - katexLoaded = true; - renderWithKaTeX(mathElements); // Run KaTeX - }) - }); - } - }; - - $.fn.syntaxHighlight = function() { - var $children; - - handleMath(); - - if ($(this).hasClass('js-syntax-highlight')) { - // Given the element itself, apply highlighting - return $(this).addClass(gon.user_color_scheme); - } else { - // Given a parent element, recurse to any of its applicable children - $children = $(this).find('.js-syntax-highlight'); - if ($children.length) { - return $children.syntaxHighlight(); - } - } - }; - - $(document).on('ready page:load', function() { - return $('.js-syntax-highlight').syntaxHighlight(); - }); - -}).call(this); -- cgit v1.2.1 From a0ba72ee28ff666e651d3a9cdef19a9d35c22616 Mon Sep 17 00:00:00 2001 From: Dimitrie Hoekstra Date: Wed, 14 Dec 2016 17:53:39 +0100 Subject: css changes @dimitrieh v1 --- app/assets/stylesheets/framework/dropdowns.scss | 2 +- app/assets/stylesheets/framework/variables.scss | 2 +- app/assets/stylesheets/pages/pipelines.scss | 27 ++++++++++++++++++++++--- 3 files changed, 26 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index d5914b900e2..21df80c01f7 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -98,7 +98,7 @@ @extend .dropdown-toggle; padding-right: 20px; position: relative; - width: 160px; + width: 163px; text-overflow: ellipsis; overflow: hidden; diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 03fbfa5f1bd..3ed19672ec1 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -578,4 +578,4 @@ Pipeline Graph */ $stage-hover-bg: #eaf3fc; $stage-hover-border: #d1e7fc; -$stage-badge-text: #d4d4d4; +$stage-badge-text: #e5e5e5; diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 26487b2acf9..ac18c39dfc4 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -460,7 +460,7 @@ border-radius: 30px; background-color: $white-light; position: relative; - padding: 8px 10px 9px; + padding: 8px 4px 9px 10px; width: 186px; margin-bottom: 10px; @@ -605,7 +605,7 @@ float: right; color: $stage-badge-text; font-weight: 100; - font-size: 13px; + font-size: 15px; margin-top: 1px; margin-right: 2px; } @@ -629,6 +629,7 @@ ul { max-height: 245px; overflow: auto; + margin: 5px 0; li { padding-top: 2px; @@ -665,6 +666,18 @@ color: $gl-text-color; } + .ci-action-icon-container { + i { + width: 25px; + height: 25px; + + &:before{ + top: 1px; + left: 1px; + } + } + } + .stage { max-width: 100px; width: 100px; @@ -681,7 +694,7 @@ // Action Icons .ci-action-icon-container .ci-action-icon-wrapper { float: right; - margin-top: -1px; + margin-top: -4px; i { color: $stage-badge-text; @@ -690,6 +703,14 @@ padding: 5px 6px; font-size: 13px; background: $white-light; + height: 30px; + width: 30px; + + &:before { + position: relative; + top: 3px; + left: 3px; + } &:hover { color: $gl-text-color; -- cgit v1.2.1 From 886a939b02c38b5caa222d47f68033fd0cbaf799 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Wed, 14 Dec 2016 16:59:36 +0000 Subject: Username exists check respects the relative root URL Closes #25548 --- app/assets/javascripts/username_validator.js.es6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/username_validator.js.es6 b/app/assets/javascripts/username_validator.js.es6 index c4dde575c6e..609dec12412 100644 --- a/app/assets/javascripts/username_validator.js.es6 +++ b/app/assets/javascripts/username_validator.js.es6 @@ -77,7 +77,7 @@ this.renderState(); return $.ajax({ type: 'GET', - url: `/users/${username}/exists`, + url: `${gon.relative_url_root}/users/${username}/exists`, dataType: 'json', success: (res) => this.setAvailabilityState(res.exists) }); -- cgit v1.2.1 From 98a12e535f612339f1af59c9d479b0cdab69df3a Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 14 Dec 2016 17:18:00 +0000 Subject: Fix extension in file --- app/views/ci/status/_graph_badge.haml | 19 ------------------- app/views/ci/status/_graph_badge.html.haml | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 19 deletions(-) delete mode 100644 app/views/ci/status/_graph_badge.haml create mode 100644 app/views/ci/status/_graph_badge.html.haml (limited to 'app') diff --git a/app/views/ci/status/_graph_badge.haml b/app/views/ci/status/_graph_badge.haml deleted file mode 100644 index 839b4334713..00000000000 --- a/app/views/ci/status/_graph_badge.haml +++ /dev/null @@ -1,19 +0,0 @@ --# Renders the graph node with both the status icon, status name and action icon - -- detailed_status = subject.detailed_status(current_user) -- details_path = detailed_status.details_path if detailed_status.has_details? -- klass = "ci-status-icon ci-status-icon-#{detailed_status}" - -- if details_path - = link_to details_path, data: { toggle: 'tooltip', title: "#{subject.name} - #{detailed_status}" } do - %span{ class: klass }= custom_icon(detailed_status.icon) - .ci-status-text= subject.name -- else - %span{ class: klass }= custom_icon(detailed_status.icon) - .ci-status-text= subject.name - -- if detailed_status.has_action? - = link_to detailed_status.action_path, method: detailed_status.action_method, - title: "#{subject.name}: #{detailed_status.action_title}", class: 'ci-action-icon-container' do - %i.ci-action-icon-wrapper - = icon(detailed_status.action_icon, class: detailed_status.action_class) diff --git a/app/views/ci/status/_graph_badge.html.haml b/app/views/ci/status/_graph_badge.html.haml new file mode 100644 index 00000000000..839b4334713 --- /dev/null +++ b/app/views/ci/status/_graph_badge.html.haml @@ -0,0 +1,19 @@ +-# Renders the graph node with both the status icon, status name and action icon + +- detailed_status = subject.detailed_status(current_user) +- details_path = detailed_status.details_path if detailed_status.has_details? +- klass = "ci-status-icon ci-status-icon-#{detailed_status}" + +- if details_path + = link_to details_path, data: { toggle: 'tooltip', title: "#{subject.name} - #{detailed_status}" } do + %span{ class: klass }= custom_icon(detailed_status.icon) + .ci-status-text= subject.name +- else + %span{ class: klass }= custom_icon(detailed_status.icon) + .ci-status-text= subject.name + +- if detailed_status.has_action? + = link_to detailed_status.action_path, method: detailed_status.action_method, + title: "#{subject.name}: #{detailed_status.action_title}", class: 'ci-action-icon-container' do + %i.ci-action-icon-wrapper + = icon(detailed_status.action_icon, class: detailed_status.action_class) -- cgit v1.2.1 From acc4b73cb5e3edfed1fa25d461d36b82fe2aacb2 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 14 Dec 2016 17:31:43 +0000 Subject: Remove duplicate color variable --- app/assets/stylesheets/framework/variables.scss | 1 - app/assets/stylesheets/pages/pipelines.scss | 11 +++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 3ed19672ec1..710b971615b 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -578,4 +578,3 @@ Pipeline Graph */ $stage-hover-bg: #eaf3fc; $stage-hover-border: #d1e7fc; -$stage-badge-text: #e5e5e5; diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index ac18c39dfc4..0124940408a 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -603,10 +603,9 @@ .dropdown-counter-badge { float: right; - color: $stage-badge-text; + color: $border-color; font-weight: 100; font-size: 15px; - margin-top: 1px; margin-right: 2px; } @@ -687,6 +686,10 @@ height: 18px; width: 18px; } + + .ci-status-text { + max-width: 95px; + } } } } @@ -697,9 +700,9 @@ margin-top: -4px; i { - color: $stage-badge-text; + color: $border-color; border-radius: 100%; - border: 1px solid $stage-badge-text; + border: 1px solid $border-color; padding: 5px 6px; font-size: 13px; background: $white-light; -- cgit v1.2.1 From aac4aa10949b89278ea40dcfb2b45ded1f24f167 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Wed, 14 Dec 2016 00:51:53 -0600 Subject: ensure classes declared outside an IIFE are properties of window --- app/assets/javascripts/boards/models/issue.js.es6 | 2 ++ app/assets/javascripts/boards/models/label.js.es6 | 2 ++ app/assets/javascripts/boards/models/list.js.es6 | 2 ++ app/assets/javascripts/boards/models/milestone.js.es6 | 2 ++ app/assets/javascripts/boards/models/user.js.es6 | 2 ++ app/assets/javascripts/boards/services/board_service.js.es6 | 4 +++- app/assets/javascripts/diff_notes/models/discussion.js.es6 | 2 ++ app/assets/javascripts/diff_notes/models/note.js.es6 | 2 ++ .../javascripts/environments/services/environments_service.js.es6 | 2 ++ .../javascripts/protected_branches/protected_branch_dropdown.js.es6 | 2 ++ 10 files changed, 21 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/boards/models/issue.js.es6 b/app/assets/javascripts/boards/models/issue.js.es6 index 21d735e8231..c1af4954af1 100644 --- a/app/assets/javascripts/boards/models/issue.js.es6 +++ b/app/assets/javascripts/boards/models/issue.js.es6 @@ -66,3 +66,5 @@ class ListIssue { return Vue.http.patch(url, data); } } + +window.ListIssue = ListIssue; diff --git a/app/assets/javascripts/boards/models/label.js.es6 b/app/assets/javascripts/boards/models/label.js.es6 index 0910fe9a854..dcb78ce86f9 100644 --- a/app/assets/javascripts/boards/models/label.js.es6 +++ b/app/assets/javascripts/boards/models/label.js.es6 @@ -9,3 +9,5 @@ class ListLabel { this.priority = (obj.priority !== null) ? obj.priority : Infinity; } } + +window.ListLabel = ListLabel; diff --git a/app/assets/javascripts/boards/models/list.js.es6 b/app/assets/javascripts/boards/models/list.js.es6 index 429bd27c3fb..967b6fbd08f 100644 --- a/app/assets/javascripts/boards/models/list.js.es6 +++ b/app/assets/javascripts/boards/models/list.js.es6 @@ -145,3 +145,5 @@ class List { }); } } + +window.List = List; diff --git a/app/assets/javascripts/boards/models/milestone.js.es6 b/app/assets/javascripts/boards/models/milestone.js.es6 index a48969e19c9..2121e512796 100644 --- a/app/assets/javascripts/boards/models/milestone.js.es6 +++ b/app/assets/javascripts/boards/models/milestone.js.es6 @@ -5,3 +5,5 @@ class ListMilestone { this.title = obj.title; } } + +window.ListMilestone = ListMilestone; diff --git a/app/assets/javascripts/boards/models/user.js.es6 b/app/assets/javascripts/boards/models/user.js.es6 index 583a973fc46..92d6b913d94 100644 --- a/app/assets/javascripts/boards/models/user.js.es6 +++ b/app/assets/javascripts/boards/models/user.js.es6 @@ -7,3 +7,5 @@ class ListUser { this.avatar = user.avatar_url; } } + +window.ListUser = ListUser; diff --git a/app/assets/javascripts/boards/services/board_service.js.es6 b/app/assets/javascripts/boards/services/board_service.js.es6 index f59a2ed7937..64532b8f75c 100644 --- a/app/assets/javascripts/boards/services/board_service.js.es6 +++ b/app/assets/javascripts/boards/services/board_service.js.es6 @@ -63,4 +63,6 @@ class BoardService { issue }); } -}; +} + +window.BoardService = BoardService; diff --git a/app/assets/javascripts/diff_notes/models/discussion.js.es6 b/app/assets/javascripts/diff_notes/models/discussion.js.es6 index badcdccc840..f4bae5e216a 100644 --- a/app/assets/javascripts/diff_notes/models/discussion.js.es6 +++ b/app/assets/javascripts/diff_notes/models/discussion.js.es6 @@ -89,3 +89,5 @@ class DiscussionModel { return false; } } + +window.DiscussionModel = DiscussionModel; diff --git a/app/assets/javascripts/diff_notes/models/note.js.es6 b/app/assets/javascripts/diff_notes/models/note.js.es6 index d0541b02632..4bbb06059a5 100644 --- a/app/assets/javascripts/diff_notes/models/note.js.es6 +++ b/app/assets/javascripts/diff_notes/models/note.js.es6 @@ -8,3 +8,5 @@ class NoteModel { this.resolved_by = resolved_by; } } + +window.NoteModel = NoteModel; diff --git a/app/assets/javascripts/environments/services/environments_service.js.es6 b/app/assets/javascripts/environments/services/environments_service.js.es6 index 15ec7b76c3d..575a45d9802 100644 --- a/app/assets/javascripts/environments/services/environments_service.js.es6 +++ b/app/assets/javascripts/environments/services/environments_service.js.es6 @@ -20,3 +20,5 @@ class EnvironmentsService { return this.environments.get(); } } + +window.EnvironmentsService = EnvironmentsService; diff --git a/app/assets/javascripts/protected_branches/protected_branch_dropdown.js.es6 b/app/assets/javascripts/protected_branches/protected_branch_dropdown.js.es6 index e3f226e9a2a..5a928631a93 100644 --- a/app/assets/javascripts/protected_branches/protected_branch_dropdown.js.es6 +++ b/app/assets/javascripts/protected_branches/protected_branch_dropdown.js.es6 @@ -75,3 +75,5 @@ class ProtectedBranchDropdown { this.$dropdownFooter.toggleClass('hidden', !branchName); } } + +window.ProtectedBranchDropdown = ProtectedBranchDropdown; -- cgit v1.2.1 From e998d6fb59e331cf000fa1c7463f79610b87be7c Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 14 Dec 2016 20:06:24 +0100 Subject: Simplify graph status badge partial and require locals --- app/views/ci/status/_graph_badge.html.haml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'app') diff --git a/app/views/ci/status/_graph_badge.html.haml b/app/views/ci/status/_graph_badge.html.haml index 839b4334713..a7e8544e7d4 100644 --- a/app/views/ci/status/_graph_badge.html.haml +++ b/app/views/ci/status/_graph_badge.html.haml @@ -1,19 +1,19 @@ -# Renders the graph node with both the status icon, status name and action icon -- detailed_status = subject.detailed_status(current_user) -- details_path = detailed_status.details_path if detailed_status.has_details? -- klass = "ci-status-icon ci-status-icon-#{detailed_status}" +- subject = local_assigns.fetch(:subject) +- status = subject.detailed_status(current_user) +- klass = "ci-status-icon ci-status-icon-#{status}" -- if details_path - = link_to details_path, data: { toggle: 'tooltip', title: "#{subject.name} - #{detailed_status}" } do - %span{ class: klass }= custom_icon(detailed_status.icon) +- if status.has_details? + = link_to status.details_path, data: { toggle: 'tooltip', title: "#{subject.name} - #{status}" } do + %span{ class: klass }= custom_icon(status.icon) .ci-status-text= subject.name - else - %span{ class: klass }= custom_icon(detailed_status.icon) + %span{ class: klass }= custom_icon(status.icon) .ci-status-text= subject.name -- if detailed_status.has_action? - = link_to detailed_status.action_path, method: detailed_status.action_method, - title: "#{subject.name}: #{detailed_status.action_title}", class: 'ci-action-icon-container' do +- if status.has_action? + = link_to status.action_path, method: status.action_method, + title: "#{subject.name}: #{status.action_title}", class: 'ci-action-icon-container' do %i.ci-action-icon-wrapper - = icon(detailed_status.action_icon, class: detailed_status.action_class) + = icon(status.action_icon, class: status.action_class) -- cgit v1.2.1 From b3bd9abceaaccafe0462220ffe4bf611c784e5c0 Mon Sep 17 00:00:00 2001 From: tauriedavis Date: Thu, 1 Dec 2016 14:45:48 -0800 Subject: 24824 Add focus state to dropdowns --- app/assets/stylesheets/framework/dropdowns.scss | 1 - 1 file changed, 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index d5914b900e2..b1422944926 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -188,7 +188,6 @@ &.is-focused { background-color: $dropdown-link-hover-bg; text-decoration: none; - outline: 0; } &.dropdown-menu-empty-link { -- cgit v1.2.1 From b7b83fe0c9368fa6f04dcb6eb8cd247978bba76b Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Thu, 8 Dec 2016 16:36:26 +0000 Subject: Introduce deployment services, starting with a KubernetesService --- app/controllers/concerns/service_params.rb | 2 +- app/models/project.rb | 9 ++ app/models/project_services/deployment_service.rb | 11 ++ app/models/project_services/kubernetes_service.rb | 118 ++++++++++++++++++++++ app/models/service.rb | 1 + 5 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 app/models/project_services/deployment_service.rb create mode 100644 app/models/project_services/kubernetes_service.rb (limited to 'app') diff --git a/app/controllers/concerns/service_params.rb b/app/controllers/concerns/service_params.rb index c33d7eecb9f..549a8526715 100644 --- a/app/controllers/concerns/service_params.rb +++ b/app/controllers/concerns/service_params.rb @@ -18,7 +18,7 @@ module ServiceParams :add_pusher, :send_from_committer_email, :disable_diffs, :external_wiki_url, :notify, :color, :server_host, :server_port, :default_irc_uri, :enable_ssl_verification, - :jira_issue_transition_id, :url, :project_key] + :jira_issue_transition_id, :url, :project_key, :ca_pem, :namespace] # Parameters to ignore if no value is specified FILTER_BLANK_PARAMS = [:password] diff --git a/app/models/project.rb b/app/models/project.rb index 77d740081c6..2c726cfc5df 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -106,6 +106,7 @@ class Project < ActiveRecord::Base has_one :bugzilla_service, dependent: :destroy has_one :gitlab_issue_tracker_service, dependent: :destroy, inverse_of: :project has_one :external_wiki_service, dependent: :destroy + has_one :kubernetes_service, dependent: :destroy, inverse_of: :project has_one :forked_project_link, dependent: :destroy, foreign_key: "forked_to_project_id" has_one :forked_from_project, through: :forked_project_link @@ -742,6 +743,14 @@ class Project < ActiveRecord::Base @ci_service ||= ci_services.reorder(nil).find_by(active: true) end + def deployment_services + services.where(category: :deployment) + end + + def deployment_service + @deployment_service ||= deployment_services.reorder(nil).find_by(active: true) + end + def jira_tracker? issues_tracker.to_param == 'jira' end diff --git a/app/models/project_services/deployment_service.rb b/app/models/project_services/deployment_service.rb new file mode 100644 index 00000000000..55e98c31251 --- /dev/null +++ b/app/models/project_services/deployment_service.rb @@ -0,0 +1,11 @@ +# Base class for deployment services +# +# These services integrate with a deployment solution like Kubernetes/OpenShift, +# Mesosphere, etc, to provide additional features to environments. +class DeploymentService < Service + default_value_for :category, 'deployment' + + def supported_events + [] + end +end diff --git a/app/models/project_services/kubernetes_service.rb b/app/models/project_services/kubernetes_service.rb new file mode 100644 index 00000000000..80ae1191108 --- /dev/null +++ b/app/models/project_services/kubernetes_service.rb @@ -0,0 +1,118 @@ +class KubernetesService < DeploymentService + # Namespace defaults to the project path, but can be overridden in case that + # is an invalid or inappropriate name + prop_accessor :namespace + + # Access to kubernetes is directly through the API + prop_accessor :api_url + + # Bearer authentication + # TODO: user/password auth, client certificates + prop_accessor :token + + # Provide a custom CA bundle for self-signed deployments + prop_accessor :ca_pem + + with_options presence: true, if: :activated? do + validates :api_url, url: true + validates :token + + validates :namespace, + format: { + with: Gitlab::Regex.kubernetes_namespace_regex, + message: Gitlab::Regex.kubernetes_namespace_regex_message, + }, + length: 1..63 + end + + def initialize_properties + if properties.nil? + self.properties = {} + self.namespace = project.path if project.present? + end + end + + def title + 'Kubernetes' + end + + def description + 'Kubernetes / Openshift integration' + end + + def help + '' + end + + def to_param + 'kubernetes' + end + + def fields + [ + { type: 'text', + name: 'namespace', + title: 'Kubernetes namespace', + placeholder: 'Kubernetes namespace', + }, + { type: 'text', + name: 'api_url', + title: 'API URL', + placeholder: 'Kubernetes API URL, like https://kube.example.com/', + }, + { type: 'text', + name: 'token', + title: 'Service token', + placeholder: 'Service token', + }, + { type: 'textarea', + name: 'ca_pem', + title: 'Custom CA bundle', + placeholder: 'Certificate Authority bundle (PEM format)', + }, + ] + end + + # Check we can connect to the Kubernetes API + def test(*args) + kubeclient = build_kubeclient + kubeclient.discover + + { success: kubeclient.discovered, result: "Checked API discovery endpoint" } + rescue => err + { success: false, result: err } + end + + private + + def build_kubeclient(api_path = '/api', api_version = 'v1') + return nil unless api_url && namespace && token + + url = URI.parse(api_url) + url.path = url.path[0..-2] if url.path[-1] == "/" + url.path += api_path + + ::Kubeclient::Client.new( + url, + api_version, + ssl_options: kubeclient_ssl_options, + auth_options: kubeclient_auth_options, + http_proxy_uri: ENV['http_proxy'] + ) + end + + def kubeclient_ssl_options + opts = { verify_ssl: OpenSSL::SSL::VERIFY_PEER } + + if ca_pem.present? + opts[:cert_store] = OpenSSL::X509::Store.new + opts[:cert_store].add_cert(OpenSSL::X509::Certificate.new(ca_pem)) + end + + opts + end + + def kubeclient_auth_options + { bearer_token: token } + end +end diff --git a/app/models/service.rb b/app/models/service.rb index 0c36acfc1b7..e49a8fa2904 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -214,6 +214,7 @@ class Service < ActiveRecord::Base hipchat irker jira + kubernetes mattermost_slash_commands pipelines_email pivotaltracker -- cgit v1.2.1 From 7760d8c06f486a64e9f97f7bc72e8d761683c289 Mon Sep 17 00:00:00 2001 From: tauriedavis Date: Wed, 14 Dec 2016 13:39:57 -0800 Subject: 25617 Fix placeholder color of todo filters --- app/views/dashboard/todos/index.html.haml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/views/dashboard/todos/index.html.haml b/app/views/dashboard/todos/index.html.haml index ea95e91eada..e13f404fee2 100644 --- a/app/views/dashboard/todos/index.html.haml +++ b/app/views/dashboard/todos/index.html.haml @@ -32,7 +32,7 @@ - if params[:project_id].present? = hidden_field_tag(:project_id, params[:project_id]) = dropdown_tag(project_dropdown_label(params[:project_id], 'Project'), options: { toggle_class: 'js-project-search js-filter-submit', title: 'Filter by project', filter: true, filterInput: 'input#project-search', dropdown_class: 'dropdown-menu-selectable dropdown-menu-project js-filter-submit', - placeholder: 'Search projects', data: { data: todo_projects_options } }) + placeholder: 'Search projects', data: { data: todo_projects_options, default_label: 'Project' } }) .filter-item.inline - if params[:author_id].present? = hidden_field_tag(:author_id, params[:author_id]) @@ -42,12 +42,12 @@ - if params[:type].present? = hidden_field_tag(:type, params[:type]) = dropdown_tag(todo_types_dropdown_label(params[:type], 'Type'), options: { toggle_class: 'js-type-search js-filter-submit', dropdown_class: 'dropdown-menu-selectable dropdown-menu-type js-filter-submit', - data: { data: todo_types_options } }) + data: { data: todo_types_options, default_label: 'Type' } }) .filter-item.inline.actions-filter - if params[:action_id].present? = hidden_field_tag(:action_id, params[:action_id]) = dropdown_tag(todo_actions_dropdown_label(params[:action_id], 'Action'), options: { toggle_class: 'js-action-search js-filter-submit', dropdown_class: 'dropdown-menu-selectable dropdown-menu-action js-filter-submit', - data: { data: todo_actions_options }}) + data: { data: todo_actions_options, default_label: 'Action' } }) .pull-right .dropdown.inline.prepend-left-10 %button.dropdown-toggle{type: 'button', 'data-toggle' => 'dropdown'} -- cgit v1.2.1 From 47646d85b10fe92d67f801325daa05a2e49a1188 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Wed, 14 Dec 2016 15:54:33 -0600 Subject: fix eslint violations in Object.assign polyfill --- app/assets/javascripts/extensions/object.js.es6 | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/extensions/object.js.es6 b/app/assets/javascripts/extensions/object.js.es6 index f8cdedd507b..70a2d765abd 100644 --- a/app/assets/javascripts/extensions/object.js.es6 +++ b/app/assets/javascripts/extensions/object.js.es6 @@ -1,20 +1,19 @@ -/* eslint-disable */ +/* eslint-disable no-restricted-syntax */ -// Taken from https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Polyfill -if (typeof Object.assign != 'function') { - Object.assign = function (target, varArgs) { // .length of function is 2 - 'use strict'; +// Adapted from https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Polyfill +if (typeof Object.assign !== 'function') { + Object.assign = function assign(target, ...args) { if (target == null) { // TypeError if undefined or null throw new TypeError('Cannot convert undefined or null to object'); } - var to = Object(target); + const to = Object(target); - for (var index = 1; index < arguments.length; index++) { - var nextSource = arguments[index]; + for (let index = 0; index < args.length; index += 1) { + const nextSource = args[index]; if (nextSource != null) { // Skip over if undefined or null - for (var nextKey in nextSource) { + for (const nextKey in nextSource) { // Avoid bugs when hasOwnProperty is shadowed if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { to[nextKey] = nextSource[nextKey]; -- cgit v1.2.1 From bdae2df31065365283720c1e29d9e5e5d495bcf3 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 14 Dec 2016 23:27:26 +0000 Subject: Fix firefox bug --- app/assets/stylesheets/pages/pipelines.scss | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 0124940408a..ee08d9d3ca0 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -463,6 +463,7 @@ padding: 8px 4px 9px 10px; width: 186px; margin-bottom: 10px; + white-space: normal; &:hover { background-color: $stage-hover-bg; @@ -586,7 +587,7 @@ border: none; padding: 0; color: $gl-text-color-light; - flex-grow: 1; + white-space: normal; &:focus { outline: none; @@ -603,6 +604,7 @@ .dropdown-counter-badge { float: right; + clear: right; color: $border-color; font-weight: 100; font-size: 15px; @@ -651,7 +653,10 @@ padding: 0; font-size: 11px; float: right; - margin-top: 5px; + clear: right; + margin-top: 3px; + display: inline-block; + position: relative; i { font-size: 11px; -- cgit v1.2.1 From 63e5e009b3fb7c85a8471d2e15951bd5d04870b5 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 14 Dec 2016 23:33:25 +0000 Subject: Changes after review --- app/assets/stylesheets/pages/pipelines.scss | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index ee08d9d3ca0..e879c2495fb 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -484,6 +484,10 @@ } } + .ci-status-icon { + position: relative; + top: 1px; + } .ci-status-icon svg { height: 20px; width: 20px; @@ -588,6 +592,7 @@ padding: 0; color: $gl-text-color-light; white-space: normal; + overflow: visible; &:focus { outline: none; -- cgit v1.2.1 From 4564492a84b91b820ef0bcc69a84563ebeed9cb2 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Thu, 15 Dec 2016 00:04:22 +0000 Subject: Fix dropdown hover --- app/assets/stylesheets/pages/pipelines.scss | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index e879c2495fb..4569b91383f 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -488,6 +488,7 @@ position: relative; top: 1px; } + .ci-status-icon svg { height: 20px; width: 20px; @@ -638,8 +639,11 @@ margin: 5px 0; li { - padding-top: 2px; margin: 0 5px; + padding-left: 0; + padding-bottom: 0; + margin-bottom: 0; + line-height: 1.2; } li:first-child { @@ -658,8 +662,7 @@ padding: 0; font-size: 11px; float: right; - clear: right; - margin-top: 3px; + margin-top: 4px; display: inline-block; position: relative; @@ -699,6 +702,9 @@ .ci-status-text { max-width: 95px; + padding-bottom: 3px; + position: relative; + top: 3px; } } } -- cgit v1.2.1 From fd3be70dcd1bd625a69701a7be17ae4e733d1512 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Tue, 6 Dec 2016 13:27:56 -0600 Subject: Shift emojis and icons styles into framework --- app/assets/stylesheets/framework.scss | 2 + app/assets/stylesheets/framework/emojis.scss | 1809 ++++++++++++++++++++++++++ app/assets/stylesheets/framework/icons.scss | 51 + app/assets/stylesheets/pages/emojis.scss | 1809 -------------------------- app/assets/stylesheets/pages/explore.scss | 8 - app/assets/stylesheets/pages/icons.scss | 51 - app/views/explore/_head.html.haml | 4 +- 7 files changed, 1864 insertions(+), 1870 deletions(-) create mode 100644 app/assets/stylesheets/framework/emojis.scss create mode 100644 app/assets/stylesheets/framework/icons.scss delete mode 100644 app/assets/stylesheets/pages/emojis.scss delete mode 100644 app/assets/stylesheets/pages/explore.scss delete mode 100644 app/assets/stylesheets/pages/icons.scss (limited to 'app') diff --git a/app/assets/stylesheets/framework.scss b/app/assets/stylesheets/framework.scss index c82a9a2b9e3..928ef408722 100644 --- a/app/assets/stylesheets/framework.scss +++ b/app/assets/stylesheets/framework.scss @@ -44,3 +44,5 @@ @import "framework/awards.scss"; @import "framework/images.scss"; @import "framework/broadcast-messages"; +@import "framework/emojis.scss"; +@import "framework/icons.scss"; diff --git a/app/assets/stylesheets/framework/emojis.scss b/app/assets/stylesheets/framework/emojis.scss new file mode 100644 index 00000000000..f17797b2381 --- /dev/null +++ b/app/assets/stylesheets/framework/emojis.scss @@ -0,0 +1,1809 @@ +.emoji-0023-20E3 { background-position: 0 0px; } +.emoji-002A-20E3 { background-position: -20px 0; } +.emoji-0030-20E3 { background-position: 0 -20px; } +.emoji-0031-20E3 { background-position: -20px -20px; } +.emoji-0032-20E3 { background-position: -40px 0; } +.emoji-0033-20E3 { background-position: -40px -20px; } +.emoji-0034-20E3 { background-position: 0 -40px; } +.emoji-0035-20E3 { background-position: -20px -40px; } +.emoji-0036-20E3 { background-position: -40px -40px; } +.emoji-0037-20E3 { background-position: -60px 0; } +.emoji-0038-20E3 { background-position: -60px -20px; } +.emoji-0039-20E3 { background-position: -60px -40px; } +.emoji-00A9 { background-position: 0 -60px; } +.emoji-00AE { background-position: -20px -60px; } +.emoji-1F004 { background-position: -40px -60px; } +.emoji-1F0CF { background-position: -60px -60px; } +.emoji-1F170 { background-position: -80px 0; } +.emoji-1F171 { background-position: -80px -20px; } +.emoji-1F17E { background-position: -80px -40px; } +.emoji-1F17F { background-position: -80px -60px; } +.emoji-1F18E { background-position: 0 -80px; } +.emoji-1F191 { background-position: -20px -80px; } +.emoji-1F192 { background-position: -40px -80px; } +.emoji-1F193 { background-position: -60px -80px; } +.emoji-1F194 { background-position: -80px -80px; } +.emoji-1F195 { background-position: -100px 0; } +.emoji-1F196 { background-position: -100px -20px; } +.emoji-1F197 { background-position: -100px -40px; } +.emoji-1F198 { background-position: -100px -60px; } +.emoji-1F199 { background-position: -100px -80px; } +.emoji-1F19A { background-position: 0 -100px; } +.emoji-1F1E6-1F1E8 { background-position: -20px -100px; } +.emoji-1F1E6-1F1E9 { background-position: -40px -100px; } +.emoji-1F1E6-1F1EA { background-position: -60px -100px; } +.emoji-1F1E6-1F1EB { background-position: -80px -100px; } +.emoji-1F1E6-1F1EC { background-position: -100px -100px; } +.emoji-1F1E6-1F1EE { background-position: -120px 0; } +.emoji-1F1E6-1F1F1 { background-position: -120px -20px; } +.emoji-1F1E6-1F1F2 { background-position: -120px -40px; } +.emoji-1F1E6-1F1F4 { background-position: -120px -60px; } +.emoji-1F1E6-1F1F6 { background-position: -120px -80px; } +.emoji-1F1E6-1F1F7 { background-position: -120px -100px; } +.emoji-1F1E6-1F1F8 { background-position: 0 -120px; } +.emoji-1F1E6-1F1F9 { background-position: -20px -120px; } +.emoji-1F1E6-1F1FA { background-position: -40px -120px; } +.emoji-1F1E6-1F1FC { background-position: -60px -120px; } +.emoji-1F1E6-1F1FD { background-position: -80px -120px; } +.emoji-1F1E6-1F1FF { background-position: -100px -120px; } +.emoji-1F1E7-1F1E6 { background-position: -120px -120px; } +.emoji-1F1E7-1F1E7 { background-position: -140px 0; } +.emoji-1F1E7-1F1E9 { background-position: -140px -20px; } +.emoji-1F1E7-1F1EA { background-position: -140px -40px; } +.emoji-1F1E7-1F1EB { background-position: -140px -60px; } +.emoji-1F1E7-1F1EC { background-position: -140px -80px; } +.emoji-1F1E7-1F1ED { background-position: -140px -100px; } +.emoji-1F1E7-1F1EE { background-position: -140px -120px; } +.emoji-1F1E7-1F1EF { background-position: 0 -140px; } +.emoji-1F1E7-1F1F1 { background-position: -20px -140px; } +.emoji-1F1E7-1F1F2 { background-position: -40px -140px; } +.emoji-1F1E7-1F1F3 { background-position: -60px -140px; } +.emoji-1F1E7-1F1F4 { background-position: -80px -140px; } +.emoji-1F1E7-1F1F6 { background-position: -100px -140px; } +.emoji-1F1E7-1F1F7 { background-position: -120px -140px; } +.emoji-1F1E7-1F1F8 { background-position: -140px -140px; } +.emoji-1F1E7-1F1F9 { background-position: -160px 0; } +.emoji-1F1E7-1F1FB { background-position: -160px -20px; } +.emoji-1F1E7-1F1FC { background-position: -160px -40px; } +.emoji-1F1E7-1F1FE { background-position: -160px -60px; } +.emoji-1F1E7-1F1FF { background-position: -160px -80px; } +.emoji-1F1E8-1F1E6 { background-position: -160px -100px; } +.emoji-1F1E8-1F1E8 { background-position: -160px -120px; } +.emoji-1F1E8-1F1E9 { background-position: -160px -140px; } +.emoji-1F1E8-1F1EB { background-position: 0 -160px; } +.emoji-1F1E8-1F1EC { background-position: -20px -160px; } +.emoji-1F1E8-1F1ED { background-position: -40px -160px; } +.emoji-1F1E8-1F1EE { background-position: -60px -160px; } +.emoji-1F1E8-1F1F0 { background-position: -80px -160px; } +.emoji-1F1E8-1F1F1 { background-position: -100px -160px; } +.emoji-1F1E8-1F1F2 { background-position: -120px -160px; } +.emoji-1F1E8-1F1F3 { background-position: -140px -160px; } +.emoji-1F1E8-1F1F4 { background-position: -160px -160px; } +.emoji-1F1E8-1F1F5 { background-position: -180px 0; } +.emoji-1F1E8-1F1F7 { background-position: -180px -20px; } +.emoji-1F1E8-1F1FA { background-position: -180px -40px; } +.emoji-1F1E8-1F1FB { background-position: -180px -60px; } +.emoji-1F1E8-1F1FC { background-position: -180px -80px; } +.emoji-1F1E8-1F1FD { background-position: -180px -100px; } +.emoji-1F1E8-1F1FE { background-position: -180px -120px; } +.emoji-1F1E8-1F1FF { background-position: -180px -140px; } +.emoji-1F1E9-1F1EA { background-position: -180px -160px; } +.emoji-1F1E9-1F1EC { background-position: 0 -180px; } +.emoji-1F1E9-1F1EF { background-position: -20px -180px; } +.emoji-1F1E9-1F1F0 { background-position: -40px -180px; } +.emoji-1F1E9-1F1F2 { background-position: -60px -180px; } +.emoji-1F1E9-1F1F4 { background-position: -80px -180px; } +.emoji-1F1E9-1F1FF { background-position: -100px -180px; } +.emoji-1F1EA-1F1E6 { background-position: -120px -180px; } +.emoji-1F1EA-1F1E8 { background-position: -140px -180px; } +.emoji-1F1EA-1F1EA { background-position: -160px -180px; } +.emoji-1F1EA-1F1EC { background-position: -180px -180px; } +.emoji-1F1EA-1F1ED { background-position: -200px 0; } +.emoji-1F1EA-1F1F7 { background-position: -200px -20px; } +.emoji-1F1EA-1F1F8 { background-position: -200px -40px; } +.emoji-1F1EA-1F1F9 { background-position: -200px -60px; } +.emoji-1F1EA-1F1FA { background-position: -200px -80px; } +.emoji-1F1EB-1F1EE { background-position: -200px -100px; } +.emoji-1F1EB-1F1EF { background-position: -200px -120px; } +.emoji-1F1EB-1F1F0 { background-position: -200px -140px; } +.emoji-1F1EB-1F1F2 { background-position: -200px -160px; } +.emoji-1F1EB-1F1F4 { background-position: -200px -180px; } +.emoji-1F1EB-1F1F7 { background-position: 0 -200px; } +.emoji-1F1EC-1F1E6 { background-position: -20px -200px; } +.emoji-1F1EC-1F1E7 { background-position: -40px -200px; } +.emoji-1F1EC-1F1E9 { background-position: -60px -200px; } +.emoji-1F1EC-1F1EA { background-position: -80px -200px; } +.emoji-1F1EC-1F1EB { background-position: -100px -200px; } +.emoji-1F1EC-1F1EC { background-position: -120px -200px; } +.emoji-1F1EC-1F1ED { background-position: -140px -200px; } +.emoji-1F1EC-1F1EE { background-position: -160px -200px; } +.emoji-1F1EC-1F1F1 { background-position: -180px -200px; } +.emoji-1F1EC-1F1F2 { background-position: -200px -200px; } +.emoji-1F1EC-1F1F3 { background-position: -220px 0; } +.emoji-1F1EC-1F1F5 { background-position: -220px -20px; } +.emoji-1F1EC-1F1F6 { background-position: -220px -40px; } +.emoji-1F1EC-1F1F7 { background-position: -220px -60px; } +.emoji-1F1EC-1F1F8 { background-position: -220px -80px; } +.emoji-1F1EC-1F1F9 { background-position: -220px -100px; } +.emoji-1F1EC-1F1FA { background-position: -220px -120px; } +.emoji-1F1EC-1F1FC { background-position: -220px -140px; } +.emoji-1F1EC-1F1FE { background-position: -220px -160px; } +.emoji-1F1ED-1F1F0 { background-position: -220px -180px; } +.emoji-1F1ED-1F1F2 { background-position: -220px -200px; } +.emoji-1F1ED-1F1F3 { background-position: 0 -220px; } +.emoji-1F1ED-1F1F7 { background-position: -20px -220px; } +.emoji-1F1ED-1F1F9 { background-position: -40px -220px; } +.emoji-1F1ED-1F1FA { background-position: -60px -220px; } +.emoji-1F1EE-1F1E8 { background-position: -80px -220px; } +.emoji-1F1EE-1F1E9 { background-position: -100px -220px; } +.emoji-1F1EE-1F1EA { background-position: -120px -220px; } +.emoji-1F1EE-1F1F1 { background-position: -140px -220px; } +.emoji-1F1EE-1F1F2 { background-position: -160px -220px; } +.emoji-1F1EE-1F1F3 { background-position: -180px -220px; } +.emoji-1F1EE-1F1F4 { background-position: -200px -220px; } +.emoji-1F1EE-1F1F6 { background-position: -220px -220px; } +.emoji-1F1EE-1F1F7 { background-position: -240px 0; } +.emoji-1F1EE-1F1F8 { background-position: -240px -20px; } +.emoji-1F1EE-1F1F9 { background-position: -240px -40px; } +.emoji-1F1EF-1F1EA { background-position: -240px -60px; } +.emoji-1F1EF-1F1F2 { background-position: -240px -80px; } +.emoji-1F1EF-1F1F4 { background-position: -240px -100px; } +.emoji-1F1EF-1F1F5 { background-position: -240px -120px; } +.emoji-1F1F0-1F1EA { background-position: -240px -140px; } +.emoji-1F1F0-1F1EC { background-position: -240px -160px; } +.emoji-1F1F0-1F1ED { background-position: -240px -180px; } +.emoji-1F1F0-1F1EE { background-position: -240px -200px; } +.emoji-1F1F0-1F1F2 { background-position: -240px -220px; } +.emoji-1F1F0-1F1F3 { background-position: 0 -240px; } +.emoji-1F1F0-1F1F5 { background-position: -20px -240px; } +.emoji-1F1F0-1F1F7 { background-position: -40px -240px; } +.emoji-1F1F0-1F1FC { background-position: -60px -240px; } +.emoji-1F1F0-1F1FE { background-position: -80px -240px; } +.emoji-1F1F0-1F1FF { background-position: -100px -240px; } +.emoji-1F1F1-1F1E6 { background-position: -120px -240px; } +.emoji-1F1F1-1F1E7 { background-position: -140px -240px; } +.emoji-1F1F1-1F1E8 { background-position: -160px -240px; } +.emoji-1F1F1-1F1EE { background-position: -180px -240px; } +.emoji-1F1F1-1F1F0 { background-position: -200px -240px; } +.emoji-1F1F1-1F1F7 { background-position: -220px -240px; } +.emoji-1F1F1-1F1F8 { background-position: -240px -240px; } +.emoji-1F1F1-1F1F9 { background-position: -260px 0; } +.emoji-1F1F1-1F1FA { background-position: -260px -20px; } +.emoji-1F1F1-1F1FB { background-position: -260px -40px; } +.emoji-1F1F1-1F1FE { background-position: -260px -60px; } +.emoji-1F1F2-1F1E6 { background-position: -260px -80px; } +.emoji-1F1F2-1F1E8 { background-position: -260px -100px; } +.emoji-1F1F2-1F1E9 { background-position: -260px -120px; } +.emoji-1F1F2-1F1EA { background-position: -260px -140px; } +.emoji-1F1F2-1F1EB { background-position: -260px -160px; } +.emoji-1F1F2-1F1EC { background-position: -260px -180px; } +.emoji-1F1F2-1F1ED { background-position: -260px -200px; } +.emoji-1F1F2-1F1F0 { background-position: -260px -220px; } +.emoji-1F1F2-1F1F1 { background-position: -260px -240px; } +.emoji-1F1F2-1F1F2 { background-position: 0 -260px; } +.emoji-1F1F2-1F1F3 { background-position: -20px -260px; } +.emoji-1F1F2-1F1F4 { background-position: -40px -260px; } +.emoji-1F1F2-1F1F5 { background-position: -60px -260px; } +.emoji-1F1F2-1F1F6 { background-position: -80px -260px; } +.emoji-1F1F2-1F1F7 { background-position: -100px -260px; } +.emoji-1F1F2-1F1F8 { background-position: -120px -260px; } +.emoji-1F1F2-1F1F9 { background-position: -140px -260px; } +.emoji-1F1F2-1F1FA { background-position: -160px -260px; } +.emoji-1F1F2-1F1FB { background-position: -180px -260px; } +.emoji-1F1F2-1F1FC { background-position: -200px -260px; } +.emoji-1F1F2-1F1FD { background-position: -220px -260px; } +.emoji-1F1F2-1F1FE { background-position: -240px -260px; } +.emoji-1F1F2-1F1FF { background-position: -260px -260px; } +.emoji-1F1F3-1F1E6 { background-position: -280px 0; } +.emoji-1F1F3-1F1E8 { background-position: -280px -20px; } +.emoji-1F1F3-1F1EA { background-position: -280px -40px; } +.emoji-1F1F3-1F1EB { background-position: -280px -60px; } +.emoji-1F1F3-1F1EC { background-position: -280px -80px; } +.emoji-1F1F3-1F1EE { background-position: -280px -100px; } +.emoji-1F1F3-1F1F1 { background-position: -280px -120px; } +.emoji-1F1F3-1F1F4 { background-position: -280px -140px; } +.emoji-1F1F3-1F1F5 { background-position: -280px -160px; } +.emoji-1F1F3-1F1F7 { background-position: -280px -180px; } +.emoji-1F1F3-1F1FA { background-position: -280px -200px; } +.emoji-1F1F3-1F1FF { background-position: -280px -220px; } +.emoji-1F1F4-1F1F2 { background-position: -280px -240px; } +.emoji-1F1F5-1F1E6 { background-position: -280px -260px; } +.emoji-1F1F5-1F1EA { background-position: 0 -280px; } +.emoji-1F1F5-1F1EB { background-position: -20px -280px; } +.emoji-1F1F5-1F1EC { background-position: -40px -280px; } +.emoji-1F1F5-1F1ED { background-position: -60px -280px; } +.emoji-1F1F5-1F1F0 { background-position: -80px -280px; } +.emoji-1F1F5-1F1F1 { background-position: -100px -280px; } +.emoji-1F1F5-1F1F2 { background-position: -120px -280px; } +.emoji-1F1F5-1F1F3 { background-position: -140px -280px; } +.emoji-1F1F5-1F1F7 { background-position: -160px -280px; } +.emoji-1F1F5-1F1F8 { background-position: -180px -280px; } +.emoji-1F1F5-1F1F9 { background-position: -200px -280px; } +.emoji-1F1F5-1F1FC { background-position: -220px -280px; } +.emoji-1F1F5-1F1FE { background-position: -240px -280px; } +.emoji-1F1F6-1F1E6 { background-position: -260px -280px; } +.emoji-1F1F7-1F1EA { background-position: -280px -280px; } +.emoji-1F1F7-1F1F4 { background-position: -300px 0; } +.emoji-1F1F7-1F1F8 { background-position: -300px -20px; } +.emoji-1F1F7-1F1FA { background-position: -300px -40px; } +.emoji-1F1F7-1F1FC { background-position: -300px -60px; } +.emoji-1F1F8-1F1E6 { background-position: -300px -80px; } +.emoji-1F1F8-1F1E7 { background-position: -300px -100px; } +.emoji-1F1F8-1F1E8 { background-position: -300px -120px; } +.emoji-1F1F8-1F1E9 { background-position: -300px -140px; } +.emoji-1F1F8-1F1EA { background-position: -300px -160px; } +.emoji-1F1F8-1F1EC { background-position: -300px -180px; } +.emoji-1F1F8-1F1ED { background-position: -300px -200px; } +.emoji-1F1F8-1F1EE { background-position: -300px -220px; } +.emoji-1F1F8-1F1EF { background-position: -300px -240px; } +.emoji-1F1F8-1F1F0 { background-position: -300px -260px; } +.emoji-1F1F8-1F1F1 { background-position: -300px -280px; } +.emoji-1F1F8-1F1F2 { background-position: 0 -300px; } +.emoji-1F1F8-1F1F3 { background-position: -20px -300px; } +.emoji-1F1F8-1F1F4 { background-position: -40px -300px; } +.emoji-1F1F8-1F1F7 { background-position: -60px -300px; } +.emoji-1F1F8-1F1F8 { background-position: -80px -300px; } +.emoji-1F1F8-1F1F9 { background-position: -100px -300px; } +.emoji-1F1F8-1F1FB { background-position: -120px -300px; } +.emoji-1F1F8-1F1FD { background-position: -140px -300px; } +.emoji-1F1F8-1F1FE { background-position: -160px -300px; } +.emoji-1F1F8-1F1FF { background-position: -180px -300px; } +.emoji-1F1F9-1F1E6 { background-position: -200px -300px; } +.emoji-1F1F9-1F1E8 { background-position: -220px -300px; } +.emoji-1F1F9-1F1E9 { background-position: -240px -300px; } +.emoji-1F1F9-1F1EB { background-position: -260px -300px; } +.emoji-1F1F9-1F1EC { background-position: -280px -300px; } +.emoji-1F1F9-1F1ED { background-position: -300px -300px; } +.emoji-1F1F9-1F1EF { background-position: -320px 0; } +.emoji-1F1F9-1F1F0 { background-position: -320px -20px; } +.emoji-1F1F9-1F1F1 { background-position: -320px -40px; } +.emoji-1F1F9-1F1F2 { background-position: -320px -60px; } +.emoji-1F1F9-1F1F3 { background-position: -320px -80px; } +.emoji-1F1F9-1F1F4 { background-position: -320px -100px; } +.emoji-1F1F9-1F1F7 { background-position: -320px -120px; } +.emoji-1F1F9-1F1F9 { background-position: -320px -140px; } +.emoji-1F1F9-1F1FB { background-position: -320px -160px; } +.emoji-1F1F9-1F1FC { background-position: -320px -180px; } +.emoji-1F1F9-1F1FF { background-position: -320px -200px; } +.emoji-1F1FA-1F1E6 { background-position: -320px -220px; } +.emoji-1F1FA-1F1EC { background-position: -320px -240px; } +.emoji-1F1FA-1F1F2 { background-position: -320px -260px; } +.emoji-1F1FA-1F1F8 { background-position: -320px -280px; } +.emoji-1F1FA-1F1FE { background-position: -320px -300px; } +.emoji-1F1FA-1F1FF { background-position: 0 -320px; } +.emoji-1F1FB-1F1E6 { background-position: -20px -320px; } +.emoji-1F1FB-1F1E8 { background-position: -40px -320px; } +.emoji-1F1FB-1F1EA { background-position: -60px -320px; } +.emoji-1F1FB-1F1EC { background-position: -80px -320px; } +.emoji-1F1FB-1F1EE { background-position: -100px -320px; } +.emoji-1F1FB-1F1F3 { background-position: -120px -320px; } +.emoji-1F1FB-1F1FA { background-position: -140px -320px; } +.emoji-1F1FC-1F1EB { background-position: -160px -320px; } +.emoji-1F1FC-1F1F8 { background-position: -180px -320px; } +.emoji-1F1FD-1F1F0 { background-position: -200px -320px; } +.emoji-1F1FE-1F1EA { background-position: -220px -320px; } +.emoji-1F1FE-1F1F9 { background-position: -240px -320px; } +.emoji-1F1FF-1F1E6 { background-position: -260px -320px; } +.emoji-1F1FF-1F1F2 { background-position: -280px -320px; } +.emoji-1F1FF-1F1FC { background-position: -300px -320px; } +.emoji-1F201 { background-position: -320px -320px; } +.emoji-1F202 { background-position: -340px 0; } +.emoji-1F21A { background-position: -340px -20px; } +.emoji-1F22F { background-position: -340px -40px; } +.emoji-1F232 { background-position: -340px -60px; } +.emoji-1F233 { background-position: -340px -80px; } +.emoji-1F234 { background-position: -340px -100px; } +.emoji-1F235 { background-position: -340px -120px; } +.emoji-1F236 { background-position: -340px -140px; } +.emoji-1F237 { background-position: -340px -160px; } +.emoji-1F238 { background-position: -340px -180px; } +.emoji-1F239 { background-position: -340px -200px; } +.emoji-1F23A { background-position: -340px -220px; } +.emoji-1F250 { background-position: -340px -240px; } +.emoji-1F251 { background-position: -340px -260px; } +.emoji-1F300 { background-position: -340px -280px; } +.emoji-1F301 { background-position: -340px -300px; } +.emoji-1F302 { background-position: -340px -320px; } +.emoji-1F303 { background-position: 0 -340px; } +.emoji-1F304 { background-position: -20px -340px; } +.emoji-1F305 { background-position: -40px -340px; } +.emoji-1F306 { background-position: -60px -340px; } +.emoji-1F307 { background-position: -80px -340px; } +.emoji-1F308 { background-position: -100px -340px; } +.emoji-1F309 { background-position: -120px -340px; } +.emoji-1F30A { background-position: -140px -340px; } +.emoji-1F30B { background-position: -160px -340px; } +.emoji-1F30C { background-position: -180px -340px; } +.emoji-1F30D { background-position: -200px -340px; } +.emoji-1F30E { background-position: -220px -340px; } +.emoji-1F30F { background-position: -240px -340px; } +.emoji-1F310 { background-position: -260px -340px; } +.emoji-1F311 { background-position: -280px -340px; } +.emoji-1F312 { background-position: -300px -340px; } +.emoji-1F313 { background-position: -320px -340px; } +.emoji-1F314 { background-position: -340px -340px; } +.emoji-1F315 { background-position: -360px 0; } +.emoji-1F316 { background-position: -360px -20px; } +.emoji-1F317 { background-position: -360px -40px; } +.emoji-1F318 { background-position: -360px -60px; } +.emoji-1F319 { background-position: -360px -80px; } +.emoji-1F31A { background-position: -360px -100px; } +.emoji-1F31B { background-position: -360px -120px; } +.emoji-1F31C { background-position: -360px -140px; } +.emoji-1F31D { background-position: -360px -160px; } +.emoji-1F31E { background-position: -360px -180px; } +.emoji-1F31F { background-position: -360px -200px; } +.emoji-1F320 { background-position: -360px -220px; } +.emoji-1F321 { background-position: -360px -240px; } +.emoji-1F324 { background-position: -360px -260px; } +.emoji-1F325 { background-position: -360px -280px; } +.emoji-1F326 { background-position: -360px -300px; } +.emoji-1F327 { background-position: -360px -320px; } +.emoji-1F328 { background-position: -360px -340px; } +.emoji-1F329 { background-position: 0 -360px; } +.emoji-1F32A { background-position: -20px -360px; } +.emoji-1F32B { background-position: -40px -360px; } +.emoji-1F32C { background-position: -60px -360px; } +.emoji-1F32D { background-position: -80px -360px; } +.emoji-1F32E { background-position: -100px -360px; } +.emoji-1F32F { background-position: -120px -360px; } +.emoji-1F330 { background-position: -140px -360px; } +.emoji-1F331 { background-position: -160px -360px; } +.emoji-1F332 { background-position: -180px -360px; } +.emoji-1F333 { background-position: -200px -360px; } +.emoji-1F334 { background-position: -220px -360px; } +.emoji-1F335 { background-position: -240px -360px; } +.emoji-1F336 { background-position: -260px -360px; } +.emoji-1F337 { background-position: -280px -360px; } +.emoji-1F338 { background-position: -300px -360px; } +.emoji-1F339 { background-position: -320px -360px; } +.emoji-1F33A { background-position: -340px -360px; } +.emoji-1F33B { background-position: -360px -360px; } +.emoji-1F33C { background-position: -380px 0; } +.emoji-1F33D { background-position: -380px -20px; } +.emoji-1F33E { background-position: -380px -40px; } +.emoji-1F33F { background-position: -380px -60px; } +.emoji-1F340 { background-position: -380px -80px; } +.emoji-1F341 { background-position: -380px -100px; } +.emoji-1F342 { background-position: -380px -120px; } +.emoji-1F343 { background-position: -380px -140px; } +.emoji-1F344 { background-position: -380px -160px; } +.emoji-1F345 { background-position: -380px -180px; } +.emoji-1F346 { background-position: -380px -200px; } +.emoji-1F347 { background-position: -380px -220px; } +.emoji-1F348 { background-position: -380px -240px; } +.emoji-1F349 { background-position: -380px -260px; } +.emoji-1F34A { background-position: -380px -280px; } +.emoji-1F34B { background-position: -380px -300px; } +.emoji-1F34C { background-position: -380px -320px; } +.emoji-1F34D { background-position: -380px -340px; } +.emoji-1F34E { background-position: -380px -360px; } +.emoji-1F34F { background-position: 0 -380px; } +.emoji-1F350 { background-position: -20px -380px; } +.emoji-1F351 { background-position: -40px -380px; } +.emoji-1F352 { background-position: -60px -380px; } +.emoji-1F353 { background-position: -80px -380px; } +.emoji-1F354 { background-position: -100px -380px; } +.emoji-1F355 { background-position: -120px -380px; } +.emoji-1F356 { background-position: -140px -380px; } +.emoji-1F357 { background-position: -160px -380px; } +.emoji-1F358 { background-position: -180px -380px; } +.emoji-1F359 { background-position: -200px -380px; } +.emoji-1F35A { background-position: -220px -380px; } +.emoji-1F35B { background-position: -240px -380px; } +.emoji-1F35C { background-position: -260px -380px; } +.emoji-1F35D { background-position: -280px -380px; } +.emoji-1F35E { background-position: -300px -380px; } +.emoji-1F35F { background-position: -320px -380px; } +.emoji-1F360 { background-position: -340px -380px; } +.emoji-1F361 { background-position: -360px -380px; } +.emoji-1F362 { background-position: -380px -380px; } +.emoji-1F363 { background-position: -400px 0; } +.emoji-1F364 { background-position: -400px -20px; } +.emoji-1F365 { background-position: -400px -40px; } +.emoji-1F366 { background-position: -400px -60px; } +.emoji-1F367 { background-position: -400px -80px; } +.emoji-1F368 { background-position: -400px -100px; } +.emoji-1F369 { background-position: -400px -120px; } +.emoji-1F36A { background-position: -400px -140px; } +.emoji-1F36B { background-position: -400px -160px; } +.emoji-1F36C { background-position: -400px -180px; } +.emoji-1F36D { background-position: -400px -200px; } +.emoji-1F36E { background-position: -400px -220px; } +.emoji-1F36F { background-position: -400px -240px; } +.emoji-1F370 { background-position: -400px -260px; } +.emoji-1F371 { background-position: -400px -280px; } +.emoji-1F372 { background-position: -400px -300px; } +.emoji-1F373 { background-position: -400px -320px; } +.emoji-1F374 { background-position: -400px -340px; } +.emoji-1F375 { background-position: -400px -360px; } +.emoji-1F376 { background-position: -400px -380px; } +.emoji-1F377 { background-position: 0 -400px; } +.emoji-1F378 { background-position: -20px -400px; } +.emoji-1F379 { background-position: -40px -400px; } +.emoji-1F37A { background-position: -60px -400px; } +.emoji-1F37B { background-position: -80px -400px; } +.emoji-1F37C { background-position: -100px -400px; } +.emoji-1F37D { background-position: -120px -400px; } +.emoji-1F37E { background-position: -140px -400px; } +.emoji-1F37F { background-position: -160px -400px; } +.emoji-1F380 { background-position: -180px -400px; } +.emoji-1F381 { background-position: -200px -400px; } +.emoji-1F382 { background-position: -220px -400px; } +.emoji-1F383 { background-position: -240px -400px; } +.emoji-1F384 { background-position: -260px -400px; } +.emoji-1F385 { background-position: -280px -400px; } +.emoji-1F385-1F3FB { background-position: -300px -400px; } +.emoji-1F385-1F3FC { background-position: -320px -400px; } +.emoji-1F385-1F3FD { background-position: -340px -400px; } +.emoji-1F385-1F3FE { background-position: -360px -400px; } +.emoji-1F385-1F3FF { background-position: -380px -400px; } +.emoji-1F386 { background-position: -400px -400px; } +.emoji-1F387 { background-position: -420px 0; } +.emoji-1F388 { background-position: -420px -20px; } +.emoji-1F389 { background-position: -420px -40px; } +.emoji-1F38A { background-position: -420px -60px; } +.emoji-1F38B { background-position: -420px -80px; } +.emoji-1F38C { background-position: -420px -100px; } +.emoji-1F38D { background-position: -420px -120px; } +.emoji-1F38E { background-position: -420px -140px; } +.emoji-1F38F { background-position: -420px -160px; } +.emoji-1F390 { background-position: -420px -180px; } +.emoji-1F391 { background-position: -420px -200px; } +.emoji-1F392 { background-position: -420px -220px; } +.emoji-1F393 { background-position: -420px -240px; } +.emoji-1F396 { background-position: -420px -260px; } +.emoji-1F397 { background-position: -420px -280px; } +.emoji-1F399 { background-position: -420px -300px; } +.emoji-1F39A { background-position: -420px -320px; } +.emoji-1F39B { background-position: -420px -340px; } +.emoji-1F39E { background-position: -420px -360px; } +.emoji-1F39F { background-position: -420px -380px; } +.emoji-1F3A0 { background-position: -420px -400px; } +.emoji-1F3A1 { background-position: 0 -420px; } +.emoji-1F3A2 { background-position: -20px -420px; } +.emoji-1F3A3 { background-position: -40px -420px; } +.emoji-1F3A4 { background-position: -60px -420px; } +.emoji-1F3A5 { background-position: -80px -420px; } +.emoji-1F3A6 { background-position: -100px -420px; } +.emoji-1F3A7 { background-position: -120px -420px; } +.emoji-1F3A8 { background-position: -140px -420px; } +.emoji-1F3A9 { background-position: -160px -420px; } +.emoji-1F3AA { background-position: -180px -420px; } +.emoji-1F3AB { background-position: -200px -420px; } +.emoji-1F3AC { background-position: -220px -420px; } +.emoji-1F3AD { background-position: -240px -420px; } +.emoji-1F3AE { background-position: -260px -420px; } +.emoji-1F3AF { background-position: -280px -420px; } +.emoji-1F3B0 { background-position: -300px -420px; } +.emoji-1F3B1 { background-position: -320px -420px; } +.emoji-1F3B2 { background-position: -340px -420px; } +.emoji-1F3B3 { background-position: -360px -420px; } +.emoji-1F3B4 { background-position: -380px -420px; } +.emoji-1F3B5 { background-position: -400px -420px; } +.emoji-1F3B6 { background-position: -420px -420px; } +.emoji-1F3B7 { background-position: -440px 0; } +.emoji-1F3B8 { background-position: -440px -20px; } +.emoji-1F3B9 { background-position: -440px -40px; } +.emoji-1F3BA { background-position: -440px -60px; } +.emoji-1F3BB { background-position: -440px -80px; } +.emoji-1F3BC { background-position: -440px -100px; } +.emoji-1F3BD { background-position: -440px -120px; } +.emoji-1F3BE { background-position: -440px -140px; } +.emoji-1F3BF { background-position: -440px -160px; } +.emoji-1F3C0 { background-position: -440px -180px; } +.emoji-1F3C1 { background-position: -440px -200px; } +.emoji-1F3C2 { background-position: -440px -220px; } +.emoji-1F3C3 { background-position: -440px -240px; } +.emoji-1F3C3-1F3FB { background-position: -440px -260px; } +.emoji-1F3C3-1F3FC { background-position: -440px -280px; } +.emoji-1F3C3-1F3FD { background-position: -440px -300px; } +.emoji-1F3C3-1F3FE { background-position: -440px -320px; } +.emoji-1F3C3-1F3FF { background-position: -440px -340px; } +.emoji-1F3C4 { background-position: -440px -360px; } +.emoji-1F3C4-1F3FB { background-position: -440px -380px; } +.emoji-1F3C4-1F3FC { background-position: -440px -400px; } +.emoji-1F3C4-1F3FD { background-position: -440px -420px; } +.emoji-1F3C4-1F3FE { background-position: 0 -440px; } +.emoji-1F3C4-1F3FF { background-position: -20px -440px; } +.emoji-1F3C5 { background-position: -40px -440px; } +.emoji-1F3C6 { background-position: -60px -440px; } +.emoji-1F3C7 { background-position: -80px -440px; } +.emoji-1F3C7-1F3FB { background-position: -100px -440px; } +.emoji-1F3C7-1F3FC { background-position: -120px -440px; } +.emoji-1F3C7-1F3FD { background-position: -140px -440px; } +.emoji-1F3C7-1F3FE { background-position: -160px -440px; } +.emoji-1F3C7-1F3FF { background-position: -180px -440px; } +.emoji-1F3C8 { background-position: -200px -440px; } +.emoji-1F3C9 { background-position: -220px -440px; } +.emoji-1F3CA { background-position: -240px -440px; } +.emoji-1F3CA-1F3FB { background-position: -260px -440px; } +.emoji-1F3CA-1F3FC { background-position: -280px -440px; } +.emoji-1F3CA-1F3FD { background-position: -300px -440px; } +.emoji-1F3CA-1F3FE { background-position: -320px -440px; } +.emoji-1F3CA-1F3FF { background-position: -340px -440px; } +.emoji-1F3CB { background-position: -360px -440px; } +.emoji-1F3CB-1F3FB { background-position: -380px -440px; } +.emoji-1F3CB-1F3FC { background-position: -400px -440px; } +.emoji-1F3CB-1F3FD { background-position: -420px -440px; } +.emoji-1F3CB-1F3FE { background-position: -440px -440px; } +.emoji-1F3CB-1F3FF { background-position: -460px 0; } +.emoji-1F3CC { background-position: -460px -20px; } +.emoji-1F3CD { background-position: -460px -40px; } +.emoji-1F3CE { background-position: -460px -60px; } +.emoji-1F3CF { background-position: -460px -80px; } +.emoji-1F3D0 { background-position: -460px -100px; } +.emoji-1F3D1 { background-position: -460px -120px; } +.emoji-1F3D2 { background-position: -460px -140px; } +.emoji-1F3D3 { background-position: -460px -160px; } +.emoji-1F3D4 { background-position: -460px -180px; } +.emoji-1F3D5 { background-position: -460px -200px; } +.emoji-1F3D6 { background-position: -460px -220px; } +.emoji-1F3D7 { background-position: -460px -240px; } +.emoji-1F3D8 { background-position: -460px -260px; } +.emoji-1F3D9 { background-position: -460px -280px; } +.emoji-1F3DA { background-position: -460px -300px; } +.emoji-1F3DB { background-position: -460px -320px; } +.emoji-1F3DC { background-position: -460px -340px; } +.emoji-1F3DD { background-position: -460px -360px; } +.emoji-1F3DE { background-position: -460px -380px; } +.emoji-1F3DF { background-position: -460px -400px; } +.emoji-1F3E0 { background-position: -460px -420px; } +.emoji-1F3E1 { background-position: -460px -440px; } +.emoji-1F3E2 { background-position: 0 -460px; } +.emoji-1F3E3 { background-position: -20px -460px; } +.emoji-1F3E4 { background-position: -40px -460px; } +.emoji-1F3E5 { background-position: -60px -460px; } +.emoji-1F3E6 { background-position: -80px -460px; } +.emoji-1F3E7 { background-position: -100px -460px; } +.emoji-1F3E8 { background-position: -120px -460px; } +.emoji-1F3E9 { background-position: -140px -460px; } +.emoji-1F3EA { background-position: -160px -460px; } +.emoji-1F3EB { background-position: -180px -460px; } +.emoji-1F3EC { background-position: -200px -460px; } +.emoji-1F3ED { background-position: -220px -460px; } +.emoji-1F3EE { background-position: -240px -460px; } +.emoji-1F3EF { background-position: -260px -460px; } +.emoji-1F3F0 { background-position: -280px -460px; } +.emoji-1F3F3 { background-position: -300px -460px; } +.emoji-1F3F4 { background-position: -320px -460px; } +.emoji-1F3F5 { background-position: -340px -460px; } +.emoji-1F3F7 { background-position: -360px -460px; } +.emoji-1F3F8 { background-position: -380px -460px; } +.emoji-1F3F9 { background-position: -400px -460px; } +.emoji-1F3FA { background-position: -420px -460px; } +.emoji-1F3FB { background-position: -440px -460px; } +.emoji-1F3FC { background-position: -460px -460px; } +.emoji-1F3FD { background-position: -480px 0; } +.emoji-1F3FE { background-position: -480px -20px; } +.emoji-1F3FF { background-position: -480px -40px; } +.emoji-1F400 { background-position: -480px -60px; } +.emoji-1F401 { background-position: -480px -80px; } +.emoji-1F402 { background-position: -480px -100px; } +.emoji-1F403 { background-position: -480px -120px; } +.emoji-1F404 { background-position: -480px -140px; } +.emoji-1F405 { background-position: -480px -160px; } +.emoji-1F406 { background-position: -480px -180px; } +.emoji-1F407 { background-position: -480px -200px; } +.emoji-1F408 { background-position: -480px -220px; } +.emoji-1F409 { background-position: -480px -240px; } +.emoji-1F40A { background-position: -480px -260px; } +.emoji-1F40B { background-position: -480px -280px; } +.emoji-1F40C { background-position: -480px -300px; } +.emoji-1F40D { background-position: -480px -320px; } +.emoji-1F40E { background-position: -480px -340px; } +.emoji-1F40F { background-position: -480px -360px; } +.emoji-1F410 { background-position: -480px -380px; } +.emoji-1F411 { background-position: -480px -400px; } +.emoji-1F412 { background-position: -480px -420px; } +.emoji-1F413 { background-position: -480px -440px; } +.emoji-1F414 { background-position: -480px -460px; } +.emoji-1F415 { background-position: 0 -480px; } +.emoji-1F416 { background-position: -20px -480px; } +.emoji-1F417 { background-position: -40px -480px; } +.emoji-1F418 { background-position: -60px -480px; } +.emoji-1F419 { background-position: -80px -480px; } +.emoji-1F41A { background-position: -100px -480px; } +.emoji-1F41B { background-position: -120px -480px; } +.emoji-1F41C { background-position: -140px -480px; } +.emoji-1F41D { background-position: -160px -480px; } +.emoji-1F41E { background-position: -180px -480px; } +.emoji-1F41F { background-position: -200px -480px; } +.emoji-1F420 { background-position: -220px -480px; } +.emoji-1F421 { background-position: -240px -480px; } +.emoji-1F422 { background-position: -260px -480px; } +.emoji-1F423 { background-position: -280px -480px; } +.emoji-1F424 { background-position: -300px -480px; } +.emoji-1F425 { background-position: -320px -480px; } +.emoji-1F426 { background-position: -340px -480px; } +.emoji-1F427 { background-position: -360px -480px; } +.emoji-1F428 { background-position: -380px -480px; } +.emoji-1F429 { background-position: -400px -480px; } +.emoji-1F42A { background-position: -420px -480px; } +.emoji-1F42B { background-position: -440px -480px; } +.emoji-1F42C { background-position: -460px -480px; } +.emoji-1F42D { background-position: -480px -480px; } +.emoji-1F42E { background-position: -500px 0; } +.emoji-1F42F { background-position: -500px -20px; } +.emoji-1F430 { background-position: -500px -40px; } +.emoji-1F431 { background-position: -500px -60px; } +.emoji-1F432 { background-position: -500px -80px; } +.emoji-1F433 { background-position: -500px -100px; } +.emoji-1F434 { background-position: -500px -120px; } +.emoji-1F435 { background-position: -500px -140px; } +.emoji-1F436 { background-position: -500px -160px; } +.emoji-1F437 { background-position: -500px -180px; } +.emoji-1F438 { background-position: -500px -200px; } +.emoji-1F439 { background-position: -500px -220px; } +.emoji-1F43A { background-position: -500px -240px; } +.emoji-1F43B { background-position: -500px -260px; } +.emoji-1F43C { background-position: -500px -280px; } +.emoji-1F43D { background-position: -500px -300px; } +.emoji-1F43E { background-position: -500px -320px; } +.emoji-1F43F { background-position: -500px -340px; } +.emoji-1F440 { background-position: -500px -360px; } +.emoji-1F441 { background-position: -500px -380px; } +.emoji-1F441-1F5E8 { background-position: -500px -400px; } +.emoji-1F442 { background-position: -500px -420px; } +.emoji-1F442-1F3FB { background-position: -500px -440px; } +.emoji-1F442-1F3FC { background-position: -500px -460px; } +.emoji-1F442-1F3FD { background-position: -500px -480px; } +.emoji-1F442-1F3FE { background-position: 0 -500px; } +.emoji-1F442-1F3FF { background-position: -20px -500px; } +.emoji-1F443 { background-position: -40px -500px; } +.emoji-1F443-1F3FB { background-position: -60px -500px; } +.emoji-1F443-1F3FC { background-position: -80px -500px; } +.emoji-1F443-1F3FD { background-position: -100px -500px; } +.emoji-1F443-1F3FE { background-position: -120px -500px; } +.emoji-1F443-1F3FF { background-position: -140px -500px; } +.emoji-1F444 { background-position: -160px -500px; } +.emoji-1F445 { background-position: -180px -500px; } +.emoji-1F446 { background-position: -200px -500px; } +.emoji-1F446-1F3FB { background-position: -220px -500px; } +.emoji-1F446-1F3FC { background-position: -240px -500px; } +.emoji-1F446-1F3FD { background-position: -260px -500px; } +.emoji-1F446-1F3FE { background-position: -280px -500px; } +.emoji-1F446-1F3FF { background-position: -300px -500px; } +.emoji-1F447 { background-position: -320px -500px; } +.emoji-1F447-1F3FB { background-position: -340px -500px; } +.emoji-1F447-1F3FC { background-position: -360px -500px; } +.emoji-1F447-1F3FD { background-position: -380px -500px; } +.emoji-1F447-1F3FE { background-position: -400px -500px; } +.emoji-1F447-1F3FF { background-position: -420px -500px; } +.emoji-1F448 { background-position: -440px -500px; } +.emoji-1F448-1F3FB { background-position: -460px -500px; } +.emoji-1F448-1F3FC { background-position: -480px -500px; } +.emoji-1F448-1F3FD { background-position: -500px -500px; } +.emoji-1F448-1F3FE { background-position: -520px 0; } +.emoji-1F448-1F3FF { background-position: -520px -20px; } +.emoji-1F449 { background-position: -520px -40px; } +.emoji-1F449-1F3FB { background-position: -520px -60px; } +.emoji-1F449-1F3FC { background-position: -520px -80px; } +.emoji-1F449-1F3FD { background-position: -520px -100px; } +.emoji-1F449-1F3FE { background-position: -520px -120px; } +.emoji-1F449-1F3FF { background-position: -520px -140px; } +.emoji-1F44A { background-position: -520px -160px; } +.emoji-1F44A-1F3FB { background-position: -520px -180px; } +.emoji-1F44A-1F3FC { background-position: -520px -200px; } +.emoji-1F44A-1F3FD { background-position: -520px -220px; } +.emoji-1F44A-1F3FE { background-position: -520px -240px; } +.emoji-1F44A-1F3FF { background-position: -520px -260px; } +.emoji-1F44B { background-position: -520px -280px; } +.emoji-1F44B-1F3FB { background-position: -520px -300px; } +.emoji-1F44B-1F3FC { background-position: -520px -320px; } +.emoji-1F44B-1F3FD { background-position: -520px -340px; } +.emoji-1F44B-1F3FE { background-position: -520px -360px; } +.emoji-1F44B-1F3FF { background-position: -520px -380px; } +.emoji-1F44C { background-position: -520px -400px; } +.emoji-1F44C-1F3FB { background-position: -520px -420px; } +.emoji-1F44C-1F3FC { background-position: -520px -440px; } +.emoji-1F44C-1F3FD { background-position: -520px -460px; } +.emoji-1F44C-1F3FE { background-position: -520px -480px; } +.emoji-1F44C-1F3FF { background-position: -520px -500px; } +.emoji-1F44D { background-position: 0 -520px; } +.emoji-1F44D-1F3FB { background-position: -20px -520px; } +.emoji-1F44D-1F3FC { background-position: -40px -520px; } +.emoji-1F44D-1F3FD { background-position: -60px -520px; } +.emoji-1F44D-1F3FE { background-position: -80px -520px; } +.emoji-1F44D-1F3FF { background-position: -100px -520px; } +.emoji-1F44E { background-position: -120px -520px; } +.emoji-1F44E-1F3FB { background-position: -140px -520px; } +.emoji-1F44E-1F3FC { background-position: -160px -520px; } +.emoji-1F44E-1F3FD { background-position: -180px -520px; } +.emoji-1F44E-1F3FE { background-position: -200px -520px; } +.emoji-1F44E-1F3FF { background-position: -220px -520px; } +.emoji-1F44F { background-position: -240px -520px; } +.emoji-1F44F-1F3FB { background-position: -260px -520px; } +.emoji-1F44F-1F3FC { background-position: -280px -520px; } +.emoji-1F44F-1F3FD { background-position: -300px -520px; } +.emoji-1F44F-1F3FE { background-position: -320px -520px; } +.emoji-1F44F-1F3FF { background-position: -340px -520px; } +.emoji-1F450 { background-position: -360px -520px; } +.emoji-1F450-1F3FB { background-position: -380px -520px; } +.emoji-1F450-1F3FC { background-position: -400px -520px; } +.emoji-1F450-1F3FD { background-position: -420px -520px; } +.emoji-1F450-1F3FE { background-position: -440px -520px; } +.emoji-1F450-1F3FF { background-position: -460px -520px; } +.emoji-1F451 { background-position: -480px -520px; } +.emoji-1F452 { background-position: -500px -520px; } +.emoji-1F453 { background-position: -520px -520px; } +.emoji-1F454 { background-position: -540px 0; } +.emoji-1F455 { background-position: -540px -20px; } +.emoji-1F456 { background-position: -540px -40px; } +.emoji-1F457 { background-position: -540px -60px; } +.emoji-1F458 { background-position: -540px -80px; } +.emoji-1F459 { background-position: -540px -100px; } +.emoji-1F45A { background-position: -540px -120px; } +.emoji-1F45B { background-position: -540px -140px; } +.emoji-1F45C { background-position: -540px -160px; } +.emoji-1F45D { background-position: -540px -180px; } +.emoji-1F45E { background-position: -540px -200px; } +.emoji-1F45F { background-position: -540px -220px; } +.emoji-1F460 { background-position: -540px -240px; } +.emoji-1F461 { background-position: -540px -260px; } +.emoji-1F462 { background-position: -540px -280px; } +.emoji-1F463 { background-position: -540px -300px; } +.emoji-1F464 { background-position: -540px -320px; } +.emoji-1F465 { background-position: -540px -340px; } +.emoji-1F466 { background-position: -540px -360px; } +.emoji-1F466-1F3FB { background-position: -540px -380px; } +.emoji-1F466-1F3FC { background-position: -540px -400px; } +.emoji-1F466-1F3FD { background-position: -540px -420px; } +.emoji-1F466-1F3FE { background-position: -540px -440px; } +.emoji-1F466-1F3FF { background-position: -540px -460px; } +.emoji-1F467 { background-position: -540px -480px; } +.emoji-1F467-1F3FB { background-position: -540px -500px; } +.emoji-1F467-1F3FC { background-position: -540px -520px; } +.emoji-1F467-1F3FD { background-position: 0 -540px; } +.emoji-1F467-1F3FE { background-position: -20px -540px; } +.emoji-1F467-1F3FF { background-position: -40px -540px; } +.emoji-1F468 { background-position: -60px -540px; } +.emoji-1F468-1F3FB { background-position: -80px -540px; } +.emoji-1F468-1F3FC { background-position: -100px -540px; } +.emoji-1F468-1F3FD { background-position: -120px -540px; } +.emoji-1F468-1F3FE { background-position: -140px -540px; } +.emoji-1F468-1F3FF { background-position: -160px -540px; } +.emoji-1F468-1F468-1F466 { background-position: -180px -540px; } +.emoji-1F468-1F468-1F466-1F466 { background-position: -200px -540px; } +.emoji-1F468-1F468-1F467 { background-position: -220px -540px; } +.emoji-1F468-1F468-1F467-1F466 { background-position: -240px -540px; } +.emoji-1F468-1F468-1F467-1F467 { background-position: -260px -540px; } +.emoji-1F468-1F469-1F466-1F466 { background-position: -280px -540px; } +.emoji-1F468-1F469-1F467 { background-position: -300px -540px; } +.emoji-1F468-1F469-1F467-1F466 { background-position: -320px -540px; } +.emoji-1F468-1F469-1F467-1F467 { background-position: -340px -540px; } +.emoji-1F468-2764-1F468 { background-position: -360px -540px; } +.emoji-1F468-2764-1F48B-1F468 { background-position: -380px -540px; } +.emoji-1F469 { background-position: -400px -540px; } +.emoji-1F469-1F3FB { background-position: -420px -540px; } +.emoji-1F469-1F3FC { background-position: -440px -540px; } +.emoji-1F469-1F3FD { background-position: -460px -540px; } +.emoji-1F469-1F3FE { background-position: -480px -540px; } +.emoji-1F469-1F3FF { background-position: -500px -540px; } +.emoji-1F469-1F469-1F466 { background-position: -520px -540px; } +.emoji-1F469-1F469-1F466-1F466 { background-position: -540px -540px; } +.emoji-1F469-1F469-1F467 { background-position: -560px 0; } +.emoji-1F469-1F469-1F467-1F466 { background-position: -560px -20px; } +.emoji-1F469-1F469-1F467-1F467 { background-position: -560px -40px; } +.emoji-1F469-2764-1F469 { background-position: -560px -60px; } +.emoji-1F469-2764-1F48B-1F469 { background-position: -560px -80px; } +.emoji-1F46A { background-position: -560px -100px; } +.emoji-1F46B { background-position: -560px -120px; } +.emoji-1F46C { background-position: -560px -140px; } +.emoji-1F46D { background-position: -560px -160px; } +.emoji-1F46E { background-position: -560px -180px; } +.emoji-1F46E-1F3FB { background-position: -560px -200px; } +.emoji-1F46E-1F3FC { background-position: -560px -220px; } +.emoji-1F46E-1F3FD { background-position: -560px -240px; } +.emoji-1F46E-1F3FE { background-position: -560px -260px; } +.emoji-1F46E-1F3FF { background-position: -560px -280px; } +.emoji-1F46F { background-position: -560px -300px; } +.emoji-1F470 { background-position: -560px -320px; } +.emoji-1F470-1F3FB { background-position: -560px -340px; } +.emoji-1F470-1F3FC { background-position: -560px -360px; } +.emoji-1F470-1F3FD { background-position: -560px -380px; } +.emoji-1F470-1F3FE { background-position: -560px -400px; } +.emoji-1F470-1F3FF { background-position: -560px -420px; } +.emoji-1F471 { background-position: -560px -440px; } +.emoji-1F471-1F3FB { background-position: -560px -460px; } +.emoji-1F471-1F3FC { background-position: -560px -480px; } +.emoji-1F471-1F3FD { background-position: -560px -500px; } +.emoji-1F471-1F3FE { background-position: -560px -520px; } +.emoji-1F471-1F3FF { background-position: -560px -540px; } +.emoji-1F472 { background-position: 0 -560px; } +.emoji-1F472-1F3FB { background-position: -20px -560px; } +.emoji-1F472-1F3FC { background-position: -40px -560px; } +.emoji-1F472-1F3FD { background-position: -60px -560px; } +.emoji-1F472-1F3FE { background-position: -80px -560px; } +.emoji-1F472-1F3FF { background-position: -100px -560px; } +.emoji-1F473 { background-position: -120px -560px; } +.emoji-1F473-1F3FB { background-position: -140px -560px; } +.emoji-1F473-1F3FC { background-position: -160px -560px; } +.emoji-1F473-1F3FD { background-position: -180px -560px; } +.emoji-1F473-1F3FE { background-position: -200px -560px; } +.emoji-1F473-1F3FF { background-position: -220px -560px; } +.emoji-1F474 { background-position: -240px -560px; } +.emoji-1F474-1F3FB { background-position: -260px -560px; } +.emoji-1F474-1F3FC { background-position: -280px -560px; } +.emoji-1F474-1F3FD { background-position: -300px -560px; } +.emoji-1F474-1F3FE { background-position: -320px -560px; } +.emoji-1F474-1F3FF { background-position: -340px -560px; } +.emoji-1F475 { background-position: -360px -560px; } +.emoji-1F475-1F3FB { background-position: -380px -560px; } +.emoji-1F475-1F3FC { background-position: -400px -560px; } +.emoji-1F475-1F3FD { background-position: -420px -560px; } +.emoji-1F475-1F3FE { background-position: -440px -560px; } +.emoji-1F475-1F3FF { background-position: -460px -560px; } +.emoji-1F476 { background-position: -480px -560px; } +.emoji-1F476-1F3FB { background-position: -500px -560px; } +.emoji-1F476-1F3FC { background-position: -520px -560px; } +.emoji-1F476-1F3FD { background-position: -540px -560px; } +.emoji-1F476-1F3FE { background-position: -560px -560px; } +.emoji-1F476-1F3FF { background-position: -580px 0; } +.emoji-1F477 { background-position: -580px -20px; } +.emoji-1F477-1F3FB { background-position: -580px -40px; } +.emoji-1F477-1F3FC { background-position: -580px -60px; } +.emoji-1F477-1F3FD { background-position: -580px -80px; } +.emoji-1F477-1F3FE { background-position: -580px -100px; } +.emoji-1F477-1F3FF { background-position: -580px -120px; } +.emoji-1F478 { background-position: -580px -140px; } +.emoji-1F478-1F3FB { background-position: -580px -160px; } +.emoji-1F478-1F3FC { background-position: -580px -180px; } +.emoji-1F478-1F3FD { background-position: -580px -200px; } +.emoji-1F478-1F3FE { background-position: -580px -220px; } +.emoji-1F478-1F3FF { background-position: -580px -240px; } +.emoji-1F479 { background-position: -580px -260px; } +.emoji-1F47A { background-position: -580px -280px; } +.emoji-1F47B { background-position: -580px -300px; } +.emoji-1F47C { background-position: -580px -320px; } +.emoji-1F47C-1F3FB { background-position: -580px -340px; } +.emoji-1F47C-1F3FC { background-position: -580px -360px; } +.emoji-1F47C-1F3FD { background-position: -580px -380px; } +.emoji-1F47C-1F3FE { background-position: -580px -400px; } +.emoji-1F47C-1F3FF { background-position: -580px -420px; } +.emoji-1F47D { background-position: -580px -440px; } +.emoji-1F47E { background-position: -580px -460px; } +.emoji-1F47F { background-position: -580px -480px; } +.emoji-1F480 { background-position: -580px -500px; } +.emoji-1F481 { background-position: -580px -520px; } +.emoji-1F481-1F3FB { background-position: -580px -540px; } +.emoji-1F481-1F3FC { background-position: -580px -560px; } +.emoji-1F481-1F3FD { background-position: 0 -580px; } +.emoji-1F481-1F3FE { background-position: -20px -580px; } +.emoji-1F481-1F3FF { background-position: -40px -580px; } +.emoji-1F482 { background-position: -60px -580px; } +.emoji-1F482-1F3FB { background-position: -80px -580px; } +.emoji-1F482-1F3FC { background-position: -100px -580px; } +.emoji-1F482-1F3FD { background-position: -120px -580px; } +.emoji-1F482-1F3FE { background-position: -140px -580px; } +.emoji-1F482-1F3FF { background-position: -160px -580px; } +.emoji-1F483 { background-position: -180px -580px; } +.emoji-1F483-1F3FB { background-position: -200px -580px; } +.emoji-1F483-1F3FC { background-position: -220px -580px; } +.emoji-1F483-1F3FD { background-position: -240px -580px; } +.emoji-1F483-1F3FE { background-position: -260px -580px; } +.emoji-1F483-1F3FF { background-position: -280px -580px; } +.emoji-1F484 { background-position: -300px -580px; } +.emoji-1F485 { background-position: -320px -580px; } +.emoji-1F485-1F3FB { background-position: -340px -580px; } +.emoji-1F485-1F3FC { background-position: -360px -580px; } +.emoji-1F485-1F3FD { background-position: -380px -580px; } +.emoji-1F485-1F3FE { background-position: -400px -580px; } +.emoji-1F485-1F3FF { background-position: -420px -580px; } +.emoji-1F486 { background-position: -440px -580px; } +.emoji-1F486-1F3FB { background-position: -460px -580px; } +.emoji-1F486-1F3FC { background-position: -480px -580px; } +.emoji-1F486-1F3FD { background-position: -500px -580px; } +.emoji-1F486-1F3FE { background-position: -520px -580px; } +.emoji-1F486-1F3FF { background-position: -540px -580px; } +.emoji-1F487 { background-position: -560px -580px; } +.emoji-1F487-1F3FB { background-position: -580px -580px; } +.emoji-1F487-1F3FC { background-position: -600px 0; } +.emoji-1F487-1F3FD { background-position: -600px -20px; } +.emoji-1F487-1F3FE { background-position: -600px -40px; } +.emoji-1F487-1F3FF { background-position: -600px -60px; } +.emoji-1F488 { background-position: -600px -80px; } +.emoji-1F489 { background-position: -600px -100px; } +.emoji-1F48A { background-position: -600px -120px; } +.emoji-1F48B { background-position: -600px -140px; } +.emoji-1F48C { background-position: -600px -160px; } +.emoji-1F48D { background-position: -600px -180px; } +.emoji-1F48E { background-position: -600px -200px; } +.emoji-1F48F { background-position: -600px -220px; } +.emoji-1F490 { background-position: -600px -240px; } +.emoji-1F491 { background-position: -600px -260px; } +.emoji-1F492 { background-position: -600px -280px; } +.emoji-1F493 { background-position: -600px -300px; } +.emoji-1F494 { background-position: -600px -320px; } +.emoji-1F495 { background-position: -600px -340px; } +.emoji-1F496 { background-position: -600px -360px; } +.emoji-1F497 { background-position: -600px -380px; } +.emoji-1F498 { background-position: -600px -400px; } +.emoji-1F499 { background-position: -600px -420px; } +.emoji-1F49A { background-position: -600px -440px; } +.emoji-1F49B { background-position: -600px -460px; } +.emoji-1F49C { background-position: -600px -480px; } +.emoji-1F49D { background-position: -600px -500px; } +.emoji-1F49E { background-position: -600px -520px; } +.emoji-1F49F { background-position: -600px -540px; } +.emoji-1F4A0 { background-position: -600px -560px; } +.emoji-1F4A1 { background-position: -600px -580px; } +.emoji-1F4A2 { background-position: 0 -600px; } +.emoji-1F4A3 { background-position: -20px -600px; } +.emoji-1F4A4 { background-position: -40px -600px; } +.emoji-1F4A5 { background-position: -60px -600px; } +.emoji-1F4A6 { background-position: -80px -600px; } +.emoji-1F4A7 { background-position: -100px -600px; } +.emoji-1F4A8 { background-position: -120px -600px; } +.emoji-1F4A9 { background-position: -140px -600px; } +.emoji-1F4AA { background-position: -160px -600px; } +.emoji-1F4AA-1F3FB { background-position: -180px -600px; } +.emoji-1F4AA-1F3FC { background-position: -200px -600px; } +.emoji-1F4AA-1F3FD { background-position: -220px -600px; } +.emoji-1F4AA-1F3FE { background-position: -240px -600px; } +.emoji-1F4AA-1F3FF { background-position: -260px -600px; } +.emoji-1F4AB { background-position: -280px -600px; } +.emoji-1F4AC { background-position: -300px -600px; } +.emoji-1F4AD { background-position: -320px -600px; } +.emoji-1F4AE { background-position: -340px -600px; } +.emoji-1F4AF { background-position: -360px -600px; } +.emoji-1F4B0 { background-position: -380px -600px; } +.emoji-1F4B1 { background-position: -400px -600px; } +.emoji-1F4B2 { background-position: -420px -600px; } +.emoji-1F4B3 { background-position: -440px -600px; } +.emoji-1F4B4 { background-position: -460px -600px; } +.emoji-1F4B5 { background-position: -480px -600px; } +.emoji-1F4B6 { background-position: -500px -600px; } +.emoji-1F4B7 { background-position: -520px -600px; } +.emoji-1F4B8 { background-position: -540px -600px; } +.emoji-1F4B9 { background-position: -560px -600px; } +.emoji-1F4BA { background-position: -580px -600px; } +.emoji-1F4BB { background-position: -600px -600px; } +.emoji-1F4BC { background-position: -620px 0; } +.emoji-1F4BD { background-position: -620px -20px; } +.emoji-1F4BE { background-position: -620px -40px; } +.emoji-1F4BF { background-position: -620px -60px; } +.emoji-1F4C0 { background-position: -620px -80px; } +.emoji-1F4C1 { background-position: -620px -100px; } +.emoji-1F4C2 { background-position: -620px -120px; } +.emoji-1F4C3 { background-position: -620px -140px; } +.emoji-1F4C4 { background-position: -620px -160px; } +.emoji-1F4C5 { background-position: -620px -180px; } +.emoji-1F4C6 { background-position: -620px -200px; } +.emoji-1F4C7 { background-position: -620px -220px; } +.emoji-1F4C8 { background-position: -620px -240px; } +.emoji-1F4C9 { background-position: -620px -260px; } +.emoji-1F4CA { background-position: -620px -280px; } +.emoji-1F4CB { background-position: -620px -300px; } +.emoji-1F4CC { background-position: -620px -320px; } +.emoji-1F4CD { background-position: -620px -340px; } +.emoji-1F4CE { background-position: -620px -360px; } +.emoji-1F4CF { background-position: -620px -380px; } +.emoji-1F4D0 { background-position: -620px -400px; } +.emoji-1F4D1 { background-position: -620px -420px; } +.emoji-1F4D2 { background-position: -620px -440px; } +.emoji-1F4D3 { background-position: -620px -460px; } +.emoji-1F4D4 { background-position: -620px -480px; } +.emoji-1F4D5 { background-position: -620px -500px; } +.emoji-1F4D6 { background-position: -620px -520px; } +.emoji-1F4D7 { background-position: -620px -540px; } +.emoji-1F4D8 { background-position: -620px -560px; } +.emoji-1F4D9 { background-position: -620px -580px; } +.emoji-1F4DA { background-position: -620px -600px; } +.emoji-1F4DB { background-position: 0 -620px; } +.emoji-1F4DC { background-position: -20px -620px; } +.emoji-1F4DD { background-position: -40px -620px; } +.emoji-1F4DE { background-position: -60px -620px; } +.emoji-1F4DF { background-position: -80px -620px; } +.emoji-1F4E0 { background-position: -100px -620px; } +.emoji-1F4E1 { background-position: -120px -620px; } +.emoji-1F4E2 { background-position: -140px -620px; } +.emoji-1F4E3 { background-position: -160px -620px; } +.emoji-1F4E4 { background-position: -180px -620px; } +.emoji-1F4E5 { background-position: -200px -620px; } +.emoji-1F4E6 { background-position: -220px -620px; } +.emoji-1F4E7 { background-position: -240px -620px; } +.emoji-1F4E8 { background-position: -260px -620px; } +.emoji-1F4E9 { background-position: -280px -620px; } +.emoji-1F4EA { background-position: -300px -620px; } +.emoji-1F4EB { background-position: -320px -620px; } +.emoji-1F4EC { background-position: -340px -620px; } +.emoji-1F4ED { background-position: -360px -620px; } +.emoji-1F4EE { background-position: -380px -620px; } +.emoji-1F4EF { background-position: -400px -620px; } +.emoji-1F4F0 { background-position: -420px -620px; } +.emoji-1F4F1 { background-position: -440px -620px; } +.emoji-1F4F2 { background-position: -460px -620px; } +.emoji-1F4F3 { background-position: -480px -620px; } +.emoji-1F4F4 { background-position: -500px -620px; } +.emoji-1F4F5 { background-position: -520px -620px; } +.emoji-1F4F6 { background-position: -540px -620px; } +.emoji-1F4F7 { background-position: -560px -620px; } +.emoji-1F4F8 { background-position: -580px -620px; } +.emoji-1F4F9 { background-position: -600px -620px; } +.emoji-1F4FA { background-position: -620px -620px; } +.emoji-1F4FB { background-position: -640px 0; } +.emoji-1F4FC { background-position: -640px -20px; } +.emoji-1F4FD { background-position: -640px -40px; } +.emoji-1F4FF { background-position: -640px -60px; } +.emoji-1F500 { background-position: -640px -80px; } +.emoji-1F501 { background-position: -640px -100px; } +.emoji-1F502 { background-position: -640px -120px; } +.emoji-1F503 { background-position: -640px -140px; } +.emoji-1F504 { background-position: -640px -160px; } +.emoji-1F505 { background-position: -640px -180px; } +.emoji-1F506 { background-position: -640px -200px; } +.emoji-1F507 { background-position: -640px -220px; } +.emoji-1F508 { background-position: -640px -240px; } +.emoji-1F509 { background-position: -640px -260px; } +.emoji-1F50A { background-position: -640px -280px; } +.emoji-1F50B { background-position: -640px -300px; } +.emoji-1F50C { background-position: -640px -320px; } +.emoji-1F50D { background-position: -640px -340px; } +.emoji-1F50E { background-position: -640px -360px; } +.emoji-1F50F { background-position: -640px -380px; } +.emoji-1F510 { background-position: -640px -400px; } +.emoji-1F511 { background-position: -640px -420px; } +.emoji-1F512 { background-position: -640px -440px; } +.emoji-1F513 { background-position: -640px -460px; } +.emoji-1F514 { background-position: -640px -480px; } +.emoji-1F515 { background-position: -640px -500px; } +.emoji-1F516 { background-position: -640px -520px; } +.emoji-1F517 { background-position: -640px -540px; } +.emoji-1F518 { background-position: -640px -560px; } +.emoji-1F519 { background-position: -640px -580px; } +.emoji-1F51A { background-position: -640px -600px; } +.emoji-1F51B { background-position: -640px -620px; } +.emoji-1F51C { background-position: 0 -640px; } +.emoji-1F51D { background-position: -20px -640px; } +.emoji-1F51E { background-position: -40px -640px; } +.emoji-1F51F { background-position: -60px -640px; } +.emoji-1F520 { background-position: -80px -640px; } +.emoji-1F521 { background-position: -100px -640px; } +.emoji-1F522 { background-position: -120px -640px; } +.emoji-1F523 { background-position: -140px -640px; } +.emoji-1F524 { background-position: -160px -640px; } +.emoji-1F525 { background-position: -180px -640px; } +.emoji-1F526 { background-position: -200px -640px; } +.emoji-1F527 { background-position: -220px -640px; } +.emoji-1F528 { background-position: -240px -640px; } +.emoji-1F529 { background-position: -260px -640px; } +.emoji-1F52A { background-position: -280px -640px; } +.emoji-1F52B { background-position: -300px -640px; } +.emoji-1F52C { background-position: -320px -640px; } +.emoji-1F52D { background-position: -340px -640px; } +.emoji-1F52E { background-position: -360px -640px; } +.emoji-1F52F { background-position: -380px -640px; } +.emoji-1F530 { background-position: -400px -640px; } +.emoji-1F531 { background-position: -420px -640px; } +.emoji-1F532 { background-position: -440px -640px; } +.emoji-1F533 { background-position: -460px -640px; } +.emoji-1F534 { background-position: -480px -640px; } +.emoji-1F535 { background-position: -500px -640px; } +.emoji-1F536 { background-position: -520px -640px; } +.emoji-1F537 { background-position: -540px -640px; } +.emoji-1F538 { background-position: -560px -640px; } +.emoji-1F539 { background-position: -580px -640px; } +.emoji-1F53A { background-position: -600px -640px; } +.emoji-1F53B { background-position: -620px -640px; } +.emoji-1F53C { background-position: -640px -640px; } +.emoji-1F53D { background-position: -660px 0; } +.emoji-1F549 { background-position: -660px -20px; } +.emoji-1F54A { background-position: -660px -40px; } +.emoji-1F54B { background-position: -660px -60px; } +.emoji-1F54C { background-position: -660px -80px; } +.emoji-1F54D { background-position: -660px -100px; } +.emoji-1F54E { background-position: -660px -120px; } +.emoji-1F550 { background-position: -660px -140px; } +.emoji-1F551 { background-position: -660px -160px; } +.emoji-1F552 { background-position: -660px -180px; } +.emoji-1F553 { background-position: -660px -200px; } +.emoji-1F554 { background-position: -660px -220px; } +.emoji-1F555 { background-position: -660px -240px; } +.emoji-1F556 { background-position: -660px -260px; } +.emoji-1F557 { background-position: -660px -280px; } +.emoji-1F558 { background-position: -660px -300px; } +.emoji-1F559 { background-position: -660px -320px; } +.emoji-1F55A { background-position: -660px -340px; } +.emoji-1F55B { background-position: -660px -360px; } +.emoji-1F55C { background-position: -660px -380px; } +.emoji-1F55D { background-position: -660px -400px; } +.emoji-1F55E { background-position: -660px -420px; } +.emoji-1F55F { background-position: -660px -440px; } +.emoji-1F560 { background-position: -660px -460px; } +.emoji-1F561 { background-position: -660px -480px; } +.emoji-1F562 { background-position: -660px -500px; } +.emoji-1F563 { background-position: -660px -520px; } +.emoji-1F564 { background-position: -660px -540px; } +.emoji-1F565 { background-position: -660px -560px; } +.emoji-1F566 { background-position: -660px -580px; } +.emoji-1F567 { background-position: -660px -600px; } +.emoji-1F56F { background-position: -660px -620px; } +.emoji-1F570 { background-position: -660px -640px; } +.emoji-1F573 { background-position: 0 -660px; } +.emoji-1F574 { background-position: -20px -660px; } +.emoji-1F575 { background-position: -40px -660px; } +.emoji-1F575-1F3FB { background-position: -60px -660px; } +.emoji-1F575-1F3FC { background-position: -80px -660px; } +.emoji-1F575-1F3FD { background-position: -100px -660px; } +.emoji-1F575-1F3FE { background-position: -120px -660px; } +.emoji-1F575-1F3FF { background-position: -140px -660px; } +.emoji-1F576 { background-position: -160px -660px; } +.emoji-1F577 { background-position: -180px -660px; } +.emoji-1F578 { background-position: -200px -660px; } +.emoji-1F579 { background-position: -220px -660px; } +.emoji-1F57A { background-position: -240px -660px; } +.emoji-1F57A-1F3FB { background-position: -260px -660px; } +.emoji-1F57A-1F3FC { background-position: -280px -660px; } +.emoji-1F57A-1F3FD { background-position: -300px -660px; } +.emoji-1F57A-1F3FE { background-position: -320px -660px; } +.emoji-1F57A-1F3FF { background-position: -340px -660px; } +.emoji-1F587 { background-position: -360px -660px; } +.emoji-1F58A { background-position: -380px -660px; } +.emoji-1F58B { background-position: -400px -660px; } +.emoji-1F58C { background-position: -420px -660px; } +.emoji-1F58D { background-position: -440px -660px; } +.emoji-1F590 { background-position: -460px -660px; } +.emoji-1F590-1F3FB { background-position: -480px -660px; } +.emoji-1F590-1F3FC { background-position: -500px -660px; } +.emoji-1F590-1F3FD { background-position: -520px -660px; } +.emoji-1F590-1F3FE { background-position: -540px -660px; } +.emoji-1F590-1F3FF { background-position: -560px -660px; } +.emoji-1F595 { background-position: -580px -660px; } +.emoji-1F595-1F3FB { background-position: -600px -660px; } +.emoji-1F595-1F3FC { background-position: -620px -660px; } +.emoji-1F595-1F3FD { background-position: -640px -660px; } +.emoji-1F595-1F3FE { background-position: -660px -660px; } +.emoji-1F595-1F3FF { background-position: -680px 0; } +.emoji-1F596 { background-position: -680px -20px; } +.emoji-1F596-1F3FB { background-position: -680px -40px; } +.emoji-1F596-1F3FC { background-position: -680px -60px; } +.emoji-1F596-1F3FD { background-position: -680px -80px; } +.emoji-1F596-1F3FE { background-position: -680px -100px; } +.emoji-1F596-1F3FF { background-position: -680px -120px; } +.emoji-1F5A4 { background-position: -680px -140px; } +.emoji-1F5A5 { background-position: -680px -160px; } +.emoji-1F5A8 { background-position: -680px -180px; } +.emoji-1F5B1 { background-position: -680px -200px; } +.emoji-1F5B2 { background-position: -680px -220px; } +.emoji-1F5BC { background-position: -680px -240px; } +.emoji-1F5C2 { background-position: -680px -260px; } +.emoji-1F5C3 { background-position: -680px -280px; } +.emoji-1F5C4 { background-position: -680px -300px; } +.emoji-1F5D1 { background-position: -680px -320px; } +.emoji-1F5D2 { background-position: -680px -340px; } +.emoji-1F5D3 { background-position: -680px -360px; } +.emoji-1F5DC { background-position: -680px -380px; } +.emoji-1F5DD { background-position: -680px -400px; } +.emoji-1F5DE { background-position: -680px -420px; } +.emoji-1F5E1 { background-position: -680px -440px; } +.emoji-1F5E3 { background-position: -680px -460px; } +.emoji-1F5EF { background-position: -680px -480px; } +.emoji-1F5F3 { background-position: -680px -500px; } +.emoji-1F5FA { background-position: -680px -520px; } +.emoji-1F5FB { background-position: -680px -540px; } +.emoji-1F5FC { background-position: -680px -560px; } +.emoji-1F5FD { background-position: -680px -580px; } +.emoji-1F5FE { background-position: -680px -600px; } +.emoji-1F5FF { background-position: -680px -620px; } +.emoji-1F600 { background-position: -680px -640px; } +.emoji-1F601 { background-position: -680px -660px; } +.emoji-1F602 { background-position: 0 -680px; } +.emoji-1F603 { background-position: -20px -680px; } +.emoji-1F604 { background-position: -40px -680px; } +.emoji-1F605 { background-position: -60px -680px; } +.emoji-1F606 { background-position: -80px -680px; } +.emoji-1F607 { background-position: -100px -680px; } +.emoji-1F608 { background-position: -120px -680px; } +.emoji-1F609 { background-position: -140px -680px; } +.emoji-1F60A { background-position: -160px -680px; } +.emoji-1F60B { background-position: -180px -680px; } +.emoji-1F60C { background-position: -200px -680px; } +.emoji-1F60D { background-position: -220px -680px; } +.emoji-1F60E { background-position: -240px -680px; } +.emoji-1F60F { background-position: -260px -680px; } +.emoji-1F610 { background-position: -280px -680px; } +.emoji-1F611 { background-position: -300px -680px; } +.emoji-1F612 { background-position: -320px -680px; } +.emoji-1F613 { background-position: -340px -680px; } +.emoji-1F614 { background-position: -360px -680px; } +.emoji-1F615 { background-position: -380px -680px; } +.emoji-1F616 { background-position: -400px -680px; } +.emoji-1F617 { background-position: -420px -680px; } +.emoji-1F618 { background-position: -440px -680px; } +.emoji-1F619 { background-position: -460px -680px; } +.emoji-1F61A { background-position: -480px -680px; } +.emoji-1F61B { background-position: -500px -680px; } +.emoji-1F61C { background-position: -520px -680px; } +.emoji-1F61D { background-position: -540px -680px; } +.emoji-1F61E { background-position: -560px -680px; } +.emoji-1F61F { background-position: -580px -680px; } +.emoji-1F620 { background-position: -600px -680px; } +.emoji-1F621 { background-position: -620px -680px; } +.emoji-1F622 { background-position: -640px -680px; } +.emoji-1F623 { background-position: -660px -680px; } +.emoji-1F624 { background-position: -680px -680px; } +.emoji-1F625 { background-position: -700px 0; } +.emoji-1F626 { background-position: -700px -20px; } +.emoji-1F627 { background-position: -700px -40px; } +.emoji-1F628 { background-position: -700px -60px; } +.emoji-1F629 { background-position: -700px -80px; } +.emoji-1F62A { background-position: -700px -100px; } +.emoji-1F62B { background-position: -700px -120px; } +.emoji-1F62C { background-position: -700px -140px; } +.emoji-1F62D { background-position: -700px -160px; } +.emoji-1F62E { background-position: -700px -180px; } +.emoji-1F62F { background-position: -700px -200px; } +.emoji-1F630 { background-position: -700px -220px; } +.emoji-1F631 { background-position: -700px -240px; } +.emoji-1F632 { background-position: -700px -260px; } +.emoji-1F633 { background-position: -700px -280px; } +.emoji-1F634 { background-position: -700px -300px; } +.emoji-1F635 { background-position: -700px -320px; } +.emoji-1F636 { background-position: -700px -340px; } +.emoji-1F637 { background-position: -700px -360px; } +.emoji-1F638 { background-position: -700px -380px; } +.emoji-1F639 { background-position: -700px -400px; } +.emoji-1F63A { background-position: -700px -420px; } +.emoji-1F63B { background-position: -700px -440px; } +.emoji-1F63C { background-position: -700px -460px; } +.emoji-1F63D { background-position: -700px -480px; } +.emoji-1F63E { background-position: -700px -500px; } +.emoji-1F63F { background-position: -700px -520px; } +.emoji-1F640 { background-position: -700px -540px; } +.emoji-1F641 { background-position: -700px -560px; } +.emoji-1F642 { background-position: -700px -580px; } +.emoji-1F643 { background-position: -700px -600px; } +.emoji-1F644 { background-position: -700px -620px; } +.emoji-1F645 { background-position: -700px -640px; } +.emoji-1F645-1F3FB { background-position: -700px -660px; } +.emoji-1F645-1F3FC { background-position: -700px -680px; } +.emoji-1F645-1F3FD { background-position: 0 -700px; } +.emoji-1F645-1F3FE { background-position: -20px -700px; } +.emoji-1F645-1F3FF { background-position: -40px -700px; } +.emoji-1F646 { background-position: -60px -700px; } +.emoji-1F646-1F3FB { background-position: -80px -700px; } +.emoji-1F646-1F3FC { background-position: -100px -700px; } +.emoji-1F646-1F3FD { background-position: -120px -700px; } +.emoji-1F646-1F3FE { background-position: -140px -700px; } +.emoji-1F646-1F3FF { background-position: -160px -700px; } +.emoji-1F647 { background-position: -180px -700px; } +.emoji-1F647-1F3FB { background-position: -200px -700px; } +.emoji-1F647-1F3FC { background-position: -220px -700px; } +.emoji-1F647-1F3FD { background-position: -240px -700px; } +.emoji-1F647-1F3FE { background-position: -260px -700px; } +.emoji-1F647-1F3FF { background-position: -280px -700px; } +.emoji-1F648 { background-position: -300px -700px; } +.emoji-1F649 { background-position: -320px -700px; } +.emoji-1F64A { background-position: -340px -700px; } +.emoji-1F64B { background-position: -360px -700px; } +.emoji-1F64B-1F3FB { background-position: -380px -700px; } +.emoji-1F64B-1F3FC { background-position: -400px -700px; } +.emoji-1F64B-1F3FD { background-position: -420px -700px; } +.emoji-1F64B-1F3FE { background-position: -440px -700px; } +.emoji-1F64B-1F3FF { background-position: -460px -700px; } +.emoji-1F64C { background-position: -480px -700px; } +.emoji-1F64C-1F3FB { background-position: -500px -700px; } +.emoji-1F64C-1F3FC { background-position: -520px -700px; } +.emoji-1F64C-1F3FD { background-position: -540px -700px; } +.emoji-1F64C-1F3FE { background-position: -560px -700px; } +.emoji-1F64C-1F3FF { background-position: -580px -700px; } +.emoji-1F64D { background-position: -600px -700px; } +.emoji-1F64D-1F3FB { background-position: -620px -700px; } +.emoji-1F64D-1F3FC { background-position: -640px -700px; } +.emoji-1F64D-1F3FD { background-position: -660px -700px; } +.emoji-1F64D-1F3FE { background-position: -680px -700px; } +.emoji-1F64D-1F3FF { background-position: -700px -700px; } +.emoji-1F64E { background-position: -720px 0; } +.emoji-1F64E-1F3FB { background-position: -720px -20px; } +.emoji-1F64E-1F3FC { background-position: -720px -40px; } +.emoji-1F64E-1F3FD { background-position: -720px -60px; } +.emoji-1F64E-1F3FE { background-position: -720px -80px; } +.emoji-1F64E-1F3FF { background-position: -720px -100px; } +.emoji-1F64F { background-position: -720px -120px; } +.emoji-1F64F-1F3FB { background-position: -720px -140px; } +.emoji-1F64F-1F3FC { background-position: -720px -160px; } +.emoji-1F64F-1F3FD { background-position: -720px -180px; } +.emoji-1F64F-1F3FE { background-position: -720px -200px; } +.emoji-1F64F-1F3FF { background-position: -720px -220px; } +.emoji-1F680 { background-position: -720px -240px; } +.emoji-1F681 { background-position: -720px -260px; } +.emoji-1F682 { background-position: -720px -280px; } +.emoji-1F683 { background-position: -720px -300px; } +.emoji-1F684 { background-position: -720px -320px; } +.emoji-1F685 { background-position: -720px -340px; } +.emoji-1F686 { background-position: -720px -360px; } +.emoji-1F687 { background-position: -720px -380px; } +.emoji-1F688 { background-position: -720px -400px; } +.emoji-1F689 { background-position: -720px -420px; } +.emoji-1F68A { background-position: -720px -440px; } +.emoji-1F68B { background-position: -720px -460px; } +.emoji-1F68C { background-position: -720px -480px; } +.emoji-1F68D { background-position: -720px -500px; } +.emoji-1F68E { background-position: -720px -520px; } +.emoji-1F68F { background-position: -720px -540px; } +.emoji-1F690 { background-position: -720px -560px; } +.emoji-1F691 { background-position: -720px -580px; } +.emoji-1F692 { background-position: -720px -600px; } +.emoji-1F693 { background-position: -720px -620px; } +.emoji-1F694 { background-position: -720px -640px; } +.emoji-1F695 { background-position: -720px -660px; } +.emoji-1F696 { background-position: -720px -680px; } +.emoji-1F697 { background-position: -720px -700px; } +.emoji-1F698 { background-position: 0 -720px; } +.emoji-1F699 { background-position: -20px -720px; } +.emoji-1F69A { background-position: -40px -720px; } +.emoji-1F69B { background-position: -60px -720px; } +.emoji-1F69C { background-position: -80px -720px; } +.emoji-1F69D { background-position: -100px -720px; } +.emoji-1F69E { background-position: -120px -720px; } +.emoji-1F69F { background-position: -140px -720px; } +.emoji-1F6A0 { background-position: -160px -720px; } +.emoji-1F6A1 { background-position: -180px -720px; } +.emoji-1F6A2 { background-position: -200px -720px; } +.emoji-1F6A3 { background-position: -220px -720px; } +.emoji-1F6A3-1F3FB { background-position: -240px -720px; } +.emoji-1F6A3-1F3FC { background-position: -260px -720px; } +.emoji-1F6A3-1F3FD { background-position: -280px -720px; } +.emoji-1F6A3-1F3FE { background-position: -300px -720px; } +.emoji-1F6A3-1F3FF { background-position: -320px -720px; } +.emoji-1F6A4 { background-position: -340px -720px; } +.emoji-1F6A5 { background-position: -360px -720px; } +.emoji-1F6A6 { background-position: -380px -720px; } +.emoji-1F6A7 { background-position: -400px -720px; } +.emoji-1F6A8 { background-position: -420px -720px; } +.emoji-1F6A9 { background-position: -440px -720px; } +.emoji-1F6AA { background-position: -460px -720px; } +.emoji-1F6AB { background-position: -480px -720px; } +.emoji-1F6AC { background-position: -500px -720px; } +.emoji-1F6AD { background-position: -520px -720px; } +.emoji-1F6AE { background-position: -540px -720px; } +.emoji-1F6AF { background-position: -560px -720px; } +.emoji-1F6B0 { background-position: -580px -720px; } +.emoji-1F6B1 { background-position: -600px -720px; } +.emoji-1F6B2 { background-position: -620px -720px; } +.emoji-1F6B3 { background-position: -640px -720px; } +.emoji-1F6B4 { background-position: -660px -720px; } +.emoji-1F6B4-1F3FB { background-position: -680px -720px; } +.emoji-1F6B4-1F3FC { background-position: -700px -720px; } +.emoji-1F6B4-1F3FD { background-position: -720px -720px; } +.emoji-1F6B4-1F3FE { background-position: -740px 0; } +.emoji-1F6B4-1F3FF { background-position: -740px -20px; } +.emoji-1F6B5 { background-position: -740px -40px; } +.emoji-1F6B5-1F3FB { background-position: -740px -60px; } +.emoji-1F6B5-1F3FC { background-position: -740px -80px; } +.emoji-1F6B5-1F3FD { background-position: -740px -100px; } +.emoji-1F6B5-1F3FE { background-position: -740px -120px; } +.emoji-1F6B5-1F3FF { background-position: -740px -140px; } +.emoji-1F6B6 { background-position: -740px -160px; } +.emoji-1F6B6-1F3FB { background-position: -740px -180px; } +.emoji-1F6B6-1F3FC { background-position: -740px -200px; } +.emoji-1F6B6-1F3FD { background-position: -740px -220px; } +.emoji-1F6B6-1F3FE { background-position: -740px -240px; } +.emoji-1F6B6-1F3FF { background-position: -740px -260px; } +.emoji-1F6B7 { background-position: -740px -280px; } +.emoji-1F6B8 { background-position: -740px -300px; } +.emoji-1F6B9 { background-position: -740px -320px; } +.emoji-1F6BA { background-position: -740px -340px; } +.emoji-1F6BB { background-position: -740px -360px; } +.emoji-1F6BC { background-position: -740px -380px; } +.emoji-1F6BD { background-position: -740px -400px; } +.emoji-1F6BE { background-position: -740px -420px; } +.emoji-1F6BF { background-position: -740px -440px; } +.emoji-1F6C0 { background-position: -740px -460px; } +.emoji-1F6C0-1F3FB { background-position: -740px -480px; } +.emoji-1F6C0-1F3FC { background-position: -740px -500px; } +.emoji-1F6C0-1F3FD { background-position: -740px -520px; } +.emoji-1F6C0-1F3FE { background-position: -740px -540px; } +.emoji-1F6C0-1F3FF { background-position: -740px -560px; } +.emoji-1F6C1 { background-position: -740px -580px; } +.emoji-1F6C2 { background-position: -740px -600px; } +.emoji-1F6C3 { background-position: -740px -620px; } +.emoji-1F6C4 { background-position: -740px -640px; } +.emoji-1F6C5 { background-position: -740px -660px; } +.emoji-1F6CB { background-position: -740px -680px; } +.emoji-1F6CC { background-position: -740px -700px; } +.emoji-1F6CD { background-position: -740px -720px; } +.emoji-1F6CE { background-position: 0 -740px; } +.emoji-1F6CF { background-position: -20px -740px; } +.emoji-1F6D0 { background-position: -40px -740px; } +.emoji-1F6D1 { background-position: -60px -740px; } +.emoji-1F6D2 { background-position: -80px -740px; } +.emoji-1F6E0 { background-position: -100px -740px; } +.emoji-1F6E1 { background-position: -120px -740px; } +.emoji-1F6E2 { background-position: -140px -740px; } +.emoji-1F6E3 { background-position: -160px -740px; } +.emoji-1F6E4 { background-position: -180px -740px; } +.emoji-1F6E5 { background-position: -200px -740px; } +.emoji-1F6E9 { background-position: -220px -740px; } +.emoji-1F6EB { background-position: -240px -740px; } +.emoji-1F6EC { background-position: -260px -740px; } +.emoji-1F6F0 { background-position: -280px -740px; } +.emoji-1F6F3 { background-position: -300px -740px; } +.emoji-1F6F4 { background-position: -320px -740px; } +.emoji-1F6F5 { background-position: -340px -740px; } +.emoji-1F6F6 { background-position: -360px -740px; } +.emoji-1F910 { background-position: -380px -740px; } +.emoji-1F911 { background-position: -400px -740px; } +.emoji-1F912 { background-position: -420px -740px; } +.emoji-1F913 { background-position: -440px -740px; } +.emoji-1F914 { background-position: -460px -740px; } +.emoji-1F915 { background-position: -480px -740px; } +.emoji-1F916 { background-position: -500px -740px; } +.emoji-1F917 { background-position: -520px -740px; } +.emoji-1F918 { background-position: -540px -740px; } +.emoji-1F918-1F3FB { background-position: -560px -740px; } +.emoji-1F918-1F3FC { background-position: -580px -740px; } +.emoji-1F918-1F3FD { background-position: -600px -740px; } +.emoji-1F918-1F3FE { background-position: -620px -740px; } +.emoji-1F918-1F3FF { background-position: -640px -740px; } +.emoji-1F919 { background-position: -660px -740px; } +.emoji-1F919-1F3FB { background-position: -680px -740px; } +.emoji-1F919-1F3FC { background-position: -700px -740px; } +.emoji-1F919-1F3FD { background-position: -720px -740px; } +.emoji-1F919-1F3FE { background-position: -740px -740px; } +.emoji-1F919-1F3FF { background-position: -760px 0; } +.emoji-1F91A { background-position: -760px -20px; } +.emoji-1F91A-1F3FB { background-position: -760px -40px; } +.emoji-1F91A-1F3FC { background-position: -760px -60px; } +.emoji-1F91A-1F3FD { background-position: -760px -80px; } +.emoji-1F91A-1F3FE { background-position: -760px -100px; } +.emoji-1F91A-1F3FF { background-position: -760px -120px; } +.emoji-1F91B { background-position: -760px -140px; } +.emoji-1F91B-1F3FB { background-position: -760px -160px; } +.emoji-1F91B-1F3FC { background-position: -760px -180px; } +.emoji-1F91B-1F3FD { background-position: -760px -200px; } +.emoji-1F91B-1F3FE { background-position: -760px -220px; } +.emoji-1F91B-1F3FF { background-position: -760px -240px; } +.emoji-1F91C { background-position: -760px -260px; } +.emoji-1F91C-1F3FB { background-position: -760px -280px; } +.emoji-1F91C-1F3FC { background-position: -760px -300px; } +.emoji-1F91C-1F3FD { background-position: -760px -320px; } +.emoji-1F91C-1F3FE { background-position: -760px -340px; } +.emoji-1F91C-1F3FF { background-position: -760px -360px; } +.emoji-1F91D { background-position: -760px -380px; } +.emoji-1F91D-1F3FB { background-position: -760px -400px; } +.emoji-1F91D-1F3FC { background-position: -760px -420px; } +.emoji-1F91D-1F3FD { background-position: -760px -440px; } +.emoji-1F91D-1F3FE { background-position: -760px -460px; } +.emoji-1F91D-1F3FF { background-position: -760px -480px; } +.emoji-1F91E { background-position: -760px -500px; } +.emoji-1F91E-1F3FB { background-position: -760px -520px; } +.emoji-1F91E-1F3FC { background-position: -760px -540px; } +.emoji-1F91E-1F3FD { background-position: -760px -560px; } +.emoji-1F91E-1F3FE { background-position: -760px -580px; } +.emoji-1F91E-1F3FF { background-position: -760px -600px; } +.emoji-1F920 { background-position: -760px -620px; } +.emoji-1F921 { background-position: -760px -640px; } +.emoji-1F922 { background-position: -760px -660px; } +.emoji-1F923 { background-position: -760px -680px; } +.emoji-1F924 { background-position: -760px -700px; } +.emoji-1F925 { background-position: -760px -720px; } +.emoji-1F926 { background-position: -760px -740px; } +.emoji-1F926-1F3FB { background-position: 0 -760px; } +.emoji-1F926-1F3FC { background-position: -20px -760px; } +.emoji-1F926-1F3FD { background-position: -40px -760px; } +.emoji-1F926-1F3FE { background-position: -60px -760px; } +.emoji-1F926-1F3FF { background-position: -80px -760px; } +.emoji-1F927 { background-position: -100px -760px; } +.emoji-1F930 { background-position: -120px -760px; } +.emoji-1F930-1F3FB { background-position: -140px -760px; } +.emoji-1F930-1F3FC { background-position: -160px -760px; } +.emoji-1F930-1F3FD { background-position: -180px -760px; } +.emoji-1F930-1F3FE { background-position: -200px -760px; } +.emoji-1F930-1F3FF { background-position: -220px -760px; } +.emoji-1F933 { background-position: -240px -760px; } +.emoji-1F933-1F3FB { background-position: -260px -760px; } +.emoji-1F933-1F3FC { background-position: -280px -760px; } +.emoji-1F933-1F3FD { background-position: -300px -760px; } +.emoji-1F933-1F3FE { background-position: -320px -760px; } +.emoji-1F933-1F3FF { background-position: -340px -760px; } +.emoji-1F934 { background-position: -360px -760px; } +.emoji-1F934-1F3FB { background-position: -380px -760px; } +.emoji-1F934-1F3FC { background-position: -400px -760px; } +.emoji-1F934-1F3FD { background-position: -420px -760px; } +.emoji-1F934-1F3FE { background-position: -440px -760px; } +.emoji-1F934-1F3FF { background-position: -460px -760px; } +.emoji-1F935 { background-position: -480px -760px; } +.emoji-1F935-1F3FB { background-position: -500px -760px; } +.emoji-1F935-1F3FC { background-position: -520px -760px; } +.emoji-1F935-1F3FD { background-position: -540px -760px; } +.emoji-1F935-1F3FE { background-position: -560px -760px; } +.emoji-1F935-1F3FF { background-position: -580px -760px; } +.emoji-1F936 { background-position: -600px -760px; } +.emoji-1F936-1F3FB { background-position: -620px -760px; } +.emoji-1F936-1F3FC { background-position: -640px -760px; } +.emoji-1F936-1F3FD { background-position: -660px -760px; } +.emoji-1F936-1F3FE { background-position: -680px -760px; } +.emoji-1F936-1F3FF { background-position: -700px -760px; } +.emoji-1F937 { background-position: -720px -760px; } +.emoji-1F937-1F3FB { background-position: -740px -760px; } +.emoji-1F937-1F3FC { background-position: -760px -760px; } +.emoji-1F937-1F3FD { background-position: -780px 0; } +.emoji-1F937-1F3FE { background-position: -780px -20px; } +.emoji-1F937-1F3FF { background-position: -780px -40px; } +.emoji-1F938 { background-position: -780px -60px; } +.emoji-1F938-1F3FB { background-position: -780px -80px; } +.emoji-1F938-1F3FC { background-position: -780px -100px; } +.emoji-1F938-1F3FD { background-position: -780px -120px; } +.emoji-1F938-1F3FE { background-position: -780px -140px; } +.emoji-1F938-1F3FF { background-position: -780px -160px; } +.emoji-1F939 { background-position: -780px -180px; } +.emoji-1F939-1F3FB { background-position: -780px -200px; } +.emoji-1F939-1F3FC { background-position: -780px -220px; } +.emoji-1F939-1F3FD { background-position: -780px -240px; } +.emoji-1F939-1F3FE { background-position: -780px -260px; } +.emoji-1F939-1F3FF { background-position: -780px -280px; } +.emoji-1F93A { background-position: -780px -300px; } +.emoji-1F93C { background-position: -780px -320px; } +.emoji-1F93C-1F3FB { background-position: -780px -340px; } +.emoji-1F93C-1F3FC { background-position: -780px -360px; } +.emoji-1F93C-1F3FD { background-position: -780px -380px; } +.emoji-1F93C-1F3FE { background-position: -780px -400px; } +.emoji-1F93C-1F3FF { background-position: -780px -420px; } +.emoji-1F93D { background-position: -780px -440px; } +.emoji-1F93D-1F3FB { background-position: -780px -460px; } +.emoji-1F93D-1F3FC { background-position: -780px -480px; } +.emoji-1F93D-1F3FD { background-position: -780px -500px; } +.emoji-1F93D-1F3FE { background-position: -780px -520px; } +.emoji-1F93D-1F3FF { background-position: -780px -540px; } +.emoji-1F93E { background-position: -780px -560px; } +.emoji-1F93E-1F3FB { background-position: -780px -580px; } +.emoji-1F93E-1F3FC { background-position: -780px -600px; } +.emoji-1F93E-1F3FD { background-position: -780px -620px; } +.emoji-1F93E-1F3FE { background-position: -780px -640px; } +.emoji-1F93E-1F3FF { background-position: -780px -660px; } +.emoji-1F940 { background-position: -780px -680px; } +.emoji-1F941 { background-position: -780px -700px; } +.emoji-1F942 { background-position: -780px -720px; } +.emoji-1F943 { background-position: -780px -740px; } +.emoji-1F944 { background-position: -780px -760px; } +.emoji-1F945 { background-position: 0 -780px; } +.emoji-1F947 { background-position: -20px -780px; } +.emoji-1F948 { background-position: -40px -780px; } +.emoji-1F949 { background-position: -60px -780px; } +.emoji-1F94A { background-position: -80px -780px; } +.emoji-1F94B { background-position: -100px -780px; } +.emoji-1F950 { background-position: -120px -780px; } +.emoji-1F951 { background-position: -140px -780px; } +.emoji-1F952 { background-position: -160px -780px; } +.emoji-1F953 { background-position: -180px -780px; } +.emoji-1F954 { background-position: -200px -780px; } +.emoji-1F955 { background-position: -220px -780px; } +.emoji-1F956 { background-position: -240px -780px; } +.emoji-1F957 { background-position: -260px -780px; } +.emoji-1F958 { background-position: -280px -780px; } +.emoji-1F959 { background-position: -300px -780px; } +.emoji-1F95A { background-position: -320px -780px; } +.emoji-1F95B { background-position: -340px -780px; } +.emoji-1F95C { background-position: -360px -780px; } +.emoji-1F95D { background-position: -380px -780px; } +.emoji-1F95E { background-position: -400px -780px; } +.emoji-1F980 { background-position: -420px -780px; } +.emoji-1F981 { background-position: -440px -780px; } +.emoji-1F982 { background-position: -460px -780px; } +.emoji-1F983 { background-position: -480px -780px; } +.emoji-1F984 { background-position: -500px -780px; } +.emoji-1F985 { background-position: -520px -780px; } +.emoji-1F986 { background-position: -540px -780px; } +.emoji-1F987 { background-position: -560px -780px; } +.emoji-1F988 { background-position: -580px -780px; } +.emoji-1F989 { background-position: -600px -780px; } +.emoji-1F98A { background-position: -620px -780px; } +.emoji-1F98B { background-position: -640px -780px; } +.emoji-1F98C { background-position: -660px -780px; } +.emoji-1F98D { background-position: -680px -780px; } +.emoji-1F98E { background-position: -700px -780px; } +.emoji-1F98F { background-position: -720px -780px; } +.emoji-1F990 { background-position: -740px -780px; } +.emoji-1F991 { background-position: -760px -780px; } +.emoji-1F9C0 { background-position: -780px -780px; } +.emoji-203C { background-position: -800px 0; } +.emoji-2049 { background-position: -800px -20px; } +.emoji-2122 { background-position: -800px -40px; } +.emoji-2139 { background-position: -800px -60px; } +.emoji-2194 { background-position: -800px -80px; } +.emoji-2195 { background-position: -800px -100px; } +.emoji-2196 { background-position: -800px -120px; } +.emoji-2197 { background-position: -800px -140px; } +.emoji-2198 { background-position: -800px -160px; } +.emoji-2199 { background-position: -800px -180px; } +.emoji-21A9 { background-position: -800px -200px; } +.emoji-21AA { background-position: -800px -220px; } +.emoji-231A { background-position: -800px -240px; } +.emoji-231B { background-position: -800px -260px; } +.emoji-2328 { background-position: -800px -280px; } +.emoji-23CF { background-position: -800px -300px; } +.emoji-23E9 { background-position: -800px -320px; } +.emoji-23EA { background-position: -800px -340px; } +.emoji-23EB { background-position: -800px -360px; } +.emoji-23EC { background-position: -800px -380px; } +.emoji-23ED { background-position: -800px -400px; } +.emoji-23EE { background-position: -800px -420px; } +.emoji-23EF { background-position: -800px -440px; } +.emoji-23F0 { background-position: -800px -460px; } +.emoji-23F1 { background-position: -800px -480px; } +.emoji-23F2 { background-position: -800px -500px; } +.emoji-23F3 { background-position: -800px -520px; } +.emoji-23F8 { background-position: -800px -540px; } +.emoji-23F9 { background-position: -800px -560px; } +.emoji-23FA { background-position: -800px -580px; } +.emoji-24C2 { background-position: -800px -600px; } +.emoji-25AA { background-position: -800px -620px; } +.emoji-25AB { background-position: -800px -640px; } +.emoji-25B6 { background-position: -800px -660px; } +.emoji-25C0 { background-position: -800px -680px; } +.emoji-25FB { background-position: -800px -700px; } +.emoji-25FC { background-position: -800px -720px; } +.emoji-25FD { background-position: -800px -740px; } +.emoji-25FE { background-position: -800px -760px; } +.emoji-2600 { background-position: -800px -780px; } +.emoji-2601 { background-position: 0 -800px; } +.emoji-2602 { background-position: -20px -800px; } +.emoji-2603 { background-position: -40px -800px; } +.emoji-2604 { background-position: -60px -800px; } +.emoji-260E { background-position: -80px -800px; } +.emoji-2611 { background-position: -100px -800px; } +.emoji-2614 { background-position: -120px -800px; } +.emoji-2615 { background-position: -140px -800px; } +.emoji-2618 { background-position: -160px -800px; } +.emoji-261D { background-position: -180px -800px; } +.emoji-261D-1F3FB { background-position: -200px -800px; } +.emoji-261D-1F3FC { background-position: -220px -800px; } +.emoji-261D-1F3FD { background-position: -240px -800px; } +.emoji-261D-1F3FE { background-position: -260px -800px; } +.emoji-261D-1F3FF { background-position: -280px -800px; } +.emoji-2620 { background-position: -300px -800px; } +.emoji-2622 { background-position: -320px -800px; } +.emoji-2623 { background-position: -340px -800px; } +.emoji-2626 { background-position: -360px -800px; } +.emoji-262A { background-position: -380px -800px; } +.emoji-262E { background-position: -400px -800px; } +.emoji-262F { background-position: -420px -800px; } +.emoji-2638 { background-position: -440px -800px; } +.emoji-2639 { background-position: -460px -800px; } +.emoji-263A { background-position: -480px -800px; } +.emoji-2648 { background-position: -500px -800px; } +.emoji-2649 { background-position: -520px -800px; } +.emoji-264A { background-position: -540px -800px; } +.emoji-264B { background-position: -560px -800px; } +.emoji-264C { background-position: -580px -800px; } +.emoji-264D { background-position: -600px -800px; } +.emoji-264E { background-position: -620px -800px; } +.emoji-264F { background-position: -640px -800px; } +.emoji-2650 { background-position: -660px -800px; } +.emoji-2651 { background-position: -680px -800px; } +.emoji-2652 { background-position: -700px -800px; } +.emoji-2653 { background-position: -720px -800px; } +.emoji-2660 { background-position: -740px -800px; } +.emoji-2663 { background-position: -760px -800px; } +.emoji-2665 { background-position: -780px -800px; } +.emoji-2666 { background-position: -800px -800px; } +.emoji-2668 { background-position: -820px 0; } +.emoji-267B { background-position: -820px -20px; } +.emoji-267F { background-position: -820px -40px; } +.emoji-2692 { background-position: -820px -60px; } +.emoji-2693 { background-position: -820px -80px; } +.emoji-2694 { background-position: -820px -100px; } +.emoji-2696 { background-position: -820px -120px; } +.emoji-2697 { background-position: -820px -140px; } +.emoji-2699 { background-position: -820px -160px; } +.emoji-269B { background-position: -820px -180px; } +.emoji-269C { background-position: -820px -200px; } +.emoji-26A0 { background-position: -820px -220px; } +.emoji-26A1 { background-position: -820px -240px; } +.emoji-26AA { background-position: -820px -260px; } +.emoji-26AB { background-position: -820px -280px; } +.emoji-26B0 { background-position: -820px -300px; } +.emoji-26B1 { background-position: -820px -320px; } +.emoji-26BD { background-position: -820px -340px; } +.emoji-26BE { background-position: -820px -360px; } +.emoji-26C4 { background-position: -820px -380px; } +.emoji-26C5 { background-position: -820px -400px; } +.emoji-26C8 { background-position: -820px -420px; } +.emoji-26CE { background-position: -820px -440px; } +.emoji-26CF { background-position: -820px -460px; } +.emoji-26D1 { background-position: -820px -480px; } +.emoji-26D3 { background-position: -820px -500px; } +.emoji-26D4 { background-position: -820px -520px; } +.emoji-26E9 { background-position: -820px -540px; } +.emoji-26EA { background-position: -820px -560px; } +.emoji-26F0 { background-position: -820px -580px; } +.emoji-26F1 { background-position: -820px -600px; } +.emoji-26F2 { background-position: -820px -620px; } +.emoji-26F3 { background-position: -820px -640px; } +.emoji-26F4 { background-position: -820px -660px; } +.emoji-26F5 { background-position: -820px -680px; } +.emoji-26F7 { background-position: -820px -700px; } +.emoji-26F8 { background-position: -820px -720px; } +.emoji-26F9 { background-position: -820px -740px; } +.emoji-26F9-1F3FB { background-position: -820px -760px; } +.emoji-26F9-1F3FC { background-position: -820px -780px; } +.emoji-26F9-1F3FD { background-position: -820px -800px; } +.emoji-26F9-1F3FE { background-position: 0 -820px; } +.emoji-26F9-1F3FF { background-position: -20px -820px; } +.emoji-26FA { background-position: -40px -820px; } +.emoji-26FD { background-position: -60px -820px; } +.emoji-2702 { background-position: -80px -820px; } +.emoji-2705 { background-position: -100px -820px; } +.emoji-2708 { background-position: -120px -820px; } +.emoji-2709 { background-position: -140px -820px; } +.emoji-270A { background-position: -160px -820px; } +.emoji-270A-1F3FB { background-position: -180px -820px; } +.emoji-270A-1F3FC { background-position: -200px -820px; } +.emoji-270A-1F3FD { background-position: -220px -820px; } +.emoji-270A-1F3FE { background-position: -240px -820px; } +.emoji-270A-1F3FF { background-position: -260px -820px; } +.emoji-270B { background-position: -280px -820px; } +.emoji-270B-1F3FB { background-position: -300px -820px; } +.emoji-270B-1F3FC { background-position: -320px -820px; } +.emoji-270B-1F3FD { background-position: -340px -820px; } +.emoji-270B-1F3FE { background-position: -360px -820px; } +.emoji-270B-1F3FF { background-position: -380px -820px; } +.emoji-270C { background-position: -400px -820px; } +.emoji-270C-1F3FB { background-position: -420px -820px; } +.emoji-270C-1F3FC { background-position: -440px -820px; } +.emoji-270C-1F3FD { background-position: -460px -820px; } +.emoji-270C-1F3FE { background-position: -480px -820px; } +.emoji-270C-1F3FF { background-position: -500px -820px; } +.emoji-270D { background-position: -520px -820px; } +.emoji-270D-1F3FB { background-position: -540px -820px; } +.emoji-270D-1F3FC { background-position: -560px -820px; } +.emoji-270D-1F3FD { background-position: -580px -820px; } +.emoji-270D-1F3FE { background-position: -600px -820px; } +.emoji-270D-1F3FF { background-position: -620px -820px; } +.emoji-270F { background-position: -640px -820px; } +.emoji-2712 { background-position: -660px -820px; } +.emoji-2714 { background-position: -680px -820px; } +.emoji-2716 { background-position: -700px -820px; } +.emoji-271D { background-position: -720px -820px; } +.emoji-2721 { background-position: -740px -820px; } +.emoji-2728 { background-position: -760px -820px; } +.emoji-2733 { background-position: -780px -820px; } +.emoji-2734 { background-position: -800px -820px; } +.emoji-2744 { background-position: -820px -820px; } +.emoji-2747 { background-position: -840px 0; } +.emoji-274C { background-position: -840px -20px; } +.emoji-274E { background-position: -840px -40px; } +.emoji-2753 { background-position: -840px -60px; } +.emoji-2754 { background-position: -840px -80px; } +.emoji-2755 { background-position: -840px -100px; } +.emoji-2757 { background-position: -840px -120px; } +.emoji-2763 { background-position: -840px -140px; } +.emoji-2764 { background-position: -840px -160px; } +.emoji-2795 { background-position: -840px -180px; } +.emoji-2796 { background-position: -840px -200px; } +.emoji-2797 { background-position: -840px -220px; } +.emoji-27A1 { background-position: -840px -240px; } +.emoji-27B0 { background-position: -840px -260px; } +.emoji-27BF { background-position: -840px -280px; } +.emoji-2934 { background-position: -840px -300px; } +.emoji-2935 { background-position: -840px -320px; } +.emoji-2B05 { background-position: -840px -340px; } +.emoji-2B06 { background-position: -840px -360px; } +.emoji-2B07 { background-position: -840px -380px; } +.emoji-2B1B { background-position: -840px -400px; } +.emoji-2B1C { background-position: -840px -420px; } +.emoji-2B50 { background-position: -840px -440px; } +.emoji-2B55 { background-position: -840px -460px; } +.emoji-3030 { background-position: -840px -480px; } +.emoji-303D { background-position: -840px -500px; } +.emoji-3297 { background-position: -840px -520px; } +.emoji-3299 { background-position: -840px -540px; } + +.emoji-icon { + background-image: image-url('emoji.png'); + background-repeat: no-repeat; + height: 20px; + width: 20px; + + @media only screen and (-webkit-min-device-pixel-ratio: 2), + only screen and (min--moz-device-pixel-ratio: 2), + only screen and (-o-min-device-pixel-ratio: 2/1), + only screen and (min-device-pixel-ratio: 2), + only screen and (min-resolution: 192dpi), + only screen and (min-resolution: 2dppx) { + background-image: image-url('emoji@2x.png'); + background-size: 860px 840px; + } +} diff --git a/app/assets/stylesheets/framework/icons.scss b/app/assets/stylesheets/framework/icons.scss new file mode 100644 index 00000000000..226bd2ead31 --- /dev/null +++ b/app/assets/stylesheets/framework/icons.scss @@ -0,0 +1,51 @@ +.ci-status-icon-success { + color: $gl-success; + + svg { + fill: $gl-success; + } +} + +.ci-status-icon-failed { + color: $gl-danger; + + svg { + fill: $gl-danger; + } +} + +.ci-status-icon-pending, +.ci-status-icon-success_with_warnings { + color: $gl-warning; + + svg { + fill: $gl-warning; + } +} + +.ci-status-icon-running { + color: $blue-normal; + + svg { + fill: $blue-normal; + } +} + +.ci-status-icon-canceled, +.ci-status-icon-disabled, +.ci-status-icon-not-found { + color: $gl-gray; + + svg { + fill: $gl-gray; + } +} + +.ci-status-icon-created, +.ci-status-icon-skipped { + color: $gray-darkest; + + svg { + fill: $gray-darkest; + } +} diff --git a/app/assets/stylesheets/pages/emojis.scss b/app/assets/stylesheets/pages/emojis.scss deleted file mode 100644 index f17797b2381..00000000000 --- a/app/assets/stylesheets/pages/emojis.scss +++ /dev/null @@ -1,1809 +0,0 @@ -.emoji-0023-20E3 { background-position: 0 0px; } -.emoji-002A-20E3 { background-position: -20px 0; } -.emoji-0030-20E3 { background-position: 0 -20px; } -.emoji-0031-20E3 { background-position: -20px -20px; } -.emoji-0032-20E3 { background-position: -40px 0; } -.emoji-0033-20E3 { background-position: -40px -20px; } -.emoji-0034-20E3 { background-position: 0 -40px; } -.emoji-0035-20E3 { background-position: -20px -40px; } -.emoji-0036-20E3 { background-position: -40px -40px; } -.emoji-0037-20E3 { background-position: -60px 0; } -.emoji-0038-20E3 { background-position: -60px -20px; } -.emoji-0039-20E3 { background-position: -60px -40px; } -.emoji-00A9 { background-position: 0 -60px; } -.emoji-00AE { background-position: -20px -60px; } -.emoji-1F004 { background-position: -40px -60px; } -.emoji-1F0CF { background-position: -60px -60px; } -.emoji-1F170 { background-position: -80px 0; } -.emoji-1F171 { background-position: -80px -20px; } -.emoji-1F17E { background-position: -80px -40px; } -.emoji-1F17F { background-position: -80px -60px; } -.emoji-1F18E { background-position: 0 -80px; } -.emoji-1F191 { background-position: -20px -80px; } -.emoji-1F192 { background-position: -40px -80px; } -.emoji-1F193 { background-position: -60px -80px; } -.emoji-1F194 { background-position: -80px -80px; } -.emoji-1F195 { background-position: -100px 0; } -.emoji-1F196 { background-position: -100px -20px; } -.emoji-1F197 { background-position: -100px -40px; } -.emoji-1F198 { background-position: -100px -60px; } -.emoji-1F199 { background-position: -100px -80px; } -.emoji-1F19A { background-position: 0 -100px; } -.emoji-1F1E6-1F1E8 { background-position: -20px -100px; } -.emoji-1F1E6-1F1E9 { background-position: -40px -100px; } -.emoji-1F1E6-1F1EA { background-position: -60px -100px; } -.emoji-1F1E6-1F1EB { background-position: -80px -100px; } -.emoji-1F1E6-1F1EC { background-position: -100px -100px; } -.emoji-1F1E6-1F1EE { background-position: -120px 0; } -.emoji-1F1E6-1F1F1 { background-position: -120px -20px; } -.emoji-1F1E6-1F1F2 { background-position: -120px -40px; } -.emoji-1F1E6-1F1F4 { background-position: -120px -60px; } -.emoji-1F1E6-1F1F6 { background-position: -120px -80px; } -.emoji-1F1E6-1F1F7 { background-position: -120px -100px; } -.emoji-1F1E6-1F1F8 { background-position: 0 -120px; } -.emoji-1F1E6-1F1F9 { background-position: -20px -120px; } -.emoji-1F1E6-1F1FA { background-position: -40px -120px; } -.emoji-1F1E6-1F1FC { background-position: -60px -120px; } -.emoji-1F1E6-1F1FD { background-position: -80px -120px; } -.emoji-1F1E6-1F1FF { background-position: -100px -120px; } -.emoji-1F1E7-1F1E6 { background-position: -120px -120px; } -.emoji-1F1E7-1F1E7 { background-position: -140px 0; } -.emoji-1F1E7-1F1E9 { background-position: -140px -20px; } -.emoji-1F1E7-1F1EA { background-position: -140px -40px; } -.emoji-1F1E7-1F1EB { background-position: -140px -60px; } -.emoji-1F1E7-1F1EC { background-position: -140px -80px; } -.emoji-1F1E7-1F1ED { background-position: -140px -100px; } -.emoji-1F1E7-1F1EE { background-position: -140px -120px; } -.emoji-1F1E7-1F1EF { background-position: 0 -140px; } -.emoji-1F1E7-1F1F1 { background-position: -20px -140px; } -.emoji-1F1E7-1F1F2 { background-position: -40px -140px; } -.emoji-1F1E7-1F1F3 { background-position: -60px -140px; } -.emoji-1F1E7-1F1F4 { background-position: -80px -140px; } -.emoji-1F1E7-1F1F6 { background-position: -100px -140px; } -.emoji-1F1E7-1F1F7 { background-position: -120px -140px; } -.emoji-1F1E7-1F1F8 { background-position: -140px -140px; } -.emoji-1F1E7-1F1F9 { background-position: -160px 0; } -.emoji-1F1E7-1F1FB { background-position: -160px -20px; } -.emoji-1F1E7-1F1FC { background-position: -160px -40px; } -.emoji-1F1E7-1F1FE { background-position: -160px -60px; } -.emoji-1F1E7-1F1FF { background-position: -160px -80px; } -.emoji-1F1E8-1F1E6 { background-position: -160px -100px; } -.emoji-1F1E8-1F1E8 { background-position: -160px -120px; } -.emoji-1F1E8-1F1E9 { background-position: -160px -140px; } -.emoji-1F1E8-1F1EB { background-position: 0 -160px; } -.emoji-1F1E8-1F1EC { background-position: -20px -160px; } -.emoji-1F1E8-1F1ED { background-position: -40px -160px; } -.emoji-1F1E8-1F1EE { background-position: -60px -160px; } -.emoji-1F1E8-1F1F0 { background-position: -80px -160px; } -.emoji-1F1E8-1F1F1 { background-position: -100px -160px; } -.emoji-1F1E8-1F1F2 { background-position: -120px -160px; } -.emoji-1F1E8-1F1F3 { background-position: -140px -160px; } -.emoji-1F1E8-1F1F4 { background-position: -160px -160px; } -.emoji-1F1E8-1F1F5 { background-position: -180px 0; } -.emoji-1F1E8-1F1F7 { background-position: -180px -20px; } -.emoji-1F1E8-1F1FA { background-position: -180px -40px; } -.emoji-1F1E8-1F1FB { background-position: -180px -60px; } -.emoji-1F1E8-1F1FC { background-position: -180px -80px; } -.emoji-1F1E8-1F1FD { background-position: -180px -100px; } -.emoji-1F1E8-1F1FE { background-position: -180px -120px; } -.emoji-1F1E8-1F1FF { background-position: -180px -140px; } -.emoji-1F1E9-1F1EA { background-position: -180px -160px; } -.emoji-1F1E9-1F1EC { background-position: 0 -180px; } -.emoji-1F1E9-1F1EF { background-position: -20px -180px; } -.emoji-1F1E9-1F1F0 { background-position: -40px -180px; } -.emoji-1F1E9-1F1F2 { background-position: -60px -180px; } -.emoji-1F1E9-1F1F4 { background-position: -80px -180px; } -.emoji-1F1E9-1F1FF { background-position: -100px -180px; } -.emoji-1F1EA-1F1E6 { background-position: -120px -180px; } -.emoji-1F1EA-1F1E8 { background-position: -140px -180px; } -.emoji-1F1EA-1F1EA { background-position: -160px -180px; } -.emoji-1F1EA-1F1EC { background-position: -180px -180px; } -.emoji-1F1EA-1F1ED { background-position: -200px 0; } -.emoji-1F1EA-1F1F7 { background-position: -200px -20px; } -.emoji-1F1EA-1F1F8 { background-position: -200px -40px; } -.emoji-1F1EA-1F1F9 { background-position: -200px -60px; } -.emoji-1F1EA-1F1FA { background-position: -200px -80px; } -.emoji-1F1EB-1F1EE { background-position: -200px -100px; } -.emoji-1F1EB-1F1EF { background-position: -200px -120px; } -.emoji-1F1EB-1F1F0 { background-position: -200px -140px; } -.emoji-1F1EB-1F1F2 { background-position: -200px -160px; } -.emoji-1F1EB-1F1F4 { background-position: -200px -180px; } -.emoji-1F1EB-1F1F7 { background-position: 0 -200px; } -.emoji-1F1EC-1F1E6 { background-position: -20px -200px; } -.emoji-1F1EC-1F1E7 { background-position: -40px -200px; } -.emoji-1F1EC-1F1E9 { background-position: -60px -200px; } -.emoji-1F1EC-1F1EA { background-position: -80px -200px; } -.emoji-1F1EC-1F1EB { background-position: -100px -200px; } -.emoji-1F1EC-1F1EC { background-position: -120px -200px; } -.emoji-1F1EC-1F1ED { background-position: -140px -200px; } -.emoji-1F1EC-1F1EE { background-position: -160px -200px; } -.emoji-1F1EC-1F1F1 { background-position: -180px -200px; } -.emoji-1F1EC-1F1F2 { background-position: -200px -200px; } -.emoji-1F1EC-1F1F3 { background-position: -220px 0; } -.emoji-1F1EC-1F1F5 { background-position: -220px -20px; } -.emoji-1F1EC-1F1F6 { background-position: -220px -40px; } -.emoji-1F1EC-1F1F7 { background-position: -220px -60px; } -.emoji-1F1EC-1F1F8 { background-position: -220px -80px; } -.emoji-1F1EC-1F1F9 { background-position: -220px -100px; } -.emoji-1F1EC-1F1FA { background-position: -220px -120px; } -.emoji-1F1EC-1F1FC { background-position: -220px -140px; } -.emoji-1F1EC-1F1FE { background-position: -220px -160px; } -.emoji-1F1ED-1F1F0 { background-position: -220px -180px; } -.emoji-1F1ED-1F1F2 { background-position: -220px -200px; } -.emoji-1F1ED-1F1F3 { background-position: 0 -220px; } -.emoji-1F1ED-1F1F7 { background-position: -20px -220px; } -.emoji-1F1ED-1F1F9 { background-position: -40px -220px; } -.emoji-1F1ED-1F1FA { background-position: -60px -220px; } -.emoji-1F1EE-1F1E8 { background-position: -80px -220px; } -.emoji-1F1EE-1F1E9 { background-position: -100px -220px; } -.emoji-1F1EE-1F1EA { background-position: -120px -220px; } -.emoji-1F1EE-1F1F1 { background-position: -140px -220px; } -.emoji-1F1EE-1F1F2 { background-position: -160px -220px; } -.emoji-1F1EE-1F1F3 { background-position: -180px -220px; } -.emoji-1F1EE-1F1F4 { background-position: -200px -220px; } -.emoji-1F1EE-1F1F6 { background-position: -220px -220px; } -.emoji-1F1EE-1F1F7 { background-position: -240px 0; } -.emoji-1F1EE-1F1F8 { background-position: -240px -20px; } -.emoji-1F1EE-1F1F9 { background-position: -240px -40px; } -.emoji-1F1EF-1F1EA { background-position: -240px -60px; } -.emoji-1F1EF-1F1F2 { background-position: -240px -80px; } -.emoji-1F1EF-1F1F4 { background-position: -240px -100px; } -.emoji-1F1EF-1F1F5 { background-position: -240px -120px; } -.emoji-1F1F0-1F1EA { background-position: -240px -140px; } -.emoji-1F1F0-1F1EC { background-position: -240px -160px; } -.emoji-1F1F0-1F1ED { background-position: -240px -180px; } -.emoji-1F1F0-1F1EE { background-position: -240px -200px; } -.emoji-1F1F0-1F1F2 { background-position: -240px -220px; } -.emoji-1F1F0-1F1F3 { background-position: 0 -240px; } -.emoji-1F1F0-1F1F5 { background-position: -20px -240px; } -.emoji-1F1F0-1F1F7 { background-position: -40px -240px; } -.emoji-1F1F0-1F1FC { background-position: -60px -240px; } -.emoji-1F1F0-1F1FE { background-position: -80px -240px; } -.emoji-1F1F0-1F1FF { background-position: -100px -240px; } -.emoji-1F1F1-1F1E6 { background-position: -120px -240px; } -.emoji-1F1F1-1F1E7 { background-position: -140px -240px; } -.emoji-1F1F1-1F1E8 { background-position: -160px -240px; } -.emoji-1F1F1-1F1EE { background-position: -180px -240px; } -.emoji-1F1F1-1F1F0 { background-position: -200px -240px; } -.emoji-1F1F1-1F1F7 { background-position: -220px -240px; } -.emoji-1F1F1-1F1F8 { background-position: -240px -240px; } -.emoji-1F1F1-1F1F9 { background-position: -260px 0; } -.emoji-1F1F1-1F1FA { background-position: -260px -20px; } -.emoji-1F1F1-1F1FB { background-position: -260px -40px; } -.emoji-1F1F1-1F1FE { background-position: -260px -60px; } -.emoji-1F1F2-1F1E6 { background-position: -260px -80px; } -.emoji-1F1F2-1F1E8 { background-position: -260px -100px; } -.emoji-1F1F2-1F1E9 { background-position: -260px -120px; } -.emoji-1F1F2-1F1EA { background-position: -260px -140px; } -.emoji-1F1F2-1F1EB { background-position: -260px -160px; } -.emoji-1F1F2-1F1EC { background-position: -260px -180px; } -.emoji-1F1F2-1F1ED { background-position: -260px -200px; } -.emoji-1F1F2-1F1F0 { background-position: -260px -220px; } -.emoji-1F1F2-1F1F1 { background-position: -260px -240px; } -.emoji-1F1F2-1F1F2 { background-position: 0 -260px; } -.emoji-1F1F2-1F1F3 { background-position: -20px -260px; } -.emoji-1F1F2-1F1F4 { background-position: -40px -260px; } -.emoji-1F1F2-1F1F5 { background-position: -60px -260px; } -.emoji-1F1F2-1F1F6 { background-position: -80px -260px; } -.emoji-1F1F2-1F1F7 { background-position: -100px -260px; } -.emoji-1F1F2-1F1F8 { background-position: -120px -260px; } -.emoji-1F1F2-1F1F9 { background-position: -140px -260px; } -.emoji-1F1F2-1F1FA { background-position: -160px -260px; } -.emoji-1F1F2-1F1FB { background-position: -180px -260px; } -.emoji-1F1F2-1F1FC { background-position: -200px -260px; } -.emoji-1F1F2-1F1FD { background-position: -220px -260px; } -.emoji-1F1F2-1F1FE { background-position: -240px -260px; } -.emoji-1F1F2-1F1FF { background-position: -260px -260px; } -.emoji-1F1F3-1F1E6 { background-position: -280px 0; } -.emoji-1F1F3-1F1E8 { background-position: -280px -20px; } -.emoji-1F1F3-1F1EA { background-position: -280px -40px; } -.emoji-1F1F3-1F1EB { background-position: -280px -60px; } -.emoji-1F1F3-1F1EC { background-position: -280px -80px; } -.emoji-1F1F3-1F1EE { background-position: -280px -100px; } -.emoji-1F1F3-1F1F1 { background-position: -280px -120px; } -.emoji-1F1F3-1F1F4 { background-position: -280px -140px; } -.emoji-1F1F3-1F1F5 { background-position: -280px -160px; } -.emoji-1F1F3-1F1F7 { background-position: -280px -180px; } -.emoji-1F1F3-1F1FA { background-position: -280px -200px; } -.emoji-1F1F3-1F1FF { background-position: -280px -220px; } -.emoji-1F1F4-1F1F2 { background-position: -280px -240px; } -.emoji-1F1F5-1F1E6 { background-position: -280px -260px; } -.emoji-1F1F5-1F1EA { background-position: 0 -280px; } -.emoji-1F1F5-1F1EB { background-position: -20px -280px; } -.emoji-1F1F5-1F1EC { background-position: -40px -280px; } -.emoji-1F1F5-1F1ED { background-position: -60px -280px; } -.emoji-1F1F5-1F1F0 { background-position: -80px -280px; } -.emoji-1F1F5-1F1F1 { background-position: -100px -280px; } -.emoji-1F1F5-1F1F2 { background-position: -120px -280px; } -.emoji-1F1F5-1F1F3 { background-position: -140px -280px; } -.emoji-1F1F5-1F1F7 { background-position: -160px -280px; } -.emoji-1F1F5-1F1F8 { background-position: -180px -280px; } -.emoji-1F1F5-1F1F9 { background-position: -200px -280px; } -.emoji-1F1F5-1F1FC { background-position: -220px -280px; } -.emoji-1F1F5-1F1FE { background-position: -240px -280px; } -.emoji-1F1F6-1F1E6 { background-position: -260px -280px; } -.emoji-1F1F7-1F1EA { background-position: -280px -280px; } -.emoji-1F1F7-1F1F4 { background-position: -300px 0; } -.emoji-1F1F7-1F1F8 { background-position: -300px -20px; } -.emoji-1F1F7-1F1FA { background-position: -300px -40px; } -.emoji-1F1F7-1F1FC { background-position: -300px -60px; } -.emoji-1F1F8-1F1E6 { background-position: -300px -80px; } -.emoji-1F1F8-1F1E7 { background-position: -300px -100px; } -.emoji-1F1F8-1F1E8 { background-position: -300px -120px; } -.emoji-1F1F8-1F1E9 { background-position: -300px -140px; } -.emoji-1F1F8-1F1EA { background-position: -300px -160px; } -.emoji-1F1F8-1F1EC { background-position: -300px -180px; } -.emoji-1F1F8-1F1ED { background-position: -300px -200px; } -.emoji-1F1F8-1F1EE { background-position: -300px -220px; } -.emoji-1F1F8-1F1EF { background-position: -300px -240px; } -.emoji-1F1F8-1F1F0 { background-position: -300px -260px; } -.emoji-1F1F8-1F1F1 { background-position: -300px -280px; } -.emoji-1F1F8-1F1F2 { background-position: 0 -300px; } -.emoji-1F1F8-1F1F3 { background-position: -20px -300px; } -.emoji-1F1F8-1F1F4 { background-position: -40px -300px; } -.emoji-1F1F8-1F1F7 { background-position: -60px -300px; } -.emoji-1F1F8-1F1F8 { background-position: -80px -300px; } -.emoji-1F1F8-1F1F9 { background-position: -100px -300px; } -.emoji-1F1F8-1F1FB { background-position: -120px -300px; } -.emoji-1F1F8-1F1FD { background-position: -140px -300px; } -.emoji-1F1F8-1F1FE { background-position: -160px -300px; } -.emoji-1F1F8-1F1FF { background-position: -180px -300px; } -.emoji-1F1F9-1F1E6 { background-position: -200px -300px; } -.emoji-1F1F9-1F1E8 { background-position: -220px -300px; } -.emoji-1F1F9-1F1E9 { background-position: -240px -300px; } -.emoji-1F1F9-1F1EB { background-position: -260px -300px; } -.emoji-1F1F9-1F1EC { background-position: -280px -300px; } -.emoji-1F1F9-1F1ED { background-position: -300px -300px; } -.emoji-1F1F9-1F1EF { background-position: -320px 0; } -.emoji-1F1F9-1F1F0 { background-position: -320px -20px; } -.emoji-1F1F9-1F1F1 { background-position: -320px -40px; } -.emoji-1F1F9-1F1F2 { background-position: -320px -60px; } -.emoji-1F1F9-1F1F3 { background-position: -320px -80px; } -.emoji-1F1F9-1F1F4 { background-position: -320px -100px; } -.emoji-1F1F9-1F1F7 { background-position: -320px -120px; } -.emoji-1F1F9-1F1F9 { background-position: -320px -140px; } -.emoji-1F1F9-1F1FB { background-position: -320px -160px; } -.emoji-1F1F9-1F1FC { background-position: -320px -180px; } -.emoji-1F1F9-1F1FF { background-position: -320px -200px; } -.emoji-1F1FA-1F1E6 { background-position: -320px -220px; } -.emoji-1F1FA-1F1EC { background-position: -320px -240px; } -.emoji-1F1FA-1F1F2 { background-position: -320px -260px; } -.emoji-1F1FA-1F1F8 { background-position: -320px -280px; } -.emoji-1F1FA-1F1FE { background-position: -320px -300px; } -.emoji-1F1FA-1F1FF { background-position: 0 -320px; } -.emoji-1F1FB-1F1E6 { background-position: -20px -320px; } -.emoji-1F1FB-1F1E8 { background-position: -40px -320px; } -.emoji-1F1FB-1F1EA { background-position: -60px -320px; } -.emoji-1F1FB-1F1EC { background-position: -80px -320px; } -.emoji-1F1FB-1F1EE { background-position: -100px -320px; } -.emoji-1F1FB-1F1F3 { background-position: -120px -320px; } -.emoji-1F1FB-1F1FA { background-position: -140px -320px; } -.emoji-1F1FC-1F1EB { background-position: -160px -320px; } -.emoji-1F1FC-1F1F8 { background-position: -180px -320px; } -.emoji-1F1FD-1F1F0 { background-position: -200px -320px; } -.emoji-1F1FE-1F1EA { background-position: -220px -320px; } -.emoji-1F1FE-1F1F9 { background-position: -240px -320px; } -.emoji-1F1FF-1F1E6 { background-position: -260px -320px; } -.emoji-1F1FF-1F1F2 { background-position: -280px -320px; } -.emoji-1F1FF-1F1FC { background-position: -300px -320px; } -.emoji-1F201 { background-position: -320px -320px; } -.emoji-1F202 { background-position: -340px 0; } -.emoji-1F21A { background-position: -340px -20px; } -.emoji-1F22F { background-position: -340px -40px; } -.emoji-1F232 { background-position: -340px -60px; } -.emoji-1F233 { background-position: -340px -80px; } -.emoji-1F234 { background-position: -340px -100px; } -.emoji-1F235 { background-position: -340px -120px; } -.emoji-1F236 { background-position: -340px -140px; } -.emoji-1F237 { background-position: -340px -160px; } -.emoji-1F238 { background-position: -340px -180px; } -.emoji-1F239 { background-position: -340px -200px; } -.emoji-1F23A { background-position: -340px -220px; } -.emoji-1F250 { background-position: -340px -240px; } -.emoji-1F251 { background-position: -340px -260px; } -.emoji-1F300 { background-position: -340px -280px; } -.emoji-1F301 { background-position: -340px -300px; } -.emoji-1F302 { background-position: -340px -320px; } -.emoji-1F303 { background-position: 0 -340px; } -.emoji-1F304 { background-position: -20px -340px; } -.emoji-1F305 { background-position: -40px -340px; } -.emoji-1F306 { background-position: -60px -340px; } -.emoji-1F307 { background-position: -80px -340px; } -.emoji-1F308 { background-position: -100px -340px; } -.emoji-1F309 { background-position: -120px -340px; } -.emoji-1F30A { background-position: -140px -340px; } -.emoji-1F30B { background-position: -160px -340px; } -.emoji-1F30C { background-position: -180px -340px; } -.emoji-1F30D { background-position: -200px -340px; } -.emoji-1F30E { background-position: -220px -340px; } -.emoji-1F30F { background-position: -240px -340px; } -.emoji-1F310 { background-position: -260px -340px; } -.emoji-1F311 { background-position: -280px -340px; } -.emoji-1F312 { background-position: -300px -340px; } -.emoji-1F313 { background-position: -320px -340px; } -.emoji-1F314 { background-position: -340px -340px; } -.emoji-1F315 { background-position: -360px 0; } -.emoji-1F316 { background-position: -360px -20px; } -.emoji-1F317 { background-position: -360px -40px; } -.emoji-1F318 { background-position: -360px -60px; } -.emoji-1F319 { background-position: -360px -80px; } -.emoji-1F31A { background-position: -360px -100px; } -.emoji-1F31B { background-position: -360px -120px; } -.emoji-1F31C { background-position: -360px -140px; } -.emoji-1F31D { background-position: -360px -160px; } -.emoji-1F31E { background-position: -360px -180px; } -.emoji-1F31F { background-position: -360px -200px; } -.emoji-1F320 { background-position: -360px -220px; } -.emoji-1F321 { background-position: -360px -240px; } -.emoji-1F324 { background-position: -360px -260px; } -.emoji-1F325 { background-position: -360px -280px; } -.emoji-1F326 { background-position: -360px -300px; } -.emoji-1F327 { background-position: -360px -320px; } -.emoji-1F328 { background-position: -360px -340px; } -.emoji-1F329 { background-position: 0 -360px; } -.emoji-1F32A { background-position: -20px -360px; } -.emoji-1F32B { background-position: -40px -360px; } -.emoji-1F32C { background-position: -60px -360px; } -.emoji-1F32D { background-position: -80px -360px; } -.emoji-1F32E { background-position: -100px -360px; } -.emoji-1F32F { background-position: -120px -360px; } -.emoji-1F330 { background-position: -140px -360px; } -.emoji-1F331 { background-position: -160px -360px; } -.emoji-1F332 { background-position: -180px -360px; } -.emoji-1F333 { background-position: -200px -360px; } -.emoji-1F334 { background-position: -220px -360px; } -.emoji-1F335 { background-position: -240px -360px; } -.emoji-1F336 { background-position: -260px -360px; } -.emoji-1F337 { background-position: -280px -360px; } -.emoji-1F338 { background-position: -300px -360px; } -.emoji-1F339 { background-position: -320px -360px; } -.emoji-1F33A { background-position: -340px -360px; } -.emoji-1F33B { background-position: -360px -360px; } -.emoji-1F33C { background-position: -380px 0; } -.emoji-1F33D { background-position: -380px -20px; } -.emoji-1F33E { background-position: -380px -40px; } -.emoji-1F33F { background-position: -380px -60px; } -.emoji-1F340 { background-position: -380px -80px; } -.emoji-1F341 { background-position: -380px -100px; } -.emoji-1F342 { background-position: -380px -120px; } -.emoji-1F343 { background-position: -380px -140px; } -.emoji-1F344 { background-position: -380px -160px; } -.emoji-1F345 { background-position: -380px -180px; } -.emoji-1F346 { background-position: -380px -200px; } -.emoji-1F347 { background-position: -380px -220px; } -.emoji-1F348 { background-position: -380px -240px; } -.emoji-1F349 { background-position: -380px -260px; } -.emoji-1F34A { background-position: -380px -280px; } -.emoji-1F34B { background-position: -380px -300px; } -.emoji-1F34C { background-position: -380px -320px; } -.emoji-1F34D { background-position: -380px -340px; } -.emoji-1F34E { background-position: -380px -360px; } -.emoji-1F34F { background-position: 0 -380px; } -.emoji-1F350 { background-position: -20px -380px; } -.emoji-1F351 { background-position: -40px -380px; } -.emoji-1F352 { background-position: -60px -380px; } -.emoji-1F353 { background-position: -80px -380px; } -.emoji-1F354 { background-position: -100px -380px; } -.emoji-1F355 { background-position: -120px -380px; } -.emoji-1F356 { background-position: -140px -380px; } -.emoji-1F357 { background-position: -160px -380px; } -.emoji-1F358 { background-position: -180px -380px; } -.emoji-1F359 { background-position: -200px -380px; } -.emoji-1F35A { background-position: -220px -380px; } -.emoji-1F35B { background-position: -240px -380px; } -.emoji-1F35C { background-position: -260px -380px; } -.emoji-1F35D { background-position: -280px -380px; } -.emoji-1F35E { background-position: -300px -380px; } -.emoji-1F35F { background-position: -320px -380px; } -.emoji-1F360 { background-position: -340px -380px; } -.emoji-1F361 { background-position: -360px -380px; } -.emoji-1F362 { background-position: -380px -380px; } -.emoji-1F363 { background-position: -400px 0; } -.emoji-1F364 { background-position: -400px -20px; } -.emoji-1F365 { background-position: -400px -40px; } -.emoji-1F366 { background-position: -400px -60px; } -.emoji-1F367 { background-position: -400px -80px; } -.emoji-1F368 { background-position: -400px -100px; } -.emoji-1F369 { background-position: -400px -120px; } -.emoji-1F36A { background-position: -400px -140px; } -.emoji-1F36B { background-position: -400px -160px; } -.emoji-1F36C { background-position: -400px -180px; } -.emoji-1F36D { background-position: -400px -200px; } -.emoji-1F36E { background-position: -400px -220px; } -.emoji-1F36F { background-position: -400px -240px; } -.emoji-1F370 { background-position: -400px -260px; } -.emoji-1F371 { background-position: -400px -280px; } -.emoji-1F372 { background-position: -400px -300px; } -.emoji-1F373 { background-position: -400px -320px; } -.emoji-1F374 { background-position: -400px -340px; } -.emoji-1F375 { background-position: -400px -360px; } -.emoji-1F376 { background-position: -400px -380px; } -.emoji-1F377 { background-position: 0 -400px; } -.emoji-1F378 { background-position: -20px -400px; } -.emoji-1F379 { background-position: -40px -400px; } -.emoji-1F37A { background-position: -60px -400px; } -.emoji-1F37B { background-position: -80px -400px; } -.emoji-1F37C { background-position: -100px -400px; } -.emoji-1F37D { background-position: -120px -400px; } -.emoji-1F37E { background-position: -140px -400px; } -.emoji-1F37F { background-position: -160px -400px; } -.emoji-1F380 { background-position: -180px -400px; } -.emoji-1F381 { background-position: -200px -400px; } -.emoji-1F382 { background-position: -220px -400px; } -.emoji-1F383 { background-position: -240px -400px; } -.emoji-1F384 { background-position: -260px -400px; } -.emoji-1F385 { background-position: -280px -400px; } -.emoji-1F385-1F3FB { background-position: -300px -400px; } -.emoji-1F385-1F3FC { background-position: -320px -400px; } -.emoji-1F385-1F3FD { background-position: -340px -400px; } -.emoji-1F385-1F3FE { background-position: -360px -400px; } -.emoji-1F385-1F3FF { background-position: -380px -400px; } -.emoji-1F386 { background-position: -400px -400px; } -.emoji-1F387 { background-position: -420px 0; } -.emoji-1F388 { background-position: -420px -20px; } -.emoji-1F389 { background-position: -420px -40px; } -.emoji-1F38A { background-position: -420px -60px; } -.emoji-1F38B { background-position: -420px -80px; } -.emoji-1F38C { background-position: -420px -100px; } -.emoji-1F38D { background-position: -420px -120px; } -.emoji-1F38E { background-position: -420px -140px; } -.emoji-1F38F { background-position: -420px -160px; } -.emoji-1F390 { background-position: -420px -180px; } -.emoji-1F391 { background-position: -420px -200px; } -.emoji-1F392 { background-position: -420px -220px; } -.emoji-1F393 { background-position: -420px -240px; } -.emoji-1F396 { background-position: -420px -260px; } -.emoji-1F397 { background-position: -420px -280px; } -.emoji-1F399 { background-position: -420px -300px; } -.emoji-1F39A { background-position: -420px -320px; } -.emoji-1F39B { background-position: -420px -340px; } -.emoji-1F39E { background-position: -420px -360px; } -.emoji-1F39F { background-position: -420px -380px; } -.emoji-1F3A0 { background-position: -420px -400px; } -.emoji-1F3A1 { background-position: 0 -420px; } -.emoji-1F3A2 { background-position: -20px -420px; } -.emoji-1F3A3 { background-position: -40px -420px; } -.emoji-1F3A4 { background-position: -60px -420px; } -.emoji-1F3A5 { background-position: -80px -420px; } -.emoji-1F3A6 { background-position: -100px -420px; } -.emoji-1F3A7 { background-position: -120px -420px; } -.emoji-1F3A8 { background-position: -140px -420px; } -.emoji-1F3A9 { background-position: -160px -420px; } -.emoji-1F3AA { background-position: -180px -420px; } -.emoji-1F3AB { background-position: -200px -420px; } -.emoji-1F3AC { background-position: -220px -420px; } -.emoji-1F3AD { background-position: -240px -420px; } -.emoji-1F3AE { background-position: -260px -420px; } -.emoji-1F3AF { background-position: -280px -420px; } -.emoji-1F3B0 { background-position: -300px -420px; } -.emoji-1F3B1 { background-position: -320px -420px; } -.emoji-1F3B2 { background-position: -340px -420px; } -.emoji-1F3B3 { background-position: -360px -420px; } -.emoji-1F3B4 { background-position: -380px -420px; } -.emoji-1F3B5 { background-position: -400px -420px; } -.emoji-1F3B6 { background-position: -420px -420px; } -.emoji-1F3B7 { background-position: -440px 0; } -.emoji-1F3B8 { background-position: -440px -20px; } -.emoji-1F3B9 { background-position: -440px -40px; } -.emoji-1F3BA { background-position: -440px -60px; } -.emoji-1F3BB { background-position: -440px -80px; } -.emoji-1F3BC { background-position: -440px -100px; } -.emoji-1F3BD { background-position: -440px -120px; } -.emoji-1F3BE { background-position: -440px -140px; } -.emoji-1F3BF { background-position: -440px -160px; } -.emoji-1F3C0 { background-position: -440px -180px; } -.emoji-1F3C1 { background-position: -440px -200px; } -.emoji-1F3C2 { background-position: -440px -220px; } -.emoji-1F3C3 { background-position: -440px -240px; } -.emoji-1F3C3-1F3FB { background-position: -440px -260px; } -.emoji-1F3C3-1F3FC { background-position: -440px -280px; } -.emoji-1F3C3-1F3FD { background-position: -440px -300px; } -.emoji-1F3C3-1F3FE { background-position: -440px -320px; } -.emoji-1F3C3-1F3FF { background-position: -440px -340px; } -.emoji-1F3C4 { background-position: -440px -360px; } -.emoji-1F3C4-1F3FB { background-position: -440px -380px; } -.emoji-1F3C4-1F3FC { background-position: -440px -400px; } -.emoji-1F3C4-1F3FD { background-position: -440px -420px; } -.emoji-1F3C4-1F3FE { background-position: 0 -440px; } -.emoji-1F3C4-1F3FF { background-position: -20px -440px; } -.emoji-1F3C5 { background-position: -40px -440px; } -.emoji-1F3C6 { background-position: -60px -440px; } -.emoji-1F3C7 { background-position: -80px -440px; } -.emoji-1F3C7-1F3FB { background-position: -100px -440px; } -.emoji-1F3C7-1F3FC { background-position: -120px -440px; } -.emoji-1F3C7-1F3FD { background-position: -140px -440px; } -.emoji-1F3C7-1F3FE { background-position: -160px -440px; } -.emoji-1F3C7-1F3FF { background-position: -180px -440px; } -.emoji-1F3C8 { background-position: -200px -440px; } -.emoji-1F3C9 { background-position: -220px -440px; } -.emoji-1F3CA { background-position: -240px -440px; } -.emoji-1F3CA-1F3FB { background-position: -260px -440px; } -.emoji-1F3CA-1F3FC { background-position: -280px -440px; } -.emoji-1F3CA-1F3FD { background-position: -300px -440px; } -.emoji-1F3CA-1F3FE { background-position: -320px -440px; } -.emoji-1F3CA-1F3FF { background-position: -340px -440px; } -.emoji-1F3CB { background-position: -360px -440px; } -.emoji-1F3CB-1F3FB { background-position: -380px -440px; } -.emoji-1F3CB-1F3FC { background-position: -400px -440px; } -.emoji-1F3CB-1F3FD { background-position: -420px -440px; } -.emoji-1F3CB-1F3FE { background-position: -440px -440px; } -.emoji-1F3CB-1F3FF { background-position: -460px 0; } -.emoji-1F3CC { background-position: -460px -20px; } -.emoji-1F3CD { background-position: -460px -40px; } -.emoji-1F3CE { background-position: -460px -60px; } -.emoji-1F3CF { background-position: -460px -80px; } -.emoji-1F3D0 { background-position: -460px -100px; } -.emoji-1F3D1 { background-position: -460px -120px; } -.emoji-1F3D2 { background-position: -460px -140px; } -.emoji-1F3D3 { background-position: -460px -160px; } -.emoji-1F3D4 { background-position: -460px -180px; } -.emoji-1F3D5 { background-position: -460px -200px; } -.emoji-1F3D6 { background-position: -460px -220px; } -.emoji-1F3D7 { background-position: -460px -240px; } -.emoji-1F3D8 { background-position: -460px -260px; } -.emoji-1F3D9 { background-position: -460px -280px; } -.emoji-1F3DA { background-position: -460px -300px; } -.emoji-1F3DB { background-position: -460px -320px; } -.emoji-1F3DC { background-position: -460px -340px; } -.emoji-1F3DD { background-position: -460px -360px; } -.emoji-1F3DE { background-position: -460px -380px; } -.emoji-1F3DF { background-position: -460px -400px; } -.emoji-1F3E0 { background-position: -460px -420px; } -.emoji-1F3E1 { background-position: -460px -440px; } -.emoji-1F3E2 { background-position: 0 -460px; } -.emoji-1F3E3 { background-position: -20px -460px; } -.emoji-1F3E4 { background-position: -40px -460px; } -.emoji-1F3E5 { background-position: -60px -460px; } -.emoji-1F3E6 { background-position: -80px -460px; } -.emoji-1F3E7 { background-position: -100px -460px; } -.emoji-1F3E8 { background-position: -120px -460px; } -.emoji-1F3E9 { background-position: -140px -460px; } -.emoji-1F3EA { background-position: -160px -460px; } -.emoji-1F3EB { background-position: -180px -460px; } -.emoji-1F3EC { background-position: -200px -460px; } -.emoji-1F3ED { background-position: -220px -460px; } -.emoji-1F3EE { background-position: -240px -460px; } -.emoji-1F3EF { background-position: -260px -460px; } -.emoji-1F3F0 { background-position: -280px -460px; } -.emoji-1F3F3 { background-position: -300px -460px; } -.emoji-1F3F4 { background-position: -320px -460px; } -.emoji-1F3F5 { background-position: -340px -460px; } -.emoji-1F3F7 { background-position: -360px -460px; } -.emoji-1F3F8 { background-position: -380px -460px; } -.emoji-1F3F9 { background-position: -400px -460px; } -.emoji-1F3FA { background-position: -420px -460px; } -.emoji-1F3FB { background-position: -440px -460px; } -.emoji-1F3FC { background-position: -460px -460px; } -.emoji-1F3FD { background-position: -480px 0; } -.emoji-1F3FE { background-position: -480px -20px; } -.emoji-1F3FF { background-position: -480px -40px; } -.emoji-1F400 { background-position: -480px -60px; } -.emoji-1F401 { background-position: -480px -80px; } -.emoji-1F402 { background-position: -480px -100px; } -.emoji-1F403 { background-position: -480px -120px; } -.emoji-1F404 { background-position: -480px -140px; } -.emoji-1F405 { background-position: -480px -160px; } -.emoji-1F406 { background-position: -480px -180px; } -.emoji-1F407 { background-position: -480px -200px; } -.emoji-1F408 { background-position: -480px -220px; } -.emoji-1F409 { background-position: -480px -240px; } -.emoji-1F40A { background-position: -480px -260px; } -.emoji-1F40B { background-position: -480px -280px; } -.emoji-1F40C { background-position: -480px -300px; } -.emoji-1F40D { background-position: -480px -320px; } -.emoji-1F40E { background-position: -480px -340px; } -.emoji-1F40F { background-position: -480px -360px; } -.emoji-1F410 { background-position: -480px -380px; } -.emoji-1F411 { background-position: -480px -400px; } -.emoji-1F412 { background-position: -480px -420px; } -.emoji-1F413 { background-position: -480px -440px; } -.emoji-1F414 { background-position: -480px -460px; } -.emoji-1F415 { background-position: 0 -480px; } -.emoji-1F416 { background-position: -20px -480px; } -.emoji-1F417 { background-position: -40px -480px; } -.emoji-1F418 { background-position: -60px -480px; } -.emoji-1F419 { background-position: -80px -480px; } -.emoji-1F41A { background-position: -100px -480px; } -.emoji-1F41B { background-position: -120px -480px; } -.emoji-1F41C { background-position: -140px -480px; } -.emoji-1F41D { background-position: -160px -480px; } -.emoji-1F41E { background-position: -180px -480px; } -.emoji-1F41F { background-position: -200px -480px; } -.emoji-1F420 { background-position: -220px -480px; } -.emoji-1F421 { background-position: -240px -480px; } -.emoji-1F422 { background-position: -260px -480px; } -.emoji-1F423 { background-position: -280px -480px; } -.emoji-1F424 { background-position: -300px -480px; } -.emoji-1F425 { background-position: -320px -480px; } -.emoji-1F426 { background-position: -340px -480px; } -.emoji-1F427 { background-position: -360px -480px; } -.emoji-1F428 { background-position: -380px -480px; } -.emoji-1F429 { background-position: -400px -480px; } -.emoji-1F42A { background-position: -420px -480px; } -.emoji-1F42B { background-position: -440px -480px; } -.emoji-1F42C { background-position: -460px -480px; } -.emoji-1F42D { background-position: -480px -480px; } -.emoji-1F42E { background-position: -500px 0; } -.emoji-1F42F { background-position: -500px -20px; } -.emoji-1F430 { background-position: -500px -40px; } -.emoji-1F431 { background-position: -500px -60px; } -.emoji-1F432 { background-position: -500px -80px; } -.emoji-1F433 { background-position: -500px -100px; } -.emoji-1F434 { background-position: -500px -120px; } -.emoji-1F435 { background-position: -500px -140px; } -.emoji-1F436 { background-position: -500px -160px; } -.emoji-1F437 { background-position: -500px -180px; } -.emoji-1F438 { background-position: -500px -200px; } -.emoji-1F439 { background-position: -500px -220px; } -.emoji-1F43A { background-position: -500px -240px; } -.emoji-1F43B { background-position: -500px -260px; } -.emoji-1F43C { background-position: -500px -280px; } -.emoji-1F43D { background-position: -500px -300px; } -.emoji-1F43E { background-position: -500px -320px; } -.emoji-1F43F { background-position: -500px -340px; } -.emoji-1F440 { background-position: -500px -360px; } -.emoji-1F441 { background-position: -500px -380px; } -.emoji-1F441-1F5E8 { background-position: -500px -400px; } -.emoji-1F442 { background-position: -500px -420px; } -.emoji-1F442-1F3FB { background-position: -500px -440px; } -.emoji-1F442-1F3FC { background-position: -500px -460px; } -.emoji-1F442-1F3FD { background-position: -500px -480px; } -.emoji-1F442-1F3FE { background-position: 0 -500px; } -.emoji-1F442-1F3FF { background-position: -20px -500px; } -.emoji-1F443 { background-position: -40px -500px; } -.emoji-1F443-1F3FB { background-position: -60px -500px; } -.emoji-1F443-1F3FC { background-position: -80px -500px; } -.emoji-1F443-1F3FD { background-position: -100px -500px; } -.emoji-1F443-1F3FE { background-position: -120px -500px; } -.emoji-1F443-1F3FF { background-position: -140px -500px; } -.emoji-1F444 { background-position: -160px -500px; } -.emoji-1F445 { background-position: -180px -500px; } -.emoji-1F446 { background-position: -200px -500px; } -.emoji-1F446-1F3FB { background-position: -220px -500px; } -.emoji-1F446-1F3FC { background-position: -240px -500px; } -.emoji-1F446-1F3FD { background-position: -260px -500px; } -.emoji-1F446-1F3FE { background-position: -280px -500px; } -.emoji-1F446-1F3FF { background-position: -300px -500px; } -.emoji-1F447 { background-position: -320px -500px; } -.emoji-1F447-1F3FB { background-position: -340px -500px; } -.emoji-1F447-1F3FC { background-position: -360px -500px; } -.emoji-1F447-1F3FD { background-position: -380px -500px; } -.emoji-1F447-1F3FE { background-position: -400px -500px; } -.emoji-1F447-1F3FF { background-position: -420px -500px; } -.emoji-1F448 { background-position: -440px -500px; } -.emoji-1F448-1F3FB { background-position: -460px -500px; } -.emoji-1F448-1F3FC { background-position: -480px -500px; } -.emoji-1F448-1F3FD { background-position: -500px -500px; } -.emoji-1F448-1F3FE { background-position: -520px 0; } -.emoji-1F448-1F3FF { background-position: -520px -20px; } -.emoji-1F449 { background-position: -520px -40px; } -.emoji-1F449-1F3FB { background-position: -520px -60px; } -.emoji-1F449-1F3FC { background-position: -520px -80px; } -.emoji-1F449-1F3FD { background-position: -520px -100px; } -.emoji-1F449-1F3FE { background-position: -520px -120px; } -.emoji-1F449-1F3FF { background-position: -520px -140px; } -.emoji-1F44A { background-position: -520px -160px; } -.emoji-1F44A-1F3FB { background-position: -520px -180px; } -.emoji-1F44A-1F3FC { background-position: -520px -200px; } -.emoji-1F44A-1F3FD { background-position: -520px -220px; } -.emoji-1F44A-1F3FE { background-position: -520px -240px; } -.emoji-1F44A-1F3FF { background-position: -520px -260px; } -.emoji-1F44B { background-position: -520px -280px; } -.emoji-1F44B-1F3FB { background-position: -520px -300px; } -.emoji-1F44B-1F3FC { background-position: -520px -320px; } -.emoji-1F44B-1F3FD { background-position: -520px -340px; } -.emoji-1F44B-1F3FE { background-position: -520px -360px; } -.emoji-1F44B-1F3FF { background-position: -520px -380px; } -.emoji-1F44C { background-position: -520px -400px; } -.emoji-1F44C-1F3FB { background-position: -520px -420px; } -.emoji-1F44C-1F3FC { background-position: -520px -440px; } -.emoji-1F44C-1F3FD { background-position: -520px -460px; } -.emoji-1F44C-1F3FE { background-position: -520px -480px; } -.emoji-1F44C-1F3FF { background-position: -520px -500px; } -.emoji-1F44D { background-position: 0 -520px; } -.emoji-1F44D-1F3FB { background-position: -20px -520px; } -.emoji-1F44D-1F3FC { background-position: -40px -520px; } -.emoji-1F44D-1F3FD { background-position: -60px -520px; } -.emoji-1F44D-1F3FE { background-position: -80px -520px; } -.emoji-1F44D-1F3FF { background-position: -100px -520px; } -.emoji-1F44E { background-position: -120px -520px; } -.emoji-1F44E-1F3FB { background-position: -140px -520px; } -.emoji-1F44E-1F3FC { background-position: -160px -520px; } -.emoji-1F44E-1F3FD { background-position: -180px -520px; } -.emoji-1F44E-1F3FE { background-position: -200px -520px; } -.emoji-1F44E-1F3FF { background-position: -220px -520px; } -.emoji-1F44F { background-position: -240px -520px; } -.emoji-1F44F-1F3FB { background-position: -260px -520px; } -.emoji-1F44F-1F3FC { background-position: -280px -520px; } -.emoji-1F44F-1F3FD { background-position: -300px -520px; } -.emoji-1F44F-1F3FE { background-position: -320px -520px; } -.emoji-1F44F-1F3FF { background-position: -340px -520px; } -.emoji-1F450 { background-position: -360px -520px; } -.emoji-1F450-1F3FB { background-position: -380px -520px; } -.emoji-1F450-1F3FC { background-position: -400px -520px; } -.emoji-1F450-1F3FD { background-position: -420px -520px; } -.emoji-1F450-1F3FE { background-position: -440px -520px; } -.emoji-1F450-1F3FF { background-position: -460px -520px; } -.emoji-1F451 { background-position: -480px -520px; } -.emoji-1F452 { background-position: -500px -520px; } -.emoji-1F453 { background-position: -520px -520px; } -.emoji-1F454 { background-position: -540px 0; } -.emoji-1F455 { background-position: -540px -20px; } -.emoji-1F456 { background-position: -540px -40px; } -.emoji-1F457 { background-position: -540px -60px; } -.emoji-1F458 { background-position: -540px -80px; } -.emoji-1F459 { background-position: -540px -100px; } -.emoji-1F45A { background-position: -540px -120px; } -.emoji-1F45B { background-position: -540px -140px; } -.emoji-1F45C { background-position: -540px -160px; } -.emoji-1F45D { background-position: -540px -180px; } -.emoji-1F45E { background-position: -540px -200px; } -.emoji-1F45F { background-position: -540px -220px; } -.emoji-1F460 { background-position: -540px -240px; } -.emoji-1F461 { background-position: -540px -260px; } -.emoji-1F462 { background-position: -540px -280px; } -.emoji-1F463 { background-position: -540px -300px; } -.emoji-1F464 { background-position: -540px -320px; } -.emoji-1F465 { background-position: -540px -340px; } -.emoji-1F466 { background-position: -540px -360px; } -.emoji-1F466-1F3FB { background-position: -540px -380px; } -.emoji-1F466-1F3FC { background-position: -540px -400px; } -.emoji-1F466-1F3FD { background-position: -540px -420px; } -.emoji-1F466-1F3FE { background-position: -540px -440px; } -.emoji-1F466-1F3FF { background-position: -540px -460px; } -.emoji-1F467 { background-position: -540px -480px; } -.emoji-1F467-1F3FB { background-position: -540px -500px; } -.emoji-1F467-1F3FC { background-position: -540px -520px; } -.emoji-1F467-1F3FD { background-position: 0 -540px; } -.emoji-1F467-1F3FE { background-position: -20px -540px; } -.emoji-1F467-1F3FF { background-position: -40px -540px; } -.emoji-1F468 { background-position: -60px -540px; } -.emoji-1F468-1F3FB { background-position: -80px -540px; } -.emoji-1F468-1F3FC { background-position: -100px -540px; } -.emoji-1F468-1F3FD { background-position: -120px -540px; } -.emoji-1F468-1F3FE { background-position: -140px -540px; } -.emoji-1F468-1F3FF { background-position: -160px -540px; } -.emoji-1F468-1F468-1F466 { background-position: -180px -540px; } -.emoji-1F468-1F468-1F466-1F466 { background-position: -200px -540px; } -.emoji-1F468-1F468-1F467 { background-position: -220px -540px; } -.emoji-1F468-1F468-1F467-1F466 { background-position: -240px -540px; } -.emoji-1F468-1F468-1F467-1F467 { background-position: -260px -540px; } -.emoji-1F468-1F469-1F466-1F466 { background-position: -280px -540px; } -.emoji-1F468-1F469-1F467 { background-position: -300px -540px; } -.emoji-1F468-1F469-1F467-1F466 { background-position: -320px -540px; } -.emoji-1F468-1F469-1F467-1F467 { background-position: -340px -540px; } -.emoji-1F468-2764-1F468 { background-position: -360px -540px; } -.emoji-1F468-2764-1F48B-1F468 { background-position: -380px -540px; } -.emoji-1F469 { background-position: -400px -540px; } -.emoji-1F469-1F3FB { background-position: -420px -540px; } -.emoji-1F469-1F3FC { background-position: -440px -540px; } -.emoji-1F469-1F3FD { background-position: -460px -540px; } -.emoji-1F469-1F3FE { background-position: -480px -540px; } -.emoji-1F469-1F3FF { background-position: -500px -540px; } -.emoji-1F469-1F469-1F466 { background-position: -520px -540px; } -.emoji-1F469-1F469-1F466-1F466 { background-position: -540px -540px; } -.emoji-1F469-1F469-1F467 { background-position: -560px 0; } -.emoji-1F469-1F469-1F467-1F466 { background-position: -560px -20px; } -.emoji-1F469-1F469-1F467-1F467 { background-position: -560px -40px; } -.emoji-1F469-2764-1F469 { background-position: -560px -60px; } -.emoji-1F469-2764-1F48B-1F469 { background-position: -560px -80px; } -.emoji-1F46A { background-position: -560px -100px; } -.emoji-1F46B { background-position: -560px -120px; } -.emoji-1F46C { background-position: -560px -140px; } -.emoji-1F46D { background-position: -560px -160px; } -.emoji-1F46E { background-position: -560px -180px; } -.emoji-1F46E-1F3FB { background-position: -560px -200px; } -.emoji-1F46E-1F3FC { background-position: -560px -220px; } -.emoji-1F46E-1F3FD { background-position: -560px -240px; } -.emoji-1F46E-1F3FE { background-position: -560px -260px; } -.emoji-1F46E-1F3FF { background-position: -560px -280px; } -.emoji-1F46F { background-position: -560px -300px; } -.emoji-1F470 { background-position: -560px -320px; } -.emoji-1F470-1F3FB { background-position: -560px -340px; } -.emoji-1F470-1F3FC { background-position: -560px -360px; } -.emoji-1F470-1F3FD { background-position: -560px -380px; } -.emoji-1F470-1F3FE { background-position: -560px -400px; } -.emoji-1F470-1F3FF { background-position: -560px -420px; } -.emoji-1F471 { background-position: -560px -440px; } -.emoji-1F471-1F3FB { background-position: -560px -460px; } -.emoji-1F471-1F3FC { background-position: -560px -480px; } -.emoji-1F471-1F3FD { background-position: -560px -500px; } -.emoji-1F471-1F3FE { background-position: -560px -520px; } -.emoji-1F471-1F3FF { background-position: -560px -540px; } -.emoji-1F472 { background-position: 0 -560px; } -.emoji-1F472-1F3FB { background-position: -20px -560px; } -.emoji-1F472-1F3FC { background-position: -40px -560px; } -.emoji-1F472-1F3FD { background-position: -60px -560px; } -.emoji-1F472-1F3FE { background-position: -80px -560px; } -.emoji-1F472-1F3FF { background-position: -100px -560px; } -.emoji-1F473 { background-position: -120px -560px; } -.emoji-1F473-1F3FB { background-position: -140px -560px; } -.emoji-1F473-1F3FC { background-position: -160px -560px; } -.emoji-1F473-1F3FD { background-position: -180px -560px; } -.emoji-1F473-1F3FE { background-position: -200px -560px; } -.emoji-1F473-1F3FF { background-position: -220px -560px; } -.emoji-1F474 { background-position: -240px -560px; } -.emoji-1F474-1F3FB { background-position: -260px -560px; } -.emoji-1F474-1F3FC { background-position: -280px -560px; } -.emoji-1F474-1F3FD { background-position: -300px -560px; } -.emoji-1F474-1F3FE { background-position: -320px -560px; } -.emoji-1F474-1F3FF { background-position: -340px -560px; } -.emoji-1F475 { background-position: -360px -560px; } -.emoji-1F475-1F3FB { background-position: -380px -560px; } -.emoji-1F475-1F3FC { background-position: -400px -560px; } -.emoji-1F475-1F3FD { background-position: -420px -560px; } -.emoji-1F475-1F3FE { background-position: -440px -560px; } -.emoji-1F475-1F3FF { background-position: -460px -560px; } -.emoji-1F476 { background-position: -480px -560px; } -.emoji-1F476-1F3FB { background-position: -500px -560px; } -.emoji-1F476-1F3FC { background-position: -520px -560px; } -.emoji-1F476-1F3FD { background-position: -540px -560px; } -.emoji-1F476-1F3FE { background-position: -560px -560px; } -.emoji-1F476-1F3FF { background-position: -580px 0; } -.emoji-1F477 { background-position: -580px -20px; } -.emoji-1F477-1F3FB { background-position: -580px -40px; } -.emoji-1F477-1F3FC { background-position: -580px -60px; } -.emoji-1F477-1F3FD { background-position: -580px -80px; } -.emoji-1F477-1F3FE { background-position: -580px -100px; } -.emoji-1F477-1F3FF { background-position: -580px -120px; } -.emoji-1F478 { background-position: -580px -140px; } -.emoji-1F478-1F3FB { background-position: -580px -160px; } -.emoji-1F478-1F3FC { background-position: -580px -180px; } -.emoji-1F478-1F3FD { background-position: -580px -200px; } -.emoji-1F478-1F3FE { background-position: -580px -220px; } -.emoji-1F478-1F3FF { background-position: -580px -240px; } -.emoji-1F479 { background-position: -580px -260px; } -.emoji-1F47A { background-position: -580px -280px; } -.emoji-1F47B { background-position: -580px -300px; } -.emoji-1F47C { background-position: -580px -320px; } -.emoji-1F47C-1F3FB { background-position: -580px -340px; } -.emoji-1F47C-1F3FC { background-position: -580px -360px; } -.emoji-1F47C-1F3FD { background-position: -580px -380px; } -.emoji-1F47C-1F3FE { background-position: -580px -400px; } -.emoji-1F47C-1F3FF { background-position: -580px -420px; } -.emoji-1F47D { background-position: -580px -440px; } -.emoji-1F47E { background-position: -580px -460px; } -.emoji-1F47F { background-position: -580px -480px; } -.emoji-1F480 { background-position: -580px -500px; } -.emoji-1F481 { background-position: -580px -520px; } -.emoji-1F481-1F3FB { background-position: -580px -540px; } -.emoji-1F481-1F3FC { background-position: -580px -560px; } -.emoji-1F481-1F3FD { background-position: 0 -580px; } -.emoji-1F481-1F3FE { background-position: -20px -580px; } -.emoji-1F481-1F3FF { background-position: -40px -580px; } -.emoji-1F482 { background-position: -60px -580px; } -.emoji-1F482-1F3FB { background-position: -80px -580px; } -.emoji-1F482-1F3FC { background-position: -100px -580px; } -.emoji-1F482-1F3FD { background-position: -120px -580px; } -.emoji-1F482-1F3FE { background-position: -140px -580px; } -.emoji-1F482-1F3FF { background-position: -160px -580px; } -.emoji-1F483 { background-position: -180px -580px; } -.emoji-1F483-1F3FB { background-position: -200px -580px; } -.emoji-1F483-1F3FC { background-position: -220px -580px; } -.emoji-1F483-1F3FD { background-position: -240px -580px; } -.emoji-1F483-1F3FE { background-position: -260px -580px; } -.emoji-1F483-1F3FF { background-position: -280px -580px; } -.emoji-1F484 { background-position: -300px -580px; } -.emoji-1F485 { background-position: -320px -580px; } -.emoji-1F485-1F3FB { background-position: -340px -580px; } -.emoji-1F485-1F3FC { background-position: -360px -580px; } -.emoji-1F485-1F3FD { background-position: -380px -580px; } -.emoji-1F485-1F3FE { background-position: -400px -580px; } -.emoji-1F485-1F3FF { background-position: -420px -580px; } -.emoji-1F486 { background-position: -440px -580px; } -.emoji-1F486-1F3FB { background-position: -460px -580px; } -.emoji-1F486-1F3FC { background-position: -480px -580px; } -.emoji-1F486-1F3FD { background-position: -500px -580px; } -.emoji-1F486-1F3FE { background-position: -520px -580px; } -.emoji-1F486-1F3FF { background-position: -540px -580px; } -.emoji-1F487 { background-position: -560px -580px; } -.emoji-1F487-1F3FB { background-position: -580px -580px; } -.emoji-1F487-1F3FC { background-position: -600px 0; } -.emoji-1F487-1F3FD { background-position: -600px -20px; } -.emoji-1F487-1F3FE { background-position: -600px -40px; } -.emoji-1F487-1F3FF { background-position: -600px -60px; } -.emoji-1F488 { background-position: -600px -80px; } -.emoji-1F489 { background-position: -600px -100px; } -.emoji-1F48A { background-position: -600px -120px; } -.emoji-1F48B { background-position: -600px -140px; } -.emoji-1F48C { background-position: -600px -160px; } -.emoji-1F48D { background-position: -600px -180px; } -.emoji-1F48E { background-position: -600px -200px; } -.emoji-1F48F { background-position: -600px -220px; } -.emoji-1F490 { background-position: -600px -240px; } -.emoji-1F491 { background-position: -600px -260px; } -.emoji-1F492 { background-position: -600px -280px; } -.emoji-1F493 { background-position: -600px -300px; } -.emoji-1F494 { background-position: -600px -320px; } -.emoji-1F495 { background-position: -600px -340px; } -.emoji-1F496 { background-position: -600px -360px; } -.emoji-1F497 { background-position: -600px -380px; } -.emoji-1F498 { background-position: -600px -400px; } -.emoji-1F499 { background-position: -600px -420px; } -.emoji-1F49A { background-position: -600px -440px; } -.emoji-1F49B { background-position: -600px -460px; } -.emoji-1F49C { background-position: -600px -480px; } -.emoji-1F49D { background-position: -600px -500px; } -.emoji-1F49E { background-position: -600px -520px; } -.emoji-1F49F { background-position: -600px -540px; } -.emoji-1F4A0 { background-position: -600px -560px; } -.emoji-1F4A1 { background-position: -600px -580px; } -.emoji-1F4A2 { background-position: 0 -600px; } -.emoji-1F4A3 { background-position: -20px -600px; } -.emoji-1F4A4 { background-position: -40px -600px; } -.emoji-1F4A5 { background-position: -60px -600px; } -.emoji-1F4A6 { background-position: -80px -600px; } -.emoji-1F4A7 { background-position: -100px -600px; } -.emoji-1F4A8 { background-position: -120px -600px; } -.emoji-1F4A9 { background-position: -140px -600px; } -.emoji-1F4AA { background-position: -160px -600px; } -.emoji-1F4AA-1F3FB { background-position: -180px -600px; } -.emoji-1F4AA-1F3FC { background-position: -200px -600px; } -.emoji-1F4AA-1F3FD { background-position: -220px -600px; } -.emoji-1F4AA-1F3FE { background-position: -240px -600px; } -.emoji-1F4AA-1F3FF { background-position: -260px -600px; } -.emoji-1F4AB { background-position: -280px -600px; } -.emoji-1F4AC { background-position: -300px -600px; } -.emoji-1F4AD { background-position: -320px -600px; } -.emoji-1F4AE { background-position: -340px -600px; } -.emoji-1F4AF { background-position: -360px -600px; } -.emoji-1F4B0 { background-position: -380px -600px; } -.emoji-1F4B1 { background-position: -400px -600px; } -.emoji-1F4B2 { background-position: -420px -600px; } -.emoji-1F4B3 { background-position: -440px -600px; } -.emoji-1F4B4 { background-position: -460px -600px; } -.emoji-1F4B5 { background-position: -480px -600px; } -.emoji-1F4B6 { background-position: -500px -600px; } -.emoji-1F4B7 { background-position: -520px -600px; } -.emoji-1F4B8 { background-position: -540px -600px; } -.emoji-1F4B9 { background-position: -560px -600px; } -.emoji-1F4BA { background-position: -580px -600px; } -.emoji-1F4BB { background-position: -600px -600px; } -.emoji-1F4BC { background-position: -620px 0; } -.emoji-1F4BD { background-position: -620px -20px; } -.emoji-1F4BE { background-position: -620px -40px; } -.emoji-1F4BF { background-position: -620px -60px; } -.emoji-1F4C0 { background-position: -620px -80px; } -.emoji-1F4C1 { background-position: -620px -100px; } -.emoji-1F4C2 { background-position: -620px -120px; } -.emoji-1F4C3 { background-position: -620px -140px; } -.emoji-1F4C4 { background-position: -620px -160px; } -.emoji-1F4C5 { background-position: -620px -180px; } -.emoji-1F4C6 { background-position: -620px -200px; } -.emoji-1F4C7 { background-position: -620px -220px; } -.emoji-1F4C8 { background-position: -620px -240px; } -.emoji-1F4C9 { background-position: -620px -260px; } -.emoji-1F4CA { background-position: -620px -280px; } -.emoji-1F4CB { background-position: -620px -300px; } -.emoji-1F4CC { background-position: -620px -320px; } -.emoji-1F4CD { background-position: -620px -340px; } -.emoji-1F4CE { background-position: -620px -360px; } -.emoji-1F4CF { background-position: -620px -380px; } -.emoji-1F4D0 { background-position: -620px -400px; } -.emoji-1F4D1 { background-position: -620px -420px; } -.emoji-1F4D2 { background-position: -620px -440px; } -.emoji-1F4D3 { background-position: -620px -460px; } -.emoji-1F4D4 { background-position: -620px -480px; } -.emoji-1F4D5 { background-position: -620px -500px; } -.emoji-1F4D6 { background-position: -620px -520px; } -.emoji-1F4D7 { background-position: -620px -540px; } -.emoji-1F4D8 { background-position: -620px -560px; } -.emoji-1F4D9 { background-position: -620px -580px; } -.emoji-1F4DA { background-position: -620px -600px; } -.emoji-1F4DB { background-position: 0 -620px; } -.emoji-1F4DC { background-position: -20px -620px; } -.emoji-1F4DD { background-position: -40px -620px; } -.emoji-1F4DE { background-position: -60px -620px; } -.emoji-1F4DF { background-position: -80px -620px; } -.emoji-1F4E0 { background-position: -100px -620px; } -.emoji-1F4E1 { background-position: -120px -620px; } -.emoji-1F4E2 { background-position: -140px -620px; } -.emoji-1F4E3 { background-position: -160px -620px; } -.emoji-1F4E4 { background-position: -180px -620px; } -.emoji-1F4E5 { background-position: -200px -620px; } -.emoji-1F4E6 { background-position: -220px -620px; } -.emoji-1F4E7 { background-position: -240px -620px; } -.emoji-1F4E8 { background-position: -260px -620px; } -.emoji-1F4E9 { background-position: -280px -620px; } -.emoji-1F4EA { background-position: -300px -620px; } -.emoji-1F4EB { background-position: -320px -620px; } -.emoji-1F4EC { background-position: -340px -620px; } -.emoji-1F4ED { background-position: -360px -620px; } -.emoji-1F4EE { background-position: -380px -620px; } -.emoji-1F4EF { background-position: -400px -620px; } -.emoji-1F4F0 { background-position: -420px -620px; } -.emoji-1F4F1 { background-position: -440px -620px; } -.emoji-1F4F2 { background-position: -460px -620px; } -.emoji-1F4F3 { background-position: -480px -620px; } -.emoji-1F4F4 { background-position: -500px -620px; } -.emoji-1F4F5 { background-position: -520px -620px; } -.emoji-1F4F6 { background-position: -540px -620px; } -.emoji-1F4F7 { background-position: -560px -620px; } -.emoji-1F4F8 { background-position: -580px -620px; } -.emoji-1F4F9 { background-position: -600px -620px; } -.emoji-1F4FA { background-position: -620px -620px; } -.emoji-1F4FB { background-position: -640px 0; } -.emoji-1F4FC { background-position: -640px -20px; } -.emoji-1F4FD { background-position: -640px -40px; } -.emoji-1F4FF { background-position: -640px -60px; } -.emoji-1F500 { background-position: -640px -80px; } -.emoji-1F501 { background-position: -640px -100px; } -.emoji-1F502 { background-position: -640px -120px; } -.emoji-1F503 { background-position: -640px -140px; } -.emoji-1F504 { background-position: -640px -160px; } -.emoji-1F505 { background-position: -640px -180px; } -.emoji-1F506 { background-position: -640px -200px; } -.emoji-1F507 { background-position: -640px -220px; } -.emoji-1F508 { background-position: -640px -240px; } -.emoji-1F509 { background-position: -640px -260px; } -.emoji-1F50A { background-position: -640px -280px; } -.emoji-1F50B { background-position: -640px -300px; } -.emoji-1F50C { background-position: -640px -320px; } -.emoji-1F50D { background-position: -640px -340px; } -.emoji-1F50E { background-position: -640px -360px; } -.emoji-1F50F { background-position: -640px -380px; } -.emoji-1F510 { background-position: -640px -400px; } -.emoji-1F511 { background-position: -640px -420px; } -.emoji-1F512 { background-position: -640px -440px; } -.emoji-1F513 { background-position: -640px -460px; } -.emoji-1F514 { background-position: -640px -480px; } -.emoji-1F515 { background-position: -640px -500px; } -.emoji-1F516 { background-position: -640px -520px; } -.emoji-1F517 { background-position: -640px -540px; } -.emoji-1F518 { background-position: -640px -560px; } -.emoji-1F519 { background-position: -640px -580px; } -.emoji-1F51A { background-position: -640px -600px; } -.emoji-1F51B { background-position: -640px -620px; } -.emoji-1F51C { background-position: 0 -640px; } -.emoji-1F51D { background-position: -20px -640px; } -.emoji-1F51E { background-position: -40px -640px; } -.emoji-1F51F { background-position: -60px -640px; } -.emoji-1F520 { background-position: -80px -640px; } -.emoji-1F521 { background-position: -100px -640px; } -.emoji-1F522 { background-position: -120px -640px; } -.emoji-1F523 { background-position: -140px -640px; } -.emoji-1F524 { background-position: -160px -640px; } -.emoji-1F525 { background-position: -180px -640px; } -.emoji-1F526 { background-position: -200px -640px; } -.emoji-1F527 { background-position: -220px -640px; } -.emoji-1F528 { background-position: -240px -640px; } -.emoji-1F529 { background-position: -260px -640px; } -.emoji-1F52A { background-position: -280px -640px; } -.emoji-1F52B { background-position: -300px -640px; } -.emoji-1F52C { background-position: -320px -640px; } -.emoji-1F52D { background-position: -340px -640px; } -.emoji-1F52E { background-position: -360px -640px; } -.emoji-1F52F { background-position: -380px -640px; } -.emoji-1F530 { background-position: -400px -640px; } -.emoji-1F531 { background-position: -420px -640px; } -.emoji-1F532 { background-position: -440px -640px; } -.emoji-1F533 { background-position: -460px -640px; } -.emoji-1F534 { background-position: -480px -640px; } -.emoji-1F535 { background-position: -500px -640px; } -.emoji-1F536 { background-position: -520px -640px; } -.emoji-1F537 { background-position: -540px -640px; } -.emoji-1F538 { background-position: -560px -640px; } -.emoji-1F539 { background-position: -580px -640px; } -.emoji-1F53A { background-position: -600px -640px; } -.emoji-1F53B { background-position: -620px -640px; } -.emoji-1F53C { background-position: -640px -640px; } -.emoji-1F53D { background-position: -660px 0; } -.emoji-1F549 { background-position: -660px -20px; } -.emoji-1F54A { background-position: -660px -40px; } -.emoji-1F54B { background-position: -660px -60px; } -.emoji-1F54C { background-position: -660px -80px; } -.emoji-1F54D { background-position: -660px -100px; } -.emoji-1F54E { background-position: -660px -120px; } -.emoji-1F550 { background-position: -660px -140px; } -.emoji-1F551 { background-position: -660px -160px; } -.emoji-1F552 { background-position: -660px -180px; } -.emoji-1F553 { background-position: -660px -200px; } -.emoji-1F554 { background-position: -660px -220px; } -.emoji-1F555 { background-position: -660px -240px; } -.emoji-1F556 { background-position: -660px -260px; } -.emoji-1F557 { background-position: -660px -280px; } -.emoji-1F558 { background-position: -660px -300px; } -.emoji-1F559 { background-position: -660px -320px; } -.emoji-1F55A { background-position: -660px -340px; } -.emoji-1F55B { background-position: -660px -360px; } -.emoji-1F55C { background-position: -660px -380px; } -.emoji-1F55D { background-position: -660px -400px; } -.emoji-1F55E { background-position: -660px -420px; } -.emoji-1F55F { background-position: -660px -440px; } -.emoji-1F560 { background-position: -660px -460px; } -.emoji-1F561 { background-position: -660px -480px; } -.emoji-1F562 { background-position: -660px -500px; } -.emoji-1F563 { background-position: -660px -520px; } -.emoji-1F564 { background-position: -660px -540px; } -.emoji-1F565 { background-position: -660px -560px; } -.emoji-1F566 { background-position: -660px -580px; } -.emoji-1F567 { background-position: -660px -600px; } -.emoji-1F56F { background-position: -660px -620px; } -.emoji-1F570 { background-position: -660px -640px; } -.emoji-1F573 { background-position: 0 -660px; } -.emoji-1F574 { background-position: -20px -660px; } -.emoji-1F575 { background-position: -40px -660px; } -.emoji-1F575-1F3FB { background-position: -60px -660px; } -.emoji-1F575-1F3FC { background-position: -80px -660px; } -.emoji-1F575-1F3FD { background-position: -100px -660px; } -.emoji-1F575-1F3FE { background-position: -120px -660px; } -.emoji-1F575-1F3FF { background-position: -140px -660px; } -.emoji-1F576 { background-position: -160px -660px; } -.emoji-1F577 { background-position: -180px -660px; } -.emoji-1F578 { background-position: -200px -660px; } -.emoji-1F579 { background-position: -220px -660px; } -.emoji-1F57A { background-position: -240px -660px; } -.emoji-1F57A-1F3FB { background-position: -260px -660px; } -.emoji-1F57A-1F3FC { background-position: -280px -660px; } -.emoji-1F57A-1F3FD { background-position: -300px -660px; } -.emoji-1F57A-1F3FE { background-position: -320px -660px; } -.emoji-1F57A-1F3FF { background-position: -340px -660px; } -.emoji-1F587 { background-position: -360px -660px; } -.emoji-1F58A { background-position: -380px -660px; } -.emoji-1F58B { background-position: -400px -660px; } -.emoji-1F58C { background-position: -420px -660px; } -.emoji-1F58D { background-position: -440px -660px; } -.emoji-1F590 { background-position: -460px -660px; } -.emoji-1F590-1F3FB { background-position: -480px -660px; } -.emoji-1F590-1F3FC { background-position: -500px -660px; } -.emoji-1F590-1F3FD { background-position: -520px -660px; } -.emoji-1F590-1F3FE { background-position: -540px -660px; } -.emoji-1F590-1F3FF { background-position: -560px -660px; } -.emoji-1F595 { background-position: -580px -660px; } -.emoji-1F595-1F3FB { background-position: -600px -660px; } -.emoji-1F595-1F3FC { background-position: -620px -660px; } -.emoji-1F595-1F3FD { background-position: -640px -660px; } -.emoji-1F595-1F3FE { background-position: -660px -660px; } -.emoji-1F595-1F3FF { background-position: -680px 0; } -.emoji-1F596 { background-position: -680px -20px; } -.emoji-1F596-1F3FB { background-position: -680px -40px; } -.emoji-1F596-1F3FC { background-position: -680px -60px; } -.emoji-1F596-1F3FD { background-position: -680px -80px; } -.emoji-1F596-1F3FE { background-position: -680px -100px; } -.emoji-1F596-1F3FF { background-position: -680px -120px; } -.emoji-1F5A4 { background-position: -680px -140px; } -.emoji-1F5A5 { background-position: -680px -160px; } -.emoji-1F5A8 { background-position: -680px -180px; } -.emoji-1F5B1 { background-position: -680px -200px; } -.emoji-1F5B2 { background-position: -680px -220px; } -.emoji-1F5BC { background-position: -680px -240px; } -.emoji-1F5C2 { background-position: -680px -260px; } -.emoji-1F5C3 { background-position: -680px -280px; } -.emoji-1F5C4 { background-position: -680px -300px; } -.emoji-1F5D1 { background-position: -680px -320px; } -.emoji-1F5D2 { background-position: -680px -340px; } -.emoji-1F5D3 { background-position: -680px -360px; } -.emoji-1F5DC { background-position: -680px -380px; } -.emoji-1F5DD { background-position: -680px -400px; } -.emoji-1F5DE { background-position: -680px -420px; } -.emoji-1F5E1 { background-position: -680px -440px; } -.emoji-1F5E3 { background-position: -680px -460px; } -.emoji-1F5EF { background-position: -680px -480px; } -.emoji-1F5F3 { background-position: -680px -500px; } -.emoji-1F5FA { background-position: -680px -520px; } -.emoji-1F5FB { background-position: -680px -540px; } -.emoji-1F5FC { background-position: -680px -560px; } -.emoji-1F5FD { background-position: -680px -580px; } -.emoji-1F5FE { background-position: -680px -600px; } -.emoji-1F5FF { background-position: -680px -620px; } -.emoji-1F600 { background-position: -680px -640px; } -.emoji-1F601 { background-position: -680px -660px; } -.emoji-1F602 { background-position: 0 -680px; } -.emoji-1F603 { background-position: -20px -680px; } -.emoji-1F604 { background-position: -40px -680px; } -.emoji-1F605 { background-position: -60px -680px; } -.emoji-1F606 { background-position: -80px -680px; } -.emoji-1F607 { background-position: -100px -680px; } -.emoji-1F608 { background-position: -120px -680px; } -.emoji-1F609 { background-position: -140px -680px; } -.emoji-1F60A { background-position: -160px -680px; } -.emoji-1F60B { background-position: -180px -680px; } -.emoji-1F60C { background-position: -200px -680px; } -.emoji-1F60D { background-position: -220px -680px; } -.emoji-1F60E { background-position: -240px -680px; } -.emoji-1F60F { background-position: -260px -680px; } -.emoji-1F610 { background-position: -280px -680px; } -.emoji-1F611 { background-position: -300px -680px; } -.emoji-1F612 { background-position: -320px -680px; } -.emoji-1F613 { background-position: -340px -680px; } -.emoji-1F614 { background-position: -360px -680px; } -.emoji-1F615 { background-position: -380px -680px; } -.emoji-1F616 { background-position: -400px -680px; } -.emoji-1F617 { background-position: -420px -680px; } -.emoji-1F618 { background-position: -440px -680px; } -.emoji-1F619 { background-position: -460px -680px; } -.emoji-1F61A { background-position: -480px -680px; } -.emoji-1F61B { background-position: -500px -680px; } -.emoji-1F61C { background-position: -520px -680px; } -.emoji-1F61D { background-position: -540px -680px; } -.emoji-1F61E { background-position: -560px -680px; } -.emoji-1F61F { background-position: -580px -680px; } -.emoji-1F620 { background-position: -600px -680px; } -.emoji-1F621 { background-position: -620px -680px; } -.emoji-1F622 { background-position: -640px -680px; } -.emoji-1F623 { background-position: -660px -680px; } -.emoji-1F624 { background-position: -680px -680px; } -.emoji-1F625 { background-position: -700px 0; } -.emoji-1F626 { background-position: -700px -20px; } -.emoji-1F627 { background-position: -700px -40px; } -.emoji-1F628 { background-position: -700px -60px; } -.emoji-1F629 { background-position: -700px -80px; } -.emoji-1F62A { background-position: -700px -100px; } -.emoji-1F62B { background-position: -700px -120px; } -.emoji-1F62C { background-position: -700px -140px; } -.emoji-1F62D { background-position: -700px -160px; } -.emoji-1F62E { background-position: -700px -180px; } -.emoji-1F62F { background-position: -700px -200px; } -.emoji-1F630 { background-position: -700px -220px; } -.emoji-1F631 { background-position: -700px -240px; } -.emoji-1F632 { background-position: -700px -260px; } -.emoji-1F633 { background-position: -700px -280px; } -.emoji-1F634 { background-position: -700px -300px; } -.emoji-1F635 { background-position: -700px -320px; } -.emoji-1F636 { background-position: -700px -340px; } -.emoji-1F637 { background-position: -700px -360px; } -.emoji-1F638 { background-position: -700px -380px; } -.emoji-1F639 { background-position: -700px -400px; } -.emoji-1F63A { background-position: -700px -420px; } -.emoji-1F63B { background-position: -700px -440px; } -.emoji-1F63C { background-position: -700px -460px; } -.emoji-1F63D { background-position: -700px -480px; } -.emoji-1F63E { background-position: -700px -500px; } -.emoji-1F63F { background-position: -700px -520px; } -.emoji-1F640 { background-position: -700px -540px; } -.emoji-1F641 { background-position: -700px -560px; } -.emoji-1F642 { background-position: -700px -580px; } -.emoji-1F643 { background-position: -700px -600px; } -.emoji-1F644 { background-position: -700px -620px; } -.emoji-1F645 { background-position: -700px -640px; } -.emoji-1F645-1F3FB { background-position: -700px -660px; } -.emoji-1F645-1F3FC { background-position: -700px -680px; } -.emoji-1F645-1F3FD { background-position: 0 -700px; } -.emoji-1F645-1F3FE { background-position: -20px -700px; } -.emoji-1F645-1F3FF { background-position: -40px -700px; } -.emoji-1F646 { background-position: -60px -700px; } -.emoji-1F646-1F3FB { background-position: -80px -700px; } -.emoji-1F646-1F3FC { background-position: -100px -700px; } -.emoji-1F646-1F3FD { background-position: -120px -700px; } -.emoji-1F646-1F3FE { background-position: -140px -700px; } -.emoji-1F646-1F3FF { background-position: -160px -700px; } -.emoji-1F647 { background-position: -180px -700px; } -.emoji-1F647-1F3FB { background-position: -200px -700px; } -.emoji-1F647-1F3FC { background-position: -220px -700px; } -.emoji-1F647-1F3FD { background-position: -240px -700px; } -.emoji-1F647-1F3FE { background-position: -260px -700px; } -.emoji-1F647-1F3FF { background-position: -280px -700px; } -.emoji-1F648 { background-position: -300px -700px; } -.emoji-1F649 { background-position: -320px -700px; } -.emoji-1F64A { background-position: -340px -700px; } -.emoji-1F64B { background-position: -360px -700px; } -.emoji-1F64B-1F3FB { background-position: -380px -700px; } -.emoji-1F64B-1F3FC { background-position: -400px -700px; } -.emoji-1F64B-1F3FD { background-position: -420px -700px; } -.emoji-1F64B-1F3FE { background-position: -440px -700px; } -.emoji-1F64B-1F3FF { background-position: -460px -700px; } -.emoji-1F64C { background-position: -480px -700px; } -.emoji-1F64C-1F3FB { background-position: -500px -700px; } -.emoji-1F64C-1F3FC { background-position: -520px -700px; } -.emoji-1F64C-1F3FD { background-position: -540px -700px; } -.emoji-1F64C-1F3FE { background-position: -560px -700px; } -.emoji-1F64C-1F3FF { background-position: -580px -700px; } -.emoji-1F64D { background-position: -600px -700px; } -.emoji-1F64D-1F3FB { background-position: -620px -700px; } -.emoji-1F64D-1F3FC { background-position: -640px -700px; } -.emoji-1F64D-1F3FD { background-position: -660px -700px; } -.emoji-1F64D-1F3FE { background-position: -680px -700px; } -.emoji-1F64D-1F3FF { background-position: -700px -700px; } -.emoji-1F64E { background-position: -720px 0; } -.emoji-1F64E-1F3FB { background-position: -720px -20px; } -.emoji-1F64E-1F3FC { background-position: -720px -40px; } -.emoji-1F64E-1F3FD { background-position: -720px -60px; } -.emoji-1F64E-1F3FE { background-position: -720px -80px; } -.emoji-1F64E-1F3FF { background-position: -720px -100px; } -.emoji-1F64F { background-position: -720px -120px; } -.emoji-1F64F-1F3FB { background-position: -720px -140px; } -.emoji-1F64F-1F3FC { background-position: -720px -160px; } -.emoji-1F64F-1F3FD { background-position: -720px -180px; } -.emoji-1F64F-1F3FE { background-position: -720px -200px; } -.emoji-1F64F-1F3FF { background-position: -720px -220px; } -.emoji-1F680 { background-position: -720px -240px; } -.emoji-1F681 { background-position: -720px -260px; } -.emoji-1F682 { background-position: -720px -280px; } -.emoji-1F683 { background-position: -720px -300px; } -.emoji-1F684 { background-position: -720px -320px; } -.emoji-1F685 { background-position: -720px -340px; } -.emoji-1F686 { background-position: -720px -360px; } -.emoji-1F687 { background-position: -720px -380px; } -.emoji-1F688 { background-position: -720px -400px; } -.emoji-1F689 { background-position: -720px -420px; } -.emoji-1F68A { background-position: -720px -440px; } -.emoji-1F68B { background-position: -720px -460px; } -.emoji-1F68C { background-position: -720px -480px; } -.emoji-1F68D { background-position: -720px -500px; } -.emoji-1F68E { background-position: -720px -520px; } -.emoji-1F68F { background-position: -720px -540px; } -.emoji-1F690 { background-position: -720px -560px; } -.emoji-1F691 { background-position: -720px -580px; } -.emoji-1F692 { background-position: -720px -600px; } -.emoji-1F693 { background-position: -720px -620px; } -.emoji-1F694 { background-position: -720px -640px; } -.emoji-1F695 { background-position: -720px -660px; } -.emoji-1F696 { background-position: -720px -680px; } -.emoji-1F697 { background-position: -720px -700px; } -.emoji-1F698 { background-position: 0 -720px; } -.emoji-1F699 { background-position: -20px -720px; } -.emoji-1F69A { background-position: -40px -720px; } -.emoji-1F69B { background-position: -60px -720px; } -.emoji-1F69C { background-position: -80px -720px; } -.emoji-1F69D { background-position: -100px -720px; } -.emoji-1F69E { background-position: -120px -720px; } -.emoji-1F69F { background-position: -140px -720px; } -.emoji-1F6A0 { background-position: -160px -720px; } -.emoji-1F6A1 { background-position: -180px -720px; } -.emoji-1F6A2 { background-position: -200px -720px; } -.emoji-1F6A3 { background-position: -220px -720px; } -.emoji-1F6A3-1F3FB { background-position: -240px -720px; } -.emoji-1F6A3-1F3FC { background-position: -260px -720px; } -.emoji-1F6A3-1F3FD { background-position: -280px -720px; } -.emoji-1F6A3-1F3FE { background-position: -300px -720px; } -.emoji-1F6A3-1F3FF { background-position: -320px -720px; } -.emoji-1F6A4 { background-position: -340px -720px; } -.emoji-1F6A5 { background-position: -360px -720px; } -.emoji-1F6A6 { background-position: -380px -720px; } -.emoji-1F6A7 { background-position: -400px -720px; } -.emoji-1F6A8 { background-position: -420px -720px; } -.emoji-1F6A9 { background-position: -440px -720px; } -.emoji-1F6AA { background-position: -460px -720px; } -.emoji-1F6AB { background-position: -480px -720px; } -.emoji-1F6AC { background-position: -500px -720px; } -.emoji-1F6AD { background-position: -520px -720px; } -.emoji-1F6AE { background-position: -540px -720px; } -.emoji-1F6AF { background-position: -560px -720px; } -.emoji-1F6B0 { background-position: -580px -720px; } -.emoji-1F6B1 { background-position: -600px -720px; } -.emoji-1F6B2 { background-position: -620px -720px; } -.emoji-1F6B3 { background-position: -640px -720px; } -.emoji-1F6B4 { background-position: -660px -720px; } -.emoji-1F6B4-1F3FB { background-position: -680px -720px; } -.emoji-1F6B4-1F3FC { background-position: -700px -720px; } -.emoji-1F6B4-1F3FD { background-position: -720px -720px; } -.emoji-1F6B4-1F3FE { background-position: -740px 0; } -.emoji-1F6B4-1F3FF { background-position: -740px -20px; } -.emoji-1F6B5 { background-position: -740px -40px; } -.emoji-1F6B5-1F3FB { background-position: -740px -60px; } -.emoji-1F6B5-1F3FC { background-position: -740px -80px; } -.emoji-1F6B5-1F3FD { background-position: -740px -100px; } -.emoji-1F6B5-1F3FE { background-position: -740px -120px; } -.emoji-1F6B5-1F3FF { background-position: -740px -140px; } -.emoji-1F6B6 { background-position: -740px -160px; } -.emoji-1F6B6-1F3FB { background-position: -740px -180px; } -.emoji-1F6B6-1F3FC { background-position: -740px -200px; } -.emoji-1F6B6-1F3FD { background-position: -740px -220px; } -.emoji-1F6B6-1F3FE { background-position: -740px -240px; } -.emoji-1F6B6-1F3FF { background-position: -740px -260px; } -.emoji-1F6B7 { background-position: -740px -280px; } -.emoji-1F6B8 { background-position: -740px -300px; } -.emoji-1F6B9 { background-position: -740px -320px; } -.emoji-1F6BA { background-position: -740px -340px; } -.emoji-1F6BB { background-position: -740px -360px; } -.emoji-1F6BC { background-position: -740px -380px; } -.emoji-1F6BD { background-position: -740px -400px; } -.emoji-1F6BE { background-position: -740px -420px; } -.emoji-1F6BF { background-position: -740px -440px; } -.emoji-1F6C0 { background-position: -740px -460px; } -.emoji-1F6C0-1F3FB { background-position: -740px -480px; } -.emoji-1F6C0-1F3FC { background-position: -740px -500px; } -.emoji-1F6C0-1F3FD { background-position: -740px -520px; } -.emoji-1F6C0-1F3FE { background-position: -740px -540px; } -.emoji-1F6C0-1F3FF { background-position: -740px -560px; } -.emoji-1F6C1 { background-position: -740px -580px; } -.emoji-1F6C2 { background-position: -740px -600px; } -.emoji-1F6C3 { background-position: -740px -620px; } -.emoji-1F6C4 { background-position: -740px -640px; } -.emoji-1F6C5 { background-position: -740px -660px; } -.emoji-1F6CB { background-position: -740px -680px; } -.emoji-1F6CC { background-position: -740px -700px; } -.emoji-1F6CD { background-position: -740px -720px; } -.emoji-1F6CE { background-position: 0 -740px; } -.emoji-1F6CF { background-position: -20px -740px; } -.emoji-1F6D0 { background-position: -40px -740px; } -.emoji-1F6D1 { background-position: -60px -740px; } -.emoji-1F6D2 { background-position: -80px -740px; } -.emoji-1F6E0 { background-position: -100px -740px; } -.emoji-1F6E1 { background-position: -120px -740px; } -.emoji-1F6E2 { background-position: -140px -740px; } -.emoji-1F6E3 { background-position: -160px -740px; } -.emoji-1F6E4 { background-position: -180px -740px; } -.emoji-1F6E5 { background-position: -200px -740px; } -.emoji-1F6E9 { background-position: -220px -740px; } -.emoji-1F6EB { background-position: -240px -740px; } -.emoji-1F6EC { background-position: -260px -740px; } -.emoji-1F6F0 { background-position: -280px -740px; } -.emoji-1F6F3 { background-position: -300px -740px; } -.emoji-1F6F4 { background-position: -320px -740px; } -.emoji-1F6F5 { background-position: -340px -740px; } -.emoji-1F6F6 { background-position: -360px -740px; } -.emoji-1F910 { background-position: -380px -740px; } -.emoji-1F911 { background-position: -400px -740px; } -.emoji-1F912 { background-position: -420px -740px; } -.emoji-1F913 { background-position: -440px -740px; } -.emoji-1F914 { background-position: -460px -740px; } -.emoji-1F915 { background-position: -480px -740px; } -.emoji-1F916 { background-position: -500px -740px; } -.emoji-1F917 { background-position: -520px -740px; } -.emoji-1F918 { background-position: -540px -740px; } -.emoji-1F918-1F3FB { background-position: -560px -740px; } -.emoji-1F918-1F3FC { background-position: -580px -740px; } -.emoji-1F918-1F3FD { background-position: -600px -740px; } -.emoji-1F918-1F3FE { background-position: -620px -740px; } -.emoji-1F918-1F3FF { background-position: -640px -740px; } -.emoji-1F919 { background-position: -660px -740px; } -.emoji-1F919-1F3FB { background-position: -680px -740px; } -.emoji-1F919-1F3FC { background-position: -700px -740px; } -.emoji-1F919-1F3FD { background-position: -720px -740px; } -.emoji-1F919-1F3FE { background-position: -740px -740px; } -.emoji-1F919-1F3FF { background-position: -760px 0; } -.emoji-1F91A { background-position: -760px -20px; } -.emoji-1F91A-1F3FB { background-position: -760px -40px; } -.emoji-1F91A-1F3FC { background-position: -760px -60px; } -.emoji-1F91A-1F3FD { background-position: -760px -80px; } -.emoji-1F91A-1F3FE { background-position: -760px -100px; } -.emoji-1F91A-1F3FF { background-position: -760px -120px; } -.emoji-1F91B { background-position: -760px -140px; } -.emoji-1F91B-1F3FB { background-position: -760px -160px; } -.emoji-1F91B-1F3FC { background-position: -760px -180px; } -.emoji-1F91B-1F3FD { background-position: -760px -200px; } -.emoji-1F91B-1F3FE { background-position: -760px -220px; } -.emoji-1F91B-1F3FF { background-position: -760px -240px; } -.emoji-1F91C { background-position: -760px -260px; } -.emoji-1F91C-1F3FB { background-position: -760px -280px; } -.emoji-1F91C-1F3FC { background-position: -760px -300px; } -.emoji-1F91C-1F3FD { background-position: -760px -320px; } -.emoji-1F91C-1F3FE { background-position: -760px -340px; } -.emoji-1F91C-1F3FF { background-position: -760px -360px; } -.emoji-1F91D { background-position: -760px -380px; } -.emoji-1F91D-1F3FB { background-position: -760px -400px; } -.emoji-1F91D-1F3FC { background-position: -760px -420px; } -.emoji-1F91D-1F3FD { background-position: -760px -440px; } -.emoji-1F91D-1F3FE { background-position: -760px -460px; } -.emoji-1F91D-1F3FF { background-position: -760px -480px; } -.emoji-1F91E { background-position: -760px -500px; } -.emoji-1F91E-1F3FB { background-position: -760px -520px; } -.emoji-1F91E-1F3FC { background-position: -760px -540px; } -.emoji-1F91E-1F3FD { background-position: -760px -560px; } -.emoji-1F91E-1F3FE { background-position: -760px -580px; } -.emoji-1F91E-1F3FF { background-position: -760px -600px; } -.emoji-1F920 { background-position: -760px -620px; } -.emoji-1F921 { background-position: -760px -640px; } -.emoji-1F922 { background-position: -760px -660px; } -.emoji-1F923 { background-position: -760px -680px; } -.emoji-1F924 { background-position: -760px -700px; } -.emoji-1F925 { background-position: -760px -720px; } -.emoji-1F926 { background-position: -760px -740px; } -.emoji-1F926-1F3FB { background-position: 0 -760px; } -.emoji-1F926-1F3FC { background-position: -20px -760px; } -.emoji-1F926-1F3FD { background-position: -40px -760px; } -.emoji-1F926-1F3FE { background-position: -60px -760px; } -.emoji-1F926-1F3FF { background-position: -80px -760px; } -.emoji-1F927 { background-position: -100px -760px; } -.emoji-1F930 { background-position: -120px -760px; } -.emoji-1F930-1F3FB { background-position: -140px -760px; } -.emoji-1F930-1F3FC { background-position: -160px -760px; } -.emoji-1F930-1F3FD { background-position: -180px -760px; } -.emoji-1F930-1F3FE { background-position: -200px -760px; } -.emoji-1F930-1F3FF { background-position: -220px -760px; } -.emoji-1F933 { background-position: -240px -760px; } -.emoji-1F933-1F3FB { background-position: -260px -760px; } -.emoji-1F933-1F3FC { background-position: -280px -760px; } -.emoji-1F933-1F3FD { background-position: -300px -760px; } -.emoji-1F933-1F3FE { background-position: -320px -760px; } -.emoji-1F933-1F3FF { background-position: -340px -760px; } -.emoji-1F934 { background-position: -360px -760px; } -.emoji-1F934-1F3FB { background-position: -380px -760px; } -.emoji-1F934-1F3FC { background-position: -400px -760px; } -.emoji-1F934-1F3FD { background-position: -420px -760px; } -.emoji-1F934-1F3FE { background-position: -440px -760px; } -.emoji-1F934-1F3FF { background-position: -460px -760px; } -.emoji-1F935 { background-position: -480px -760px; } -.emoji-1F935-1F3FB { background-position: -500px -760px; } -.emoji-1F935-1F3FC { background-position: -520px -760px; } -.emoji-1F935-1F3FD { background-position: -540px -760px; } -.emoji-1F935-1F3FE { background-position: -560px -760px; } -.emoji-1F935-1F3FF { background-position: -580px -760px; } -.emoji-1F936 { background-position: -600px -760px; } -.emoji-1F936-1F3FB { background-position: -620px -760px; } -.emoji-1F936-1F3FC { background-position: -640px -760px; } -.emoji-1F936-1F3FD { background-position: -660px -760px; } -.emoji-1F936-1F3FE { background-position: -680px -760px; } -.emoji-1F936-1F3FF { background-position: -700px -760px; } -.emoji-1F937 { background-position: -720px -760px; } -.emoji-1F937-1F3FB { background-position: -740px -760px; } -.emoji-1F937-1F3FC { background-position: -760px -760px; } -.emoji-1F937-1F3FD { background-position: -780px 0; } -.emoji-1F937-1F3FE { background-position: -780px -20px; } -.emoji-1F937-1F3FF { background-position: -780px -40px; } -.emoji-1F938 { background-position: -780px -60px; } -.emoji-1F938-1F3FB { background-position: -780px -80px; } -.emoji-1F938-1F3FC { background-position: -780px -100px; } -.emoji-1F938-1F3FD { background-position: -780px -120px; } -.emoji-1F938-1F3FE { background-position: -780px -140px; } -.emoji-1F938-1F3FF { background-position: -780px -160px; } -.emoji-1F939 { background-position: -780px -180px; } -.emoji-1F939-1F3FB { background-position: -780px -200px; } -.emoji-1F939-1F3FC { background-position: -780px -220px; } -.emoji-1F939-1F3FD { background-position: -780px -240px; } -.emoji-1F939-1F3FE { background-position: -780px -260px; } -.emoji-1F939-1F3FF { background-position: -780px -280px; } -.emoji-1F93A { background-position: -780px -300px; } -.emoji-1F93C { background-position: -780px -320px; } -.emoji-1F93C-1F3FB { background-position: -780px -340px; } -.emoji-1F93C-1F3FC { background-position: -780px -360px; } -.emoji-1F93C-1F3FD { background-position: -780px -380px; } -.emoji-1F93C-1F3FE { background-position: -780px -400px; } -.emoji-1F93C-1F3FF { background-position: -780px -420px; } -.emoji-1F93D { background-position: -780px -440px; } -.emoji-1F93D-1F3FB { background-position: -780px -460px; } -.emoji-1F93D-1F3FC { background-position: -780px -480px; } -.emoji-1F93D-1F3FD { background-position: -780px -500px; } -.emoji-1F93D-1F3FE { background-position: -780px -520px; } -.emoji-1F93D-1F3FF { background-position: -780px -540px; } -.emoji-1F93E { background-position: -780px -560px; } -.emoji-1F93E-1F3FB { background-position: -780px -580px; } -.emoji-1F93E-1F3FC { background-position: -780px -600px; } -.emoji-1F93E-1F3FD { background-position: -780px -620px; } -.emoji-1F93E-1F3FE { background-position: -780px -640px; } -.emoji-1F93E-1F3FF { background-position: -780px -660px; } -.emoji-1F940 { background-position: -780px -680px; } -.emoji-1F941 { background-position: -780px -700px; } -.emoji-1F942 { background-position: -780px -720px; } -.emoji-1F943 { background-position: -780px -740px; } -.emoji-1F944 { background-position: -780px -760px; } -.emoji-1F945 { background-position: 0 -780px; } -.emoji-1F947 { background-position: -20px -780px; } -.emoji-1F948 { background-position: -40px -780px; } -.emoji-1F949 { background-position: -60px -780px; } -.emoji-1F94A { background-position: -80px -780px; } -.emoji-1F94B { background-position: -100px -780px; } -.emoji-1F950 { background-position: -120px -780px; } -.emoji-1F951 { background-position: -140px -780px; } -.emoji-1F952 { background-position: -160px -780px; } -.emoji-1F953 { background-position: -180px -780px; } -.emoji-1F954 { background-position: -200px -780px; } -.emoji-1F955 { background-position: -220px -780px; } -.emoji-1F956 { background-position: -240px -780px; } -.emoji-1F957 { background-position: -260px -780px; } -.emoji-1F958 { background-position: -280px -780px; } -.emoji-1F959 { background-position: -300px -780px; } -.emoji-1F95A { background-position: -320px -780px; } -.emoji-1F95B { background-position: -340px -780px; } -.emoji-1F95C { background-position: -360px -780px; } -.emoji-1F95D { background-position: -380px -780px; } -.emoji-1F95E { background-position: -400px -780px; } -.emoji-1F980 { background-position: -420px -780px; } -.emoji-1F981 { background-position: -440px -780px; } -.emoji-1F982 { background-position: -460px -780px; } -.emoji-1F983 { background-position: -480px -780px; } -.emoji-1F984 { background-position: -500px -780px; } -.emoji-1F985 { background-position: -520px -780px; } -.emoji-1F986 { background-position: -540px -780px; } -.emoji-1F987 { background-position: -560px -780px; } -.emoji-1F988 { background-position: -580px -780px; } -.emoji-1F989 { background-position: -600px -780px; } -.emoji-1F98A { background-position: -620px -780px; } -.emoji-1F98B { background-position: -640px -780px; } -.emoji-1F98C { background-position: -660px -780px; } -.emoji-1F98D { background-position: -680px -780px; } -.emoji-1F98E { background-position: -700px -780px; } -.emoji-1F98F { background-position: -720px -780px; } -.emoji-1F990 { background-position: -740px -780px; } -.emoji-1F991 { background-position: -760px -780px; } -.emoji-1F9C0 { background-position: -780px -780px; } -.emoji-203C { background-position: -800px 0; } -.emoji-2049 { background-position: -800px -20px; } -.emoji-2122 { background-position: -800px -40px; } -.emoji-2139 { background-position: -800px -60px; } -.emoji-2194 { background-position: -800px -80px; } -.emoji-2195 { background-position: -800px -100px; } -.emoji-2196 { background-position: -800px -120px; } -.emoji-2197 { background-position: -800px -140px; } -.emoji-2198 { background-position: -800px -160px; } -.emoji-2199 { background-position: -800px -180px; } -.emoji-21A9 { background-position: -800px -200px; } -.emoji-21AA { background-position: -800px -220px; } -.emoji-231A { background-position: -800px -240px; } -.emoji-231B { background-position: -800px -260px; } -.emoji-2328 { background-position: -800px -280px; } -.emoji-23CF { background-position: -800px -300px; } -.emoji-23E9 { background-position: -800px -320px; } -.emoji-23EA { background-position: -800px -340px; } -.emoji-23EB { background-position: -800px -360px; } -.emoji-23EC { background-position: -800px -380px; } -.emoji-23ED { background-position: -800px -400px; } -.emoji-23EE { background-position: -800px -420px; } -.emoji-23EF { background-position: -800px -440px; } -.emoji-23F0 { background-position: -800px -460px; } -.emoji-23F1 { background-position: -800px -480px; } -.emoji-23F2 { background-position: -800px -500px; } -.emoji-23F3 { background-position: -800px -520px; } -.emoji-23F8 { background-position: -800px -540px; } -.emoji-23F9 { background-position: -800px -560px; } -.emoji-23FA { background-position: -800px -580px; } -.emoji-24C2 { background-position: -800px -600px; } -.emoji-25AA { background-position: -800px -620px; } -.emoji-25AB { background-position: -800px -640px; } -.emoji-25B6 { background-position: -800px -660px; } -.emoji-25C0 { background-position: -800px -680px; } -.emoji-25FB { background-position: -800px -700px; } -.emoji-25FC { background-position: -800px -720px; } -.emoji-25FD { background-position: -800px -740px; } -.emoji-25FE { background-position: -800px -760px; } -.emoji-2600 { background-position: -800px -780px; } -.emoji-2601 { background-position: 0 -800px; } -.emoji-2602 { background-position: -20px -800px; } -.emoji-2603 { background-position: -40px -800px; } -.emoji-2604 { background-position: -60px -800px; } -.emoji-260E { background-position: -80px -800px; } -.emoji-2611 { background-position: -100px -800px; } -.emoji-2614 { background-position: -120px -800px; } -.emoji-2615 { background-position: -140px -800px; } -.emoji-2618 { background-position: -160px -800px; } -.emoji-261D { background-position: -180px -800px; } -.emoji-261D-1F3FB { background-position: -200px -800px; } -.emoji-261D-1F3FC { background-position: -220px -800px; } -.emoji-261D-1F3FD { background-position: -240px -800px; } -.emoji-261D-1F3FE { background-position: -260px -800px; } -.emoji-261D-1F3FF { background-position: -280px -800px; } -.emoji-2620 { background-position: -300px -800px; } -.emoji-2622 { background-position: -320px -800px; } -.emoji-2623 { background-position: -340px -800px; } -.emoji-2626 { background-position: -360px -800px; } -.emoji-262A { background-position: -380px -800px; } -.emoji-262E { background-position: -400px -800px; } -.emoji-262F { background-position: -420px -800px; } -.emoji-2638 { background-position: -440px -800px; } -.emoji-2639 { background-position: -460px -800px; } -.emoji-263A { background-position: -480px -800px; } -.emoji-2648 { background-position: -500px -800px; } -.emoji-2649 { background-position: -520px -800px; } -.emoji-264A { background-position: -540px -800px; } -.emoji-264B { background-position: -560px -800px; } -.emoji-264C { background-position: -580px -800px; } -.emoji-264D { background-position: -600px -800px; } -.emoji-264E { background-position: -620px -800px; } -.emoji-264F { background-position: -640px -800px; } -.emoji-2650 { background-position: -660px -800px; } -.emoji-2651 { background-position: -680px -800px; } -.emoji-2652 { background-position: -700px -800px; } -.emoji-2653 { background-position: -720px -800px; } -.emoji-2660 { background-position: -740px -800px; } -.emoji-2663 { background-position: -760px -800px; } -.emoji-2665 { background-position: -780px -800px; } -.emoji-2666 { background-position: -800px -800px; } -.emoji-2668 { background-position: -820px 0; } -.emoji-267B { background-position: -820px -20px; } -.emoji-267F { background-position: -820px -40px; } -.emoji-2692 { background-position: -820px -60px; } -.emoji-2693 { background-position: -820px -80px; } -.emoji-2694 { background-position: -820px -100px; } -.emoji-2696 { background-position: -820px -120px; } -.emoji-2697 { background-position: -820px -140px; } -.emoji-2699 { background-position: -820px -160px; } -.emoji-269B { background-position: -820px -180px; } -.emoji-269C { background-position: -820px -200px; } -.emoji-26A0 { background-position: -820px -220px; } -.emoji-26A1 { background-position: -820px -240px; } -.emoji-26AA { background-position: -820px -260px; } -.emoji-26AB { background-position: -820px -280px; } -.emoji-26B0 { background-position: -820px -300px; } -.emoji-26B1 { background-position: -820px -320px; } -.emoji-26BD { background-position: -820px -340px; } -.emoji-26BE { background-position: -820px -360px; } -.emoji-26C4 { background-position: -820px -380px; } -.emoji-26C5 { background-position: -820px -400px; } -.emoji-26C8 { background-position: -820px -420px; } -.emoji-26CE { background-position: -820px -440px; } -.emoji-26CF { background-position: -820px -460px; } -.emoji-26D1 { background-position: -820px -480px; } -.emoji-26D3 { background-position: -820px -500px; } -.emoji-26D4 { background-position: -820px -520px; } -.emoji-26E9 { background-position: -820px -540px; } -.emoji-26EA { background-position: -820px -560px; } -.emoji-26F0 { background-position: -820px -580px; } -.emoji-26F1 { background-position: -820px -600px; } -.emoji-26F2 { background-position: -820px -620px; } -.emoji-26F3 { background-position: -820px -640px; } -.emoji-26F4 { background-position: -820px -660px; } -.emoji-26F5 { background-position: -820px -680px; } -.emoji-26F7 { background-position: -820px -700px; } -.emoji-26F8 { background-position: -820px -720px; } -.emoji-26F9 { background-position: -820px -740px; } -.emoji-26F9-1F3FB { background-position: -820px -760px; } -.emoji-26F9-1F3FC { background-position: -820px -780px; } -.emoji-26F9-1F3FD { background-position: -820px -800px; } -.emoji-26F9-1F3FE { background-position: 0 -820px; } -.emoji-26F9-1F3FF { background-position: -20px -820px; } -.emoji-26FA { background-position: -40px -820px; } -.emoji-26FD { background-position: -60px -820px; } -.emoji-2702 { background-position: -80px -820px; } -.emoji-2705 { background-position: -100px -820px; } -.emoji-2708 { background-position: -120px -820px; } -.emoji-2709 { background-position: -140px -820px; } -.emoji-270A { background-position: -160px -820px; } -.emoji-270A-1F3FB { background-position: -180px -820px; } -.emoji-270A-1F3FC { background-position: -200px -820px; } -.emoji-270A-1F3FD { background-position: -220px -820px; } -.emoji-270A-1F3FE { background-position: -240px -820px; } -.emoji-270A-1F3FF { background-position: -260px -820px; } -.emoji-270B { background-position: -280px -820px; } -.emoji-270B-1F3FB { background-position: -300px -820px; } -.emoji-270B-1F3FC { background-position: -320px -820px; } -.emoji-270B-1F3FD { background-position: -340px -820px; } -.emoji-270B-1F3FE { background-position: -360px -820px; } -.emoji-270B-1F3FF { background-position: -380px -820px; } -.emoji-270C { background-position: -400px -820px; } -.emoji-270C-1F3FB { background-position: -420px -820px; } -.emoji-270C-1F3FC { background-position: -440px -820px; } -.emoji-270C-1F3FD { background-position: -460px -820px; } -.emoji-270C-1F3FE { background-position: -480px -820px; } -.emoji-270C-1F3FF { background-position: -500px -820px; } -.emoji-270D { background-position: -520px -820px; } -.emoji-270D-1F3FB { background-position: -540px -820px; } -.emoji-270D-1F3FC { background-position: -560px -820px; } -.emoji-270D-1F3FD { background-position: -580px -820px; } -.emoji-270D-1F3FE { background-position: -600px -820px; } -.emoji-270D-1F3FF { background-position: -620px -820px; } -.emoji-270F { background-position: -640px -820px; } -.emoji-2712 { background-position: -660px -820px; } -.emoji-2714 { background-position: -680px -820px; } -.emoji-2716 { background-position: -700px -820px; } -.emoji-271D { background-position: -720px -820px; } -.emoji-2721 { background-position: -740px -820px; } -.emoji-2728 { background-position: -760px -820px; } -.emoji-2733 { background-position: -780px -820px; } -.emoji-2734 { background-position: -800px -820px; } -.emoji-2744 { background-position: -820px -820px; } -.emoji-2747 { background-position: -840px 0; } -.emoji-274C { background-position: -840px -20px; } -.emoji-274E { background-position: -840px -40px; } -.emoji-2753 { background-position: -840px -60px; } -.emoji-2754 { background-position: -840px -80px; } -.emoji-2755 { background-position: -840px -100px; } -.emoji-2757 { background-position: -840px -120px; } -.emoji-2763 { background-position: -840px -140px; } -.emoji-2764 { background-position: -840px -160px; } -.emoji-2795 { background-position: -840px -180px; } -.emoji-2796 { background-position: -840px -200px; } -.emoji-2797 { background-position: -840px -220px; } -.emoji-27A1 { background-position: -840px -240px; } -.emoji-27B0 { background-position: -840px -260px; } -.emoji-27BF { background-position: -840px -280px; } -.emoji-2934 { background-position: -840px -300px; } -.emoji-2935 { background-position: -840px -320px; } -.emoji-2B05 { background-position: -840px -340px; } -.emoji-2B06 { background-position: -840px -360px; } -.emoji-2B07 { background-position: -840px -380px; } -.emoji-2B1B { background-position: -840px -400px; } -.emoji-2B1C { background-position: -840px -420px; } -.emoji-2B50 { background-position: -840px -440px; } -.emoji-2B55 { background-position: -840px -460px; } -.emoji-3030 { background-position: -840px -480px; } -.emoji-303D { background-position: -840px -500px; } -.emoji-3297 { background-position: -840px -520px; } -.emoji-3299 { background-position: -840px -540px; } - -.emoji-icon { - background-image: image-url('emoji.png'); - background-repeat: no-repeat; - height: 20px; - width: 20px; - - @media only screen and (-webkit-min-device-pixel-ratio: 2), - only screen and (min--moz-device-pixel-ratio: 2), - only screen and (-o-min-device-pixel-ratio: 2/1), - only screen and (min-device-pixel-ratio: 2), - only screen and (min-resolution: 192dpi), - only screen and (min-resolution: 2dppx) { - background-image: image-url('emoji@2x.png'); - background-size: 860px 840px; - } -} diff --git a/app/assets/stylesheets/pages/explore.scss b/app/assets/stylesheets/pages/explore.scss deleted file mode 100644 index 9b92128624c..00000000000 --- a/app/assets/stylesheets/pages/explore.scss +++ /dev/null @@ -1,8 +0,0 @@ -.explore-title { - text-align: center; - - h3 { - font-weight: normal; - font-size: 30px; - } -} diff --git a/app/assets/stylesheets/pages/icons.scss b/app/assets/stylesheets/pages/icons.scss deleted file mode 100644 index 226bd2ead31..00000000000 --- a/app/assets/stylesheets/pages/icons.scss +++ /dev/null @@ -1,51 +0,0 @@ -.ci-status-icon-success { - color: $gl-success; - - svg { - fill: $gl-success; - } -} - -.ci-status-icon-failed { - color: $gl-danger; - - svg { - fill: $gl-danger; - } -} - -.ci-status-icon-pending, -.ci-status-icon-success_with_warnings { - color: $gl-warning; - - svg { - fill: $gl-warning; - } -} - -.ci-status-icon-running { - color: $blue-normal; - - svg { - fill: $blue-normal; - } -} - -.ci-status-icon-canceled, -.ci-status-icon-disabled, -.ci-status-icon-not-found { - color: $gl-gray; - - svg { - fill: $gl-gray; - } -} - -.ci-status-icon-created, -.ci-status-icon-skipped { - color: $gray-darkest; - - svg { - fill: $gray-darkest; - } -} diff --git a/app/views/explore/_head.html.haml b/app/views/explore/_head.html.haml index d8a57560788..a3b0709e261 100644 --- a/app/views/explore/_head.html.haml +++ b/app/views/explore/_head.html.haml @@ -1,5 +1,5 @@ -.explore-title - %h3 +.explore-title.text-center + %h2 Explore GitLab %p.lead Discover projects, groups and snippets. Share your projects with others -- cgit v1.2.1 From f1d30769f3c3123b93f1e11ea9a76399719435c9 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Tue, 6 Dec 2016 13:29:13 -0600 Subject: Remove unused bootstrap imports --- app/assets/stylesheets/framework/tw_bootstrap.scss | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/tw_bootstrap.scss b/app/assets/stylesheets/framework/tw_bootstrap.scss index 55bc325b858..1a985ee2a66 100644 --- a/app/assets/stylesheets/framework/tw_bootstrap.scss +++ b/app/assets/stylesheets/framework/tw_bootstrap.scss @@ -21,7 +21,7 @@ @import "bootstrap/buttons"; // Components -@import "bootstrap/component-animations"; +// @import "bootstrap/component-animations"; // @import "bootstrap/dropdowns"; @import "bootstrap/button-groups"; @import "bootstrap/input-groups"; @@ -33,11 +33,11 @@ @import "bootstrap/labels"; @import "bootstrap/badges"; @import "bootstrap/alerts"; -@import "bootstrap/progress-bars"; +// @import "bootstrap/progress-bars"; @import "bootstrap/list-group"; -@import "bootstrap/wells"; -@import "bootstrap/close"; -@import "bootstrap/panels"; +// @import "bootstrap/wells"; +// @import "bootstrap/close"; +// @import "bootstrap/panels"; // Components w/ JavaScript @import "bootstrap/modals"; -- cgit v1.2.1 From 18489218443ea6b8c6fdfd9ab953ff7ef84f69db Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Wed, 7 Dec 2016 17:05:42 -0600 Subject: Remove pages/snippets css --- app/assets/stylesheets/framework.scss | 1 + app/assets/stylesheets/framework/emojis.scss | 2 +- app/assets/stylesheets/framework/snippets.scss | 48 ++++++++++++++++++ app/assets/stylesheets/framework/tw_bootstrap.scss | 6 +-- app/assets/stylesheets/pages/notifications.scss | 14 +----- app/assets/stylesheets/pages/snippets.scss | 58 ---------------------- app/views/projects/snippets/show.html.haml | 5 +- app/views/snippets/show.html.haml | 4 +- 8 files changed, 59 insertions(+), 79 deletions(-) create mode 100644 app/assets/stylesheets/framework/snippets.scss delete mode 100644 app/assets/stylesheets/pages/snippets.scss (limited to 'app') diff --git a/app/assets/stylesheets/framework.scss b/app/assets/stylesheets/framework.scss index 928ef408722..40bc0579393 100644 --- a/app/assets/stylesheets/framework.scss +++ b/app/assets/stylesheets/framework.scss @@ -46,3 +46,4 @@ @import "framework/broadcast-messages"; @import "framework/emojis.scss"; @import "framework/icons.scss"; +@import "framework/snippets.scss"; diff --git a/app/assets/stylesheets/framework/emojis.scss b/app/assets/stylesheets/framework/emojis.scss index f17797b2381..7158de65143 100644 --- a/app/assets/stylesheets/framework/emojis.scss +++ b/app/assets/stylesheets/framework/emojis.scss @@ -1,4 +1,4 @@ -.emoji-0023-20E3 { background-position: 0 0px; } +.emoji-0023-20E3 { background-position: 0 0; } .emoji-002A-20E3 { background-position: -20px 0; } .emoji-0030-20E3 { background-position: 0 -20px; } .emoji-0031-20E3 { background-position: -20px -20px; } diff --git a/app/assets/stylesheets/framework/snippets.scss b/app/assets/stylesheets/framework/snippets.scss new file mode 100644 index 00000000000..5f7e1b17cc7 --- /dev/null +++ b/app/assets/stylesheets/framework/snippets.scss @@ -0,0 +1,48 @@ +.snippet-row { + .title { + margin-bottom: 2px; + } + + .snippet-filename { + padding: 0 2px; + } +} + +.snippet-form-holder .file-holder .file-title { + padding: 2px; +} + +.markdown-snippet-copy { + position: fixed; + top: -10px; + left: -10px; + max-height: 0; + max-width: 0; +} + +.snippet-file-content { + border-radius: 3px; +} + +.snippet-header { + padding: $gl-padding 0; +} + +.snippet-title { + font-size: 24px; + font-weight: 600; +} + +.snippet-edited-ago { + color: $gray-darkest; +} + +.snippet-actions { + @media (min-width: $screen-sm-min) { + float: right; + } +} + +.snippet-scope-menu .btn-new { + margin-top: 15px; +} diff --git a/app/assets/stylesheets/framework/tw_bootstrap.scss b/app/assets/stylesheets/framework/tw_bootstrap.scss index 1a985ee2a66..d998d654aa4 100644 --- a/app/assets/stylesheets/framework/tw_bootstrap.scss +++ b/app/assets/stylesheets/framework/tw_bootstrap.scss @@ -21,7 +21,7 @@ @import "bootstrap/buttons"; // Components -// @import "bootstrap/component-animations"; +@import "bootstrap/component-animations"; // @import "bootstrap/dropdowns"; @import "bootstrap/button-groups"; @import "bootstrap/input-groups"; @@ -36,8 +36,8 @@ // @import "bootstrap/progress-bars"; @import "bootstrap/list-group"; // @import "bootstrap/wells"; -// @import "bootstrap/close"; -// @import "bootstrap/panels"; +@import "bootstrap/close"; +@import "bootstrap/panels"; // Components w/ JavaScript @import "bootstrap/modals"; diff --git a/app/assets/stylesheets/pages/notifications.scss b/app/assets/stylesheets/pages/notifications.scss index 7d61390a439..bdf07a99daf 100644 --- a/app/assets/stylesheets/pages/notifications.scss +++ b/app/assets/stylesheets/pages/notifications.scss @@ -10,19 +10,7 @@ position: relative; top: 1px; - > .fa { + .fa { font-size: 18px; } } - -.ns-part { - color: $gl-text-green; -} - -.ns-watch { - color: $gl-success; -} - -.ns-mute { - color: $gl-danger; -} diff --git a/app/assets/stylesheets/pages/snippets.scss b/app/assets/stylesheets/pages/snippets.scss deleted file mode 100644 index a6037d76797..00000000000 --- a/app/assets/stylesheets/pages/snippets.scss +++ /dev/null @@ -1,58 +0,0 @@ -.snippet-row { - .title { - margin-bottom: 2px; - } - - .snippet-filename { - padding: 0 2px; - } -} - -.snippet-form-holder .file-holder .file-title { - padding: 2px; -} - -.markdown-snippet-copy { - position: fixed; - top: -10px; - left: -10px; - max-height: 0; - max-width: 0; -} - -.snippet-file-content { - border-radius: 3px; - margin-bottom: $gl-padding; - - .btn-clipboard { - @extend .btn; - } -} - -.project-snippets .awards { - border-bottom: 1px solid $white-normal; - padding-bottom: $gl-padding; -} - -.snippet-header { - padding: $gl-padding 0; -} - -.snippet-title { - font-size: 24px; - font-weight: 600; -} - -.snippet-edited-ago { - color: $gray-darkest; -} - -.snippet-actions { - @media (min-width: $screen-sm-min) { - float: right; - } -} - -.snippet-scope-menu .btn-new { - margin-top: 15px; -} diff --git a/app/views/projects/snippets/show.html.haml b/app/views/projects/snippets/show.html.haml index 9503dbded13..79d87b7db12 100644 --- a/app/views/projects/snippets/show.html.haml +++ b/app/views/projects/snippets/show.html.haml @@ -8,10 +8,11 @@ = blob_icon 0, @snippet.file_name = @snippet.file_name .file-actions - = clipboard_button(clipboard_target: ".blob-content[data-blob-id='#{@snippet.id}']") + = clipboard_button(clipboard_target: ".blob-content[data-blob-id='#{@snippet.id}']", class: "btn btn-sm") = link_to 'Raw', raw_namespace_project_snippet_path(@project.namespace, @project, @snippet), class: "btn btn-sm", target: "_blank" = render 'shared/snippets/blob' - = render 'award_emoji/awards_block', awardable: @snippet, inline: true + .row-content-block.top-block.content-component-block + = render 'award_emoji/awards_block', awardable: @snippet, inline: true %div#notes= render "projects/notes/notes_with_form" diff --git a/app/views/snippets/show.html.haml b/app/views/snippets/show.html.haml index 27d7a6c5bb6..837a1a0cc8c 100644 --- a/app/views/snippets/show.html.haml +++ b/app/views/snippets/show.html.haml @@ -7,9 +7,9 @@ = blob_icon 0, @snippet.file_name = @snippet.file_name .file-actions - = clipboard_button(clipboard_target: ".blob-content[data-blob-id='#{@snippet.id}']") + = clipboard_button(clipboard_target: ".blob-content[data-blob-id='#{@snippet.id}']", class: "btn btn-sm") = link_to 'Raw', raw_snippet_path(@snippet), class: "btn btn-sm", target: "_blank" = link_to 'Download', download_snippet_path(@snippet), class: "btn btn-sm" = render 'shared/snippets/blob' -= render 'award_emoji/awards_block', awardable: @snippet, inline: true \ No newline at end of file += render 'award_emoji/awards_block', awardable: @snippet, inline: true -- cgit v1.2.1 From 05bc71c856c735fa364e15db62ba5d40cfd7c5ef Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 14 Dec 2016 22:38:40 +0800 Subject: Convert CI YAML variables keys into strings So that this would be more consistent with the other variables, which all of them are string based. Closes #25554 --- app/models/ci/build.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index e7cf606a7ae..99f3f4711aa 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -10,7 +10,7 @@ module Ci has_many :deployments, as: :deployable serialize :options - serialize :yaml_variables + serialize :yaml_variables, Gitlab::Serialize::YamlVariables validates :coverage, numericality: true, allow_blank: true validates_presence_of :ref -- cgit v1.2.1 From 089dbc7db1d885a62d2022c0a696b26ad4ae0e17 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 15 Dec 2016 09:31:25 +0000 Subject: Fixed bug with +1 not autocompleting --- app/assets/javascripts/gfm_auto_complete.js.es6 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/gfm_auto_complete.js.es6 b/app/assets/javascripts/gfm_auto_complete.js.es6 index 076475d3ed4..0e274521525 100644 --- a/app/assets/javascripts/gfm_auto_complete.js.es6 +++ b/app/assets/javascripts/gfm_auto_complete.js.es6 @@ -62,14 +62,15 @@ // The below is taken from At.js source // Tweaked to commands to start without a space only if char before is a non-word character // https://github.com/ichord/At.js - var _a, _y, regexp, match; + var _a, _y, regexp, match, atSymbols; + atSymbols = Object.keys(this.app.controllers).join('|'); subtext = subtext.split(' ').pop(); flag = flag.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); _a = decodeURI("%C3%80"); _y = decodeURI("%C3%BF"); - regexp = new RegExp("(?:\\B|\\W|\\s)" + flag + "(?!\\W)([A-Za-z" + _a + "-" + _y + "0-9_\'\.\+\-]*)$", 'gi'); + regexp = new RegExp("(?:\\B|\\W|\\s)" + flag + "(?![" + atSymbols + "])([A-Za-z" + _a + "-" + _y + "0-9_\'\.\+\-]*)$", 'gi'); match = regexp.exec(subtext); -- cgit v1.2.1 From b4a7e7cfbf2a79cf6ecdb8b251ad41c09a40e5bd Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 15 Dec 2016 18:38:26 +0800 Subject: Don't call anything on a block, use simple if Feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7333#note_20058743 --- app/models/ci/pipeline.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 9edfc75eac7..48354cdbefb 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -89,13 +89,15 @@ module Ci # ref can't be HEAD or SHA, can only be branch/tag name scope :latest, ->(ref = nil) do - max_id = unscope(:select).select("max(#{quoted_table_name}.id)") + max_id = unscope(:select) + .select("max(#{quoted_table_name}.id)") + .group(:ref, :sha) if ref - where(ref: ref) + where(id: max_id, ref: ref) else - self - end.where(id: max_id.group(:ref, :sha)) + where(id: max_id) + end end def self.latest_status(ref = nil) -- cgit v1.2.1 From 48fed57b05b0394ca824bed90c670505b3a8a273 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Thu, 15 Dec 2016 10:55:34 +0000 Subject: Fix scss linter error --- app/assets/stylesheets/pages/pipelines.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 4569b91383f..3054f0655db 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -683,7 +683,7 @@ width: 25px; height: 25px; - &:before{ + &::before { top: 1px; left: 1px; } @@ -725,7 +725,7 @@ height: 30px; width: 30px; - &:before { + &::before { position: relative; top: 3px; left: 3px; -- cgit v1.2.1 From 6731ab5d76c34462f0b4424ff03c9646ad916b76 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Thu, 18 Aug 2016 16:31:44 +0200 Subject: Add Gitlab::Middleware::Multipart --- app/uploaders/artifact_uploader.rb | 10 +--------- app/uploaders/attachment_uploader.rb | 2 +- app/uploaders/avatar_uploader.rb | 2 +- app/uploaders/file_uploader.rb | 2 +- app/uploaders/gitlab_uploader.rb | 11 +++++++++++ app/uploaders/lfs_object_uploader.rb | 10 +--------- 6 files changed, 16 insertions(+), 21 deletions(-) create mode 100644 app/uploaders/gitlab_uploader.rb (limited to 'app') diff --git a/app/uploaders/artifact_uploader.rb b/app/uploaders/artifact_uploader.rb index b6c52ddac7a..86f317dcd18 100644 --- a/app/uploaders/artifact_uploader.rb +++ b/app/uploaders/artifact_uploader.rb @@ -1,4 +1,4 @@ -class ArtifactUploader < CarrierWave::Uploader::Base +class ArtifactUploader < GitlabUploader storage :file attr_accessor :build, :field @@ -38,12 +38,4 @@ class ArtifactUploader < CarrierWave::Uploader::Base def exists? file.try(:exists?) end - - def move_to_cache - true - end - - def move_to_store - true - end end diff --git a/app/uploaders/attachment_uploader.rb b/app/uploaders/attachment_uploader.rb index fb3b5dfecd0..cfcb877cc3e 100644 --- a/app/uploaders/attachment_uploader.rb +++ b/app/uploaders/attachment_uploader.rb @@ -1,4 +1,4 @@ -class AttachmentUploader < CarrierWave::Uploader::Base +class AttachmentUploader < GitlabUploader include UploaderHelper storage :file diff --git a/app/uploaders/avatar_uploader.rb b/app/uploaders/avatar_uploader.rb index 38683fdf6d7..a1ecb7bc00b 100644 --- a/app/uploaders/avatar_uploader.rb +++ b/app/uploaders/avatar_uploader.rb @@ -1,4 +1,4 @@ -class AvatarUploader < CarrierWave::Uploader::Base +class AvatarUploader < GitlabUploader include UploaderHelper storage :file diff --git a/app/uploaders/file_uploader.rb b/app/uploaders/file_uploader.rb index 3ac6030c21c..47bef7cd1e4 100644 --- a/app/uploaders/file_uploader.rb +++ b/app/uploaders/file_uploader.rb @@ -1,4 +1,4 @@ -class FileUploader < CarrierWave::Uploader::Base +class FileUploader < GitlabUploader include UploaderHelper MARKDOWN_PATTERN = %r{\!?\[.*?\]\(/uploads/(?[0-9a-f]{32})/(?.*?)\)} diff --git a/app/uploaders/gitlab_uploader.rb b/app/uploaders/gitlab_uploader.rb new file mode 100644 index 00000000000..02d7c601d6c --- /dev/null +++ b/app/uploaders/gitlab_uploader.rb @@ -0,0 +1,11 @@ +class GitlabUploader < CarrierWave::Uploader::Base + # Reduce disk IO + def move_to_cache + true + end + + # Reduce disk IO + def move_to_store + true + end +end diff --git a/app/uploaders/lfs_object_uploader.rb b/app/uploaders/lfs_object_uploader.rb index 4f356dd663e..faab539b8e0 100644 --- a/app/uploaders/lfs_object_uploader.rb +++ b/app/uploaders/lfs_object_uploader.rb @@ -1,4 +1,4 @@ -class LfsObjectUploader < CarrierWave::Uploader::Base +class LfsObjectUploader < GitlabUploader storage :file def store_dir @@ -9,14 +9,6 @@ class LfsObjectUploader < CarrierWave::Uploader::Base "#{Gitlab.config.lfs.storage_path}/tmp/cache" end - def move_to_cache - true - end - - def move_to_store - true - end - def exists? file.try(:exists?) end -- cgit v1.2.1 From 26628fb91a89bbe4998633eec00d2bd76cfb95c0 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Thu, 15 Dec 2016 14:19:28 +0200 Subject: BB importer: Fixed bug with putting expired token to a project.clone_url --- app/controllers/import/bitbucket_controller.rb | 3 +++ 1 file changed, 3 insertions(+) (limited to 'app') diff --git a/app/controllers/import/bitbucket_controller.rb b/app/controllers/import/bitbucket_controller.rb index b9cc6556140..8e42cdf415f 100644 --- a/app/controllers/import/bitbucket_controller.rb +++ b/app/controllers/import/bitbucket_controller.rb @@ -49,6 +49,9 @@ class Import::BitbucketController < Import::BaseController namespace = find_or_create_namespace(@target_namespace, current_user) if current_user.can?(:create_projects, namespace) + # The token in a session can be expired, we need to get most recent one because + # Bitbucket::Connection class refreshes it. + session[:bitbucket_token] = bitbucket_client.connection.token @project = Gitlab::BitbucketImport::ProjectCreator.new(repo, @project_name, namespace, current_user, credentials).execute else render 'unauthorized' -- cgit v1.2.1 From 70c0a76cad4c7ce5656c97ac81b4caa21318e961 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 15 Dec 2016 13:41:46 +0100 Subject: Fix rubocop offenses in code related to pipelines --- app/controllers/projects/pipelines_controller.rb | 35 ++++++++++++++---------- 1 file changed, 21 insertions(+), 14 deletions(-) (limited to 'app') diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb index 7179f3b22ea..642651101f0 100644 --- a/app/controllers/projects/pipelines_controller.rb +++ b/app/controllers/projects/pipelines_controller.rb @@ -7,25 +7,32 @@ class Projects::PipelinesController < Projects::ApplicationController def index @scope = params[:scope] - @pipelines = PipelinesFinder.new(project).execute(scope: @scope).page(params[:page]).per(30) + @pipelines = PipelinesFinder + .new(project) + .execute(scope: @scope) + .page(params[:page]) + .per(30) - @running_or_pending_count = PipelinesFinder.new(project).execute(scope: 'running').count - @pipelines_count = PipelinesFinder.new(project).execute.count + @running_or_pending_count = PipelinesFinder + .new(project).execute(scope: 'running').count + + @pipelines_count = PipelinesFinder + .new(project).execute.count respond_to do |format| format.html format.json do - render json: { - pipelines: PipelineSerializer - .new(project: @project, user: @current_user) - .with_pagination(request, response) - .represent(@pipelines), - updated_at: Time.now.utc, - count: { - all: @pipelines_count, - running_or_pending: @running_or_pending_count - } - } + render json: { + pipelines: PipelineSerializer + .new(project: @project, user: @current_user) + .with_pagination(request, response) + .represent(@pipelines), + updated_at: Time.now.utc, + count: { + all: @pipelines_count, + running_or_pending: @running_or_pending_count + } + } end end end -- cgit v1.2.1 From 141faaacf9119ce5d765efe73c6509030ba078cd Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Fri, 25 Nov 2016 17:36:37 -0200 Subject: Mattermost Notifications Service --- app/models/project.rb | 1 + .../project_services/chat_message/base_message.rb | 34 ++++ .../project_services/chat_message/build_message.rb | 82 ++++++++++ .../project_services/chat_message/issue_message.rb | 69 ++++++++ .../project_services/chat_message/merge_message.rb | 60 +++++++ .../project_services/chat_message/note_message.rb | 83 ++++++++++ .../chat_message/pipeline_message.rb | 78 +++++++++ .../project_services/chat_message/push_message.rb | 110 +++++++++++++ .../chat_message/wiki_page_message.rb | 53 +++++++ app/models/project_services/chat_service.rb | 141 ++++++++++++++++- app/models/project_services/mattermost_service.rb | 41 +++++ .../mattermost_slash_commands_service.rb | 12 +- app/models/project_services/slack_service.rb | 174 +++------------------ .../project_services/slack_service/base_message.rb | 34 ---- .../slack_service/build_message.rb | 82 ---------- .../slack_service/issue_message.rb | 69 -------- .../slack_service/merge_message.rb | 60 ------- .../project_services/slack_service/note_message.rb | 83 ---------- .../slack_service/pipeline_message.rb | 78 --------- .../project_services/slack_service/push_message.rb | 110 ------------- .../slack_service/wiki_page_message.rb | 53 ------- app/models/service.rb | 1 + 22 files changed, 776 insertions(+), 732 deletions(-) create mode 100644 app/models/project_services/chat_message/base_message.rb create mode 100644 app/models/project_services/chat_message/build_message.rb create mode 100644 app/models/project_services/chat_message/issue_message.rb create mode 100644 app/models/project_services/chat_message/merge_message.rb create mode 100644 app/models/project_services/chat_message/note_message.rb create mode 100644 app/models/project_services/chat_message/pipeline_message.rb create mode 100644 app/models/project_services/chat_message/push_message.rb create mode 100644 app/models/project_services/chat_message/wiki_page_message.rb create mode 100644 app/models/project_services/mattermost_service.rb delete mode 100644 app/models/project_services/slack_service/base_message.rb delete mode 100644 app/models/project_services/slack_service/build_message.rb delete mode 100644 app/models/project_services/slack_service/issue_message.rb delete mode 100644 app/models/project_services/slack_service/merge_message.rb delete mode 100644 app/models/project_services/slack_service/note_message.rb delete mode 100644 app/models/project_services/slack_service/pipeline_message.rb delete mode 100644 app/models/project_services/slack_service/push_message.rb delete mode 100644 app/models/project_services/slack_service/wiki_page_message.rb (limited to 'app') diff --git a/app/models/project.rb b/app/models/project.rb index 2c726cfc5df..19c2d24212d 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -95,6 +95,7 @@ class Project < ActiveRecord::Base has_one :asana_service, dependent: :destroy has_one :gemnasium_service, dependent: :destroy has_one :mattermost_slash_commands_service, dependent: :destroy + has_one :mattermost_service, dependent: :destroy has_one :slack_service, dependent: :destroy has_one :buildkite_service, dependent: :destroy has_one :bamboo_service, dependent: :destroy diff --git a/app/models/project_services/chat_message/base_message.rb b/app/models/project_services/chat_message/base_message.rb new file mode 100644 index 00000000000..a03605d01fb --- /dev/null +++ b/app/models/project_services/chat_message/base_message.rb @@ -0,0 +1,34 @@ +require 'slack-notifier' + +module ChatMessage + class BaseMessage + def initialize(params) + raise NotImplementedError + end + + def pretext + format(message) + end + + def fallback + end + + def attachments + raise NotImplementedError + end + + private + + def message + raise NotImplementedError + end + + def format(string) + Slack::Notifier::LinkFormatter.format(string) + end + + def attachment_color + '#345' + end + end +end diff --git a/app/models/project_services/chat_message/build_message.rb b/app/models/project_services/chat_message/build_message.rb new file mode 100644 index 00000000000..53e35cb21bf --- /dev/null +++ b/app/models/project_services/chat_message/build_message.rb @@ -0,0 +1,82 @@ +module ChatMessage + class BuildMessage < BaseMessage + attr_reader :sha + attr_reader :ref_type + attr_reader :ref + attr_reader :status + attr_reader :project_name + attr_reader :project_url + attr_reader :user_name + attr_reader :duration + + def initialize(params) + @sha = params[:sha] + @ref_type = params[:tag] ? 'tag' : 'branch' + @ref = params[:ref] + @project_name = params[:project_name] + @project_url = params[:project_url] + @status = params[:commit][:status] + @user_name = params[:commit][:author_name] + @duration = params[:commit][:duration] + end + + def pretext + '' + end + + def fallback + format(message) + end + + def attachments + [{ text: format(message), color: attachment_color }] + end + + private + + def message + "#{project_link}: Commit #{commit_link} of #{branch_link} #{ref_type} by #{user_name} #{humanized_status} in #{duration} #{'second'.pluralize(duration)}" + end + + def format(string) + Slack::Notifier::LinkFormatter.format(string) + end + + def humanized_status + case status + when 'success' + 'passed' + else + status + end + end + + def attachment_color + if status == 'success' + 'good' + else + 'danger' + end + end + + def branch_url + "#{project_url}/commits/#{ref}" + end + + def branch_link + "[#{ref}](#{branch_url})" + end + + def project_link + "[#{project_name}](#{project_url})" + end + + def commit_url + "#{project_url}/commit/#{sha}/builds" + end + + def commit_link + "[#{Commit.truncate_sha(sha)}](#{commit_url})" + end + end +end diff --git a/app/models/project_services/chat_message/issue_message.rb b/app/models/project_services/chat_message/issue_message.rb new file mode 100644 index 00000000000..14fd64e5332 --- /dev/null +++ b/app/models/project_services/chat_message/issue_message.rb @@ -0,0 +1,69 @@ +module ChatMessage + class IssueMessage < BaseMessage + attr_reader :user_name + attr_reader :title + attr_reader :project_name + attr_reader :project_url + attr_reader :issue_iid + attr_reader :issue_url + attr_reader :action + attr_reader :state + attr_reader :description + + def initialize(params) + @user_name = params[:user][:username] + @project_name = params[:project_name] + @project_url = params[:project_url] + + obj_attr = params[:object_attributes] + obj_attr = HashWithIndifferentAccess.new(obj_attr) + @title = obj_attr[:title] + @issue_iid = obj_attr[:iid] + @issue_url = obj_attr[:url] + @action = obj_attr[:action] + @state = obj_attr[:state] + @description = obj_attr[:description] || '' + end + + def attachments + return [] unless opened_issue? + + description_message + end + + private + + def message + case state + when "opened" + "[#{project_link}] Issue #{state} by #{user_name}" + else + "[#{project_link}] Issue #{issue_link} #{state} by #{user_name}" + end + end + + def opened_issue? + action == "open" + end + + def description_message + [{ + title: issue_title, + title_link: issue_url, + text: format(description), + color: "#C95823" }] + end + + def project_link + "[#{project_name}](#{project_url})" + end + + def issue_link + "[#{issue_title}](#{issue_url})" + end + + def issue_title + "##{issue_iid} #{title}" + end + end +end diff --git a/app/models/project_services/chat_message/merge_message.rb b/app/models/project_services/chat_message/merge_message.rb new file mode 100644 index 00000000000..ab5e8b24167 --- /dev/null +++ b/app/models/project_services/chat_message/merge_message.rb @@ -0,0 +1,60 @@ +module ChatMessage + class MergeMessage < BaseMessage + attr_reader :user_name + attr_reader :project_name + attr_reader :project_url + attr_reader :merge_request_id + attr_reader :source_branch + attr_reader :target_branch + attr_reader :state + attr_reader :title + + def initialize(params) + @user_name = params[:user][:username] + @project_name = params[:project_name] + @project_url = params[:project_url] + + obj_attr = params[:object_attributes] + obj_attr = HashWithIndifferentAccess.new(obj_attr) + @merge_request_id = obj_attr[:iid] + @source_branch = obj_attr[:source_branch] + @target_branch = obj_attr[:target_branch] + @state = obj_attr[:state] + @title = format_title(obj_attr[:title]) + end + + def pretext + format(message) + end + + def attachments + [] + end + + private + + def format_title(title) + '*' + title.lines.first.chomp + '*' + end + + def message + merge_request_message + end + + def project_link + "[#{project_name}](#{project_url})" + end + + def merge_request_message + "#{user_name} #{state} #{merge_request_link} in #{project_link}: #{title}" + end + + def merge_request_link + "[merge request !#{merge_request_id}](#{merge_request_url})" + end + + def merge_request_url + "#{project_url}/merge_requests/#{merge_request_id}" + end + end +end diff --git a/app/models/project_services/chat_message/note_message.rb b/app/models/project_services/chat_message/note_message.rb new file mode 100644 index 00000000000..ca1d7207034 --- /dev/null +++ b/app/models/project_services/chat_message/note_message.rb @@ -0,0 +1,83 @@ +module ChatMessage + class NoteMessage < BaseMessage + attr_reader :message + attr_reader :user_name + attr_reader :project_name + attr_reader :project_link + attr_reader :note + attr_reader :note_url + attr_reader :title + + def initialize(params) + params = HashWithIndifferentAccess.new(params) + @user_name = params[:user][:username] + @project_name = params[:project_name] + @project_url = params[:project_url] + + obj_attr = params[:object_attributes] + obj_attr = HashWithIndifferentAccess.new(obj_attr) + @note = obj_attr[:note] + @note_url = obj_attr[:url] + noteable_type = obj_attr[:noteable_type] + + case noteable_type + when "Commit" + create_commit_note(HashWithIndifferentAccess.new(params[:commit])) + when "Issue" + create_issue_note(HashWithIndifferentAccess.new(params[:issue])) + when "MergeRequest" + create_merge_note(HashWithIndifferentAccess.new(params[:merge_request])) + when "Snippet" + create_snippet_note(HashWithIndifferentAccess.new(params[:snippet])) + end + end + + def attachments + description_message + end + + private + + def format_title(title) + title.lines.first.chomp + end + + def create_commit_note(commit) + commit_sha = commit[:id] + commit_sha = Commit.truncate_sha(commit_sha) + commented_on_message( + "commit #{commit_sha}", + format_title(commit[:message])) + end + + def create_issue_note(issue) + commented_on_message( + "issue ##{issue[:iid]}", + format_title(issue[:title])) + end + + def create_merge_note(merge_request) + commented_on_message( + "merge request !#{merge_request[:iid]}", + format_title(merge_request[:title])) + end + + def create_snippet_note(snippet) + commented_on_message( + "snippet ##{snippet[:id]}", + format_title(snippet[:title])) + end + + def description_message + [{ text: format(@note), color: attachment_color }] + end + + def project_link + "[#{@project_name}](#{@project_url})" + end + + def commented_on_message(target, title) + @message = "#{@user_name} [commented on #{target}](#{@note_url}) in #{project_link}: *#{title}*" + end + end +end diff --git a/app/models/project_services/chat_message/pipeline_message.rb b/app/models/project_services/chat_message/pipeline_message.rb new file mode 100644 index 00000000000..210027565a8 --- /dev/null +++ b/app/models/project_services/chat_message/pipeline_message.rb @@ -0,0 +1,78 @@ +module ChatMessage + class PipelineMessage < BaseMessage + attr_reader :ref_type, :ref, :status, :project_name, :project_url, + :user_name, :duration, :pipeline_id + + def initialize(data) + pipeline_attributes = data[:object_attributes] + @ref_type = pipeline_attributes[:tag] ? 'tag' : 'branch' + @ref = pipeline_attributes[:ref] + @status = pipeline_attributes[:status] + @duration = pipeline_attributes[:duration] + @pipeline_id = pipeline_attributes[:id] + + @project_name = data[:project][:path_with_namespace] + @project_url = data[:project][:web_url] + @user_name = (data[:user] && data[:user][:name]) || 'API' + end + + def pretext + '' + end + + def fallback + format(message) + end + + def attachments + [{ text: format(message), color: attachment_color }] + end + + private + + def message + "#{project_link}: Pipeline #{pipeline_link} of #{branch_link} #{ref_type} by #{user_name} #{humanized_status} in #{duration} #{'second'.pluralize(duration)}" + end + + def format(string) + Slack::Notifier::LinkFormatter.format(string) + end + + def humanized_status + case status + when 'success' + 'passed' + else + status + end + end + + def attachment_color + if status == 'success' + 'good' + else + 'danger' + end + end + + def branch_url + "#{project_url}/commits/#{ref}" + end + + def branch_link + "[#{ref}](#{branch_url})" + end + + def project_link + "[#{project_name}](#{project_url})" + end + + def pipeline_url + "#{project_url}/pipelines/#{pipeline_id}" + end + + def pipeline_link + "[##{pipeline_id}](#{pipeline_url})" + end + end +end diff --git a/app/models/project_services/chat_message/push_message.rb b/app/models/project_services/chat_message/push_message.rb new file mode 100644 index 00000000000..2d73b71ec37 --- /dev/null +++ b/app/models/project_services/chat_message/push_message.rb @@ -0,0 +1,110 @@ +module ChatMessage + class PushMessage < BaseMessage + attr_reader :after + attr_reader :before + attr_reader :commits + attr_reader :project_name + attr_reader :project_url + attr_reader :ref + attr_reader :ref_type + attr_reader :user_name + + def initialize(params) + @after = params[:after] + @before = params[:before] + @commits = params.fetch(:commits, []) + @project_name = params[:project_name] + @project_url = params[:project_url] + @ref_type = Gitlab::Git.tag_ref?(params[:ref]) ? 'tag' : 'branch' + @ref = Gitlab::Git.ref_name(params[:ref]) + @user_name = params[:user_name] + end + + def pretext + format(message) + end + + def attachments + return [] if new_branch? || removed_branch? + + commit_message_attachments + end + + private + + def message + if new_branch? + new_branch_message + elsif removed_branch? + removed_branch_message + else + push_message + end + end + + def format(string) + Slack::Notifier::LinkFormatter.format(string) + end + + def new_branch_message + "#{user_name} pushed new #{ref_type} #{branch_link} to #{project_link}" + end + + def removed_branch_message + "#{user_name} removed #{ref_type} #{ref} from #{project_link}" + end + + def push_message + "#{user_name} pushed to #{ref_type} #{branch_link} of #{project_link} (#{compare_link})" + end + + def commit_messages + commits.map { |commit| compose_commit_message(commit) }.join("\n") + end + + def commit_message_attachments + [{ text: format(commit_messages), color: attachment_color }] + end + + def compose_commit_message(commit) + author = commit[:author][:name] + id = Commit.truncate_sha(commit[:id]) + message = commit[:message] + url = commit[:url] + + "[#{id}](#{url}): #{message} - #{author}" + end + + def new_branch? + Gitlab::Git.blank_ref?(before) + end + + def removed_branch? + Gitlab::Git.blank_ref?(after) + end + + def branch_url + "#{project_url}/commits/#{ref}" + end + + def compare_url + "#{project_url}/compare/#{before}...#{after}" + end + + def branch_link + "[#{ref}](#{branch_url})" + end + + def project_link + "[#{project_name}](#{project_url})" + end + + def compare_link + "[Compare changes](#{compare_url})" + end + + def attachment_color + '#345' + end + end +end diff --git a/app/models/project_services/chat_message/wiki_page_message.rb b/app/models/project_services/chat_message/wiki_page_message.rb new file mode 100644 index 00000000000..134083e4504 --- /dev/null +++ b/app/models/project_services/chat_message/wiki_page_message.rb @@ -0,0 +1,53 @@ +module ChatMessage + class WikiPageMessage < BaseMessage + attr_reader :user_name + attr_reader :title + attr_reader :project_name + attr_reader :project_url + attr_reader :wiki_page_url + attr_reader :action + attr_reader :description + + def initialize(params) + @user_name = params[:user][:username] + @project_name = params[:project_name] + @project_url = params[:project_url] + + obj_attr = params[:object_attributes] + obj_attr = HashWithIndifferentAccess.new(obj_attr) + @title = obj_attr[:title] + @wiki_page_url = obj_attr[:url] + @description = obj_attr[:content] + + @action = + case obj_attr[:action] + when "create" + "created" + when "update" + "edited" + end + end + + def attachments + description_message + end + + private + + def message + "#{user_name} #{action} #{wiki_page_link} in #{project_link}: *#{title}*" + end + + def description_message + [{ text: format(@description), color: attachment_color }] + end + + def project_link + "[#{project_name}](#{project_url})" + end + + def wiki_page_link + "[wiki page](#{wiki_page_url})" + end + end +end diff --git a/app/models/project_services/chat_service.rb b/app/models/project_services/chat_service.rb index d36beff5fa6..8ac049ba939 100644 --- a/app/models/project_services/chat_service.rb +++ b/app/models/project_services/chat_service.rb @@ -1,21 +1,148 @@ # Base class for Chat services # This class is not meant to be used directly, but only to inherrit from. class ChatService < Service + include ChatMessage + default_value_for :category, 'chat' - has_many :chat_names, foreign_key: :service_id + prop_accessor :webhook, :username, :channel + boolean_accessor :notify_only_broken_builds, :notify_only_broken_pipelines + + validates :webhook, presence: true, url: true, if: :activated? + + def initialize_properties + # Custom serialized properties initialization + self.supported_events.each { |event| self.class.prop_accessor(event_channel_name(event)) } - def valid_token?(token) - self.respond_to?(:token) && - self.token.present? && - ActiveSupport::SecurityUtils.variable_size_secure_compare(token, self.token) + if properties.nil? + self.properties = {} + self.notify_only_broken_builds = true + self.notify_only_broken_pipelines = true + end + end + + def can_test? + valid? end def supported_events - [] + %w[push issue confidential_issue merge_request note tag_push + build pipeline wiki_page] end - def trigger(params) + def execute(data) + return unless supported_events.include?(data[:object_kind]) + return unless webhook.present? + + object_kind = data[:object_kind] + + data = data.merge( + project_url: project_url, + project_name: project_name + ) + + # WebHook events often have an 'update' event that follows a 'open' or + # 'close' action. Ignore update events for now to prevent duplicate + # messages from arriving. + + message = get_message(object_kind, data) + + return false unless message + + opt = {} + + opt[:channel] = get_channel_field(object_kind).presence || channel || default_channel + opt[:username] = username if username + + notifier = Slack::Notifier.new(webhook, opt) + notifier.ping(message.pretext, attachments: message.attachments, fallback: message.fallback) + + true + end + + def event_channel_names + supported_events.map { |event| event_channel_name(event) } + end + + def event_field(event) + fields.find { |field| field[:name] == event_channel_name(event) } + end + + def global_fields + fields.reject { |field| field[:name].end_with?('channel') } + end + + def default_channel raise NotImplementedError end + + private + + def get_message(object_kind, data) + case object_kind + when "push", "tag_push" + PushMessage.new(data) + when "issue" + IssueMessage.new(data) unless is_update?(data) + when "merge_request" + MergeMessage.new(data) unless is_update?(data) + when "note" + NoteMessage.new(data) + when "build" + BuildMessage.new(data) if should_build_be_notified?(data) + when "pipeline" + PipelineMessage.new(data) if should_pipeline_be_notified?(data) + when "wiki_page" + WikiPageMessage.new(data) + end + end + + def get_channel_field(event) + field_name = event_channel_name(event) + self.public_send(field_name) + end + + def build_event_channels + supported_events.reduce([]) do |channels, event| + channels << { type: 'text', name: event_channel_name(event), placeholder: default_channel } + end + end + + def event_channel_name(event) + "#{event}_channel" + end + + def project_name + project.name_with_namespace.gsub(/\s/, '') + end + + def project_url + project.web_url + end + + def is_update?(data) + data[:object_attributes][:action] == 'update' + end + + def should_build_be_notified?(data) + case data[:commit][:status] + when 'success' + !notify_only_broken_builds? + when 'failed' + true + else + false + end + end + + def should_pipeline_be_notified?(data) + case data[:object_attributes][:status] + when 'success' + !notify_only_broken_pipelines? + when 'failed' + true + else + false + end + end end diff --git a/app/models/project_services/mattermost_service.rb b/app/models/project_services/mattermost_service.rb new file mode 100644 index 00000000000..9d61c251a32 --- /dev/null +++ b/app/models/project_services/mattermost_service.rb @@ -0,0 +1,41 @@ +class MattermostService < ChatService + def title + 'Mattermost notifications' + end + + def description + 'Receive event notifications in Mattermost' + end + + def to_param + 'mattermost' + end + + def help + 'This service sends notifications about projects events to Mattermost channels.
    + To set up this service: +
    ' + end + + def fields + default_fields + build_event_channels + end + + def default_fields + [ + { type: 'text', name: 'webhook', placeholder: 'http://mattermost_host/hooks/...' }, + { type: 'text', name: 'username', placeholder: 'username' }, + { type: 'checkbox', name: 'notify_only_broken_builds' }, + { type: 'checkbox', name: 'notify_only_broken_pipelines' }, + ] + end + + def default_channel + "#town-square" + end +end diff --git a/app/models/project_services/mattermost_slash_commands_service.rb b/app/models/project_services/mattermost_slash_commands_service.rb index 33431f41dc2..3993dfbda17 100644 --- a/app/models/project_services/mattermost_slash_commands_service.rb +++ b/app/models/project_services/mattermost_slash_commands_service.rb @@ -1,8 +1,18 @@ -class MattermostSlashCommandsService < ChatService +class MattermostSlashCommandsService < Service include TriggersHelper prop_accessor :token + def valid_token?(token) + self.respond_to?(:token) && + self.token.present? && + ActiveSupport::SecurityUtils.variable_size_secure_compare(token, self.token) + end + + def supported_events + [] + end + def can_test? false end diff --git a/app/models/project_services/slack_service.rb b/app/models/project_services/slack_service.rb index e1b937817f4..0df1743c4ba 100644 --- a/app/models/project_services/slack_service.rb +++ b/app/models/project_services/slack_service.rb @@ -1,25 +1,10 @@ -class SlackService < Service - prop_accessor :webhook, :username, :channel - boolean_accessor :notify_only_broken_builds, :notify_only_broken_pipelines - validates :webhook, presence: true, url: true, if: :activated? - - def initialize_properties - # Custom serialized properties initialization - self.supported_events.each { |event| self.class.prop_accessor(event_channel_name(event)) } - - if properties.nil? - self.properties = {} - self.notify_only_broken_builds = true - self.notify_only_broken_pipelines = true - end - end - +class SlackService < ChatService def title - 'Slack' + 'Slack notifications' end def description - 'A team communication tool for the 21st century' + 'Receive event notifications in Slack' end def to_param @@ -27,150 +12,29 @@ class SlackService < Service end def help - 'This service sends notifications to your Slack channel.
    - To setup this Service you need to create a new "Incoming webhook" in your Slack integration panel, - and enter the Webhook URL below.' + 'This service sends notifications about projects events to Slack channels.
    + To setup this service: +
      +
    1. Add an incoming webhook in your Slack team. The default channel can be overridden for each event.
    2. +
    3. Paste the Webhook URL into the field below.
    4. +
    5. Select events below to enable notifications. The channel and username are optional.
    6. +
    ' end def fields - default_fields = - [ - { type: 'text', name: 'webhook', placeholder: 'https://hooks.slack.com/services/...' }, - { type: 'text', name: 'username', placeholder: 'username' }, - { type: 'text', name: 'channel', placeholder: "#general" }, - { type: 'checkbox', name: 'notify_only_broken_builds' }, - { type: 'checkbox', name: 'notify_only_broken_pipelines' }, - ] - default_fields + build_event_channels end - def supported_events - %w[push issue confidential_issue merge_request note tag_push - build pipeline wiki_page] - end - - def execute(data) - return unless supported_events.include?(data[:object_kind]) - return unless webhook.present? - - object_kind = data[:object_kind] - - data = data.merge( - project_url: project_url, - project_name: project_name - ) - - # WebHook events often have an 'update' event that follows a 'open' or - # 'close' action. Ignore update events for now to prevent duplicate - # messages from arriving. - - message = get_message(object_kind, data) - - if message - opt = {} - - event_channel = get_channel_field(object_kind) || channel - - opt[:channel] = event_channel if event_channel - opt[:username] = username if username - - notifier = Slack::Notifier.new(webhook, opt) - notifier.ping(message.pretext, attachments: message.attachments, fallback: message.fallback) - - true - else - false - end - end - - def event_channel_names - supported_events.map { |event| event_channel_name(event) } - end - - def event_field(event) - fields.find { |field| field[:name] == event_channel_name(event) } + def default_fields + [ + { type: 'text', name: 'webhook', placeholder: 'https://hooks.slack.com/services/...' }, + { type: 'text', name: 'username', placeholder: 'username' }, + { type: 'checkbox', name: 'notify_only_broken_builds' }, + { type: 'checkbox', name: 'notify_only_broken_pipelines' }, + ] end - def global_fields - fields.reject { |field| field[:name].end_with?('channel') } - end - - private - - def get_message(object_kind, data) - case object_kind - when "push", "tag_push" - PushMessage.new(data) - when "issue" - IssueMessage.new(data) unless is_update?(data) - when "merge_request" - MergeMessage.new(data) unless is_update?(data) - when "note" - NoteMessage.new(data) - when "build" - BuildMessage.new(data) if should_build_be_notified?(data) - when "pipeline" - PipelineMessage.new(data) if should_pipeline_be_notified?(data) - when "wiki_page" - WikiPageMessage.new(data) - end - end - - def get_channel_field(event) - field_name = event_channel_name(event) - self.public_send(field_name) - end - - def build_event_channels - supported_events.reduce([]) do |channels, event| - channels << { type: 'text', name: event_channel_name(event), placeholder: "#general" } - end - end - - def event_channel_name(event) - "#{event}_channel" - end - - def project_name - project.name_with_namespace.gsub(/\s/, '') - end - - def project_url - project.web_url - end - - def is_update?(data) - data[:object_attributes][:action] == 'update' - end - - def should_build_be_notified?(data) - case data[:commit][:status] - when 'success' - !notify_only_broken_builds? - when 'failed' - true - else - false - end - end - - def should_pipeline_be_notified?(data) - case data[:object_attributes][:status] - when 'success' - !notify_only_broken_pipelines? - when 'failed' - true - else - false - end + def default_channel + "#general" end end - -require "slack_service/issue_message" -require "slack_service/push_message" -require "slack_service/merge_message" -require "slack_service/note_message" -require "slack_service/build_message" -require "slack_service/pipeline_message" -require "slack_service/wiki_page_message" diff --git a/app/models/project_services/slack_service/base_message.rb b/app/models/project_services/slack_service/base_message.rb deleted file mode 100644 index f1182824687..00000000000 --- a/app/models/project_services/slack_service/base_message.rb +++ /dev/null @@ -1,34 +0,0 @@ -require 'slack-notifier' - -class SlackService - class BaseMessage - def initialize(params) - raise NotImplementedError - end - - def pretext - format(message) - end - - def fallback - end - - def attachments - raise NotImplementedError - end - - private - - def message - raise NotImplementedError - end - - def format(string) - Slack::Notifier::LinkFormatter.format(string) - end - - def attachment_color - '#345' - end - end -end diff --git a/app/models/project_services/slack_service/build_message.rb b/app/models/project_services/slack_service/build_message.rb deleted file mode 100644 index 0fca4267bad..00000000000 --- a/app/models/project_services/slack_service/build_message.rb +++ /dev/null @@ -1,82 +0,0 @@ -class SlackService - class BuildMessage < BaseMessage - attr_reader :sha - attr_reader :ref_type - attr_reader :ref - attr_reader :status - attr_reader :project_name - attr_reader :project_url - attr_reader :user_name - attr_reader :duration - - def initialize(params) - @sha = params[:sha] - @ref_type = params[:tag] ? 'tag' : 'branch' - @ref = params[:ref] - @project_name = params[:project_name] - @project_url = params[:project_url] - @status = params[:commit][:status] - @user_name = params[:commit][:author_name] - @duration = params[:commit][:duration] - end - - def pretext - '' - end - - def fallback - format(message) - end - - def attachments - [{ text: format(message), color: attachment_color }] - end - - private - - def message - "#{project_link}: Commit #{commit_link} of #{branch_link} #{ref_type} by #{user_name} #{humanized_status} in #{duration} #{'second'.pluralize(duration)}" - end - - def format(string) - Slack::Notifier::LinkFormatter.format(string) - end - - def humanized_status - case status - when 'success' - 'passed' - else - status - end - end - - def attachment_color - if status == 'success' - 'good' - else - 'danger' - end - end - - def branch_url - "#{project_url}/commits/#{ref}" - end - - def branch_link - "[#{ref}](#{branch_url})" - end - - def project_link - "[#{project_name}](#{project_url})" - end - - def commit_url - "#{project_url}/commit/#{sha}/builds" - end - - def commit_link - "[#{Commit.truncate_sha(sha)}](#{commit_url})" - end - end -end diff --git a/app/models/project_services/slack_service/issue_message.rb b/app/models/project_services/slack_service/issue_message.rb deleted file mode 100644 index cd87a79d0c6..00000000000 --- a/app/models/project_services/slack_service/issue_message.rb +++ /dev/null @@ -1,69 +0,0 @@ -class SlackService - class IssueMessage < BaseMessage - attr_reader :user_name - attr_reader :title - attr_reader :project_name - attr_reader :project_url - attr_reader :issue_iid - attr_reader :issue_url - attr_reader :action - attr_reader :state - attr_reader :description - - def initialize(params) - @user_name = params[:user][:username] - @project_name = params[:project_name] - @project_url = params[:project_url] - - obj_attr = params[:object_attributes] - obj_attr = HashWithIndifferentAccess.new(obj_attr) - @title = obj_attr[:title] - @issue_iid = obj_attr[:iid] - @issue_url = obj_attr[:url] - @action = obj_attr[:action] - @state = obj_attr[:state] - @description = obj_attr[:description] || '' - end - - def attachments - return [] unless opened_issue? - - description_message - end - - private - - def message - case state - when "opened" - "[#{project_link}] Issue #{state} by #{user_name}" - else - "[#{project_link}] Issue #{issue_link} #{state} by #{user_name}" - end - end - - def opened_issue? - action == "open" - end - - def description_message - [{ - title: issue_title, - title_link: issue_url, - text: format(description), - color: "#C95823" }] - end - - def project_link - "[#{project_name}](#{project_url})" - end - - def issue_link - "[#{issue_title}](#{issue_url})" - end - - def issue_title - "##{issue_iid} #{title}" - end - end -end diff --git a/app/models/project_services/slack_service/merge_message.rb b/app/models/project_services/slack_service/merge_message.rb deleted file mode 100644 index b7615c96068..00000000000 --- a/app/models/project_services/slack_service/merge_message.rb +++ /dev/null @@ -1,60 +0,0 @@ -class SlackService - class MergeMessage < BaseMessage - attr_reader :user_name - attr_reader :project_name - attr_reader :project_url - attr_reader :merge_request_id - attr_reader :source_branch - attr_reader :target_branch - attr_reader :state - attr_reader :title - - def initialize(params) - @user_name = params[:user][:username] - @project_name = params[:project_name] - @project_url = params[:project_url] - - obj_attr = params[:object_attributes] - obj_attr = HashWithIndifferentAccess.new(obj_attr) - @merge_request_id = obj_attr[:iid] - @source_branch = obj_attr[:source_branch] - @target_branch = obj_attr[:target_branch] - @state = obj_attr[:state] - @title = format_title(obj_attr[:title]) - end - - def pretext - format(message) - end - - def attachments - [] - end - - private - - def format_title(title) - '*' + title.lines.first.chomp + '*' - end - - def message - merge_request_message - end - - def project_link - "[#{project_name}](#{project_url})" - end - - def merge_request_message - "#{user_name} #{state} #{merge_request_link} in #{project_link}: #{title}" - end - - def merge_request_link - "[merge request !#{merge_request_id}](#{merge_request_url})" - end - - def merge_request_url - "#{project_url}/merge_requests/#{merge_request_id}" - end - end -end diff --git a/app/models/project_services/slack_service/note_message.rb b/app/models/project_services/slack_service/note_message.rb deleted file mode 100644 index 797c5937f09..00000000000 --- a/app/models/project_services/slack_service/note_message.rb +++ /dev/null @@ -1,83 +0,0 @@ -class SlackService - class NoteMessage < BaseMessage - attr_reader :message - attr_reader :user_name - attr_reader :project_name - attr_reader :project_link - attr_reader :note - attr_reader :note_url - attr_reader :title - - def initialize(params) - params = HashWithIndifferentAccess.new(params) - @user_name = params[:user][:username] - @project_name = params[:project_name] - @project_url = params[:project_url] - - obj_attr = params[:object_attributes] - obj_attr = HashWithIndifferentAccess.new(obj_attr) - @note = obj_attr[:note] - @note_url = obj_attr[:url] - noteable_type = obj_attr[:noteable_type] - - case noteable_type - when "Commit" - create_commit_note(HashWithIndifferentAccess.new(params[:commit])) - when "Issue" - create_issue_note(HashWithIndifferentAccess.new(params[:issue])) - when "MergeRequest" - create_merge_note(HashWithIndifferentAccess.new(params[:merge_request])) - when "Snippet" - create_snippet_note(HashWithIndifferentAccess.new(params[:snippet])) - end - end - - def attachments - description_message - end - - private - - def format_title(title) - title.lines.first.chomp - end - - def create_commit_note(commit) - commit_sha = commit[:id] - commit_sha = Commit.truncate_sha(commit_sha) - commented_on_message( - "commit #{commit_sha}", - format_title(commit[:message])) - end - - def create_issue_note(issue) - commented_on_message( - "issue ##{issue[:iid]}", - format_title(issue[:title])) - end - - def create_merge_note(merge_request) - commented_on_message( - "merge request !#{merge_request[:iid]}", - format_title(merge_request[:title])) - end - - def create_snippet_note(snippet) - commented_on_message( - "snippet ##{snippet[:id]}", - format_title(snippet[:title])) - end - - def description_message - [{ text: format(@note), color: attachment_color }] - end - - def project_link - "[#{@project_name}](#{@project_url})" - end - - def commented_on_message(target, title) - @message = "#{@user_name} [commented on #{target}](#{@note_url}) in #{project_link}: *#{title}*" - end - end -end diff --git a/app/models/project_services/slack_service/pipeline_message.rb b/app/models/project_services/slack_service/pipeline_message.rb deleted file mode 100644 index b6355fc4171..00000000000 --- a/app/models/project_services/slack_service/pipeline_message.rb +++ /dev/null @@ -1,78 +0,0 @@ -class SlackService - class PipelineMessage < BaseMessage - attr_reader :ref_type, :ref, :status, :project_name, :project_url, - :user_name, :duration, :pipeline_id - - def initialize(data) - pipeline_attributes = data[:object_attributes] - @ref_type = pipeline_attributes[:tag] ? 'tag' : 'branch' - @ref = pipeline_attributes[:ref] - @status = pipeline_attributes[:status] - @duration = pipeline_attributes[:duration] - @pipeline_id = pipeline_attributes[:id] - - @project_name = data[:project][:path_with_namespace] - @project_url = data[:project][:web_url] - @user_name = (data[:user] && data[:user][:name]) || 'API' - end - - def pretext - '' - end - - def fallback - format(message) - end - - def attachments - [{ text: format(message), color: attachment_color }] - end - - private - - def message - "#{project_link}: Pipeline #{pipeline_link} of #{branch_link} #{ref_type} by #{user_name} #{humanized_status} in #{duration} #{'second'.pluralize(duration)}" - end - - def format(string) - Slack::Notifier::LinkFormatter.format(string) - end - - def humanized_status - case status - when 'success' - 'passed' - else - status - end - end - - def attachment_color - if status == 'success' - 'good' - else - 'danger' - end - end - - def branch_url - "#{project_url}/commits/#{ref}" - end - - def branch_link - "[#{ref}](#{branch_url})" - end - - def project_link - "[#{project_name}](#{project_url})" - end - - def pipeline_url - "#{project_url}/pipelines/#{pipeline_id}" - end - - def pipeline_link - "[##{pipeline_id}](#{pipeline_url})" - end - end -end diff --git a/app/models/project_services/slack_service/push_message.rb b/app/models/project_services/slack_service/push_message.rb deleted file mode 100644 index b26f3e9ddce..00000000000 --- a/app/models/project_services/slack_service/push_message.rb +++ /dev/null @@ -1,110 +0,0 @@ -class SlackService - class PushMessage < BaseMessage - attr_reader :after - attr_reader :before - attr_reader :commits - attr_reader :project_name - attr_reader :project_url - attr_reader :ref - attr_reader :ref_type - attr_reader :user_name - - def initialize(params) - @after = params[:after] - @before = params[:before] - @commits = params.fetch(:commits, []) - @project_name = params[:project_name] - @project_url = params[:project_url] - @ref_type = Gitlab::Git.tag_ref?(params[:ref]) ? 'tag' : 'branch' - @ref = Gitlab::Git.ref_name(params[:ref]) - @user_name = params[:user_name] - end - - def pretext - format(message) - end - - def attachments - return [] if new_branch? || removed_branch? - - commit_message_attachments - end - - private - - def message - if new_branch? - new_branch_message - elsif removed_branch? - removed_branch_message - else - push_message - end - end - - def format(string) - Slack::Notifier::LinkFormatter.format(string) - end - - def new_branch_message - "#{user_name} pushed new #{ref_type} #{branch_link} to #{project_link}" - end - - def removed_branch_message - "#{user_name} removed #{ref_type} #{ref} from #{project_link}" - end - - def push_message - "#{user_name} pushed to #{ref_type} #{branch_link} of #{project_link} (#{compare_link})" - end - - def commit_messages - commits.map { |commit| compose_commit_message(commit) }.join("\n") - end - - def commit_message_attachments - [{ text: format(commit_messages), color: attachment_color }] - end - - def compose_commit_message(commit) - author = commit[:author][:name] - id = Commit.truncate_sha(commit[:id]) - message = commit[:message] - url = commit[:url] - - "[#{id}](#{url}): #{message} - #{author}" - end - - def new_branch? - Gitlab::Git.blank_ref?(before) - end - - def removed_branch? - Gitlab::Git.blank_ref?(after) - end - - def branch_url - "#{project_url}/commits/#{ref}" - end - - def compare_url - "#{project_url}/compare/#{before}...#{after}" - end - - def branch_link - "[#{ref}](#{branch_url})" - end - - def project_link - "[#{project_name}](#{project_url})" - end - - def compare_link - "[Compare changes](#{compare_url})" - end - - def attachment_color - '#345' - end - end -end diff --git a/app/models/project_services/slack_service/wiki_page_message.rb b/app/models/project_services/slack_service/wiki_page_message.rb deleted file mode 100644 index 160ca3ac115..00000000000 --- a/app/models/project_services/slack_service/wiki_page_message.rb +++ /dev/null @@ -1,53 +0,0 @@ -class SlackService - class WikiPageMessage < BaseMessage - attr_reader :user_name - attr_reader :title - attr_reader :project_name - attr_reader :project_url - attr_reader :wiki_page_url - attr_reader :action - attr_reader :description - - def initialize(params) - @user_name = params[:user][:username] - @project_name = params[:project_name] - @project_url = params[:project_url] - - obj_attr = params[:object_attributes] - obj_attr = HashWithIndifferentAccess.new(obj_attr) - @title = obj_attr[:title] - @wiki_page_url = obj_attr[:url] - @description = obj_attr[:content] - - @action = - case obj_attr[:action] - when "create" - "created" - when "update" - "edited" - end - end - - def attachments - description_message - end - - private - - def message - "#{user_name} #{action} #{wiki_page_link} in #{project_link}: *#{title}*" - end - - def description_message - [{ text: format(@description), color: attachment_color }] - end - - def project_link - "[#{project_name}](#{project_url})" - end - - def wiki_page_link - "[wiki page](#{wiki_page_url})" - end - end -end diff --git a/app/models/service.rb b/app/models/service.rb index e49a8fa2904..8e58f2a1925 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -220,6 +220,7 @@ class Service < ActiveRecord::Base pivotaltracker pushover redmine + mattermost slack teamcity ] -- cgit v1.2.1 From 93a03cd92f6418fbeaf126c30c161ab40d377e94 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Thu, 8 Dec 2016 01:09:18 +0000 Subject: Add an environment slug --- app/models/environment.rb | 50 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'app') diff --git a/app/models/environment.rb b/app/models/environment.rb index 96700143ddd..0abbf674b9d 100644 --- a/app/models/environment.rb +++ b/app/models/environment.rb @@ -1,9 +1,15 @@ class Environment < ActiveRecord::Base + # Used to generate random suffixes for the slug + NUMBERS = '0'..'9' + SUFFIX_CHARS = ('a'..'z').to_a + NUMBERS.to_a + belongs_to :project, required: true, validate: true has_many :deployments before_validation :nullify_external_url + before_validation :generate_slug, if: ->(env) { env.slug.blank? } + before_save :set_environment_type validates :name, @@ -13,6 +19,13 @@ class Environment < ActiveRecord::Base format: { with: Gitlab::Regex.environment_name_regex, message: Gitlab::Regex.environment_name_regex_message } + validates :slug, + presence: true, + uniqueness: { scope: :project_id }, + length: { maximum: 24 }, + format: { with: Gitlab::Regex.environment_slug_regex, + message: Gitlab::Regex.environment_slug_regex_message } + validates :external_url, uniqueness: { scope: :project_id }, length: { maximum: 255 }, @@ -107,4 +120,41 @@ class Environment < ActiveRecord::Base action.expanded_environment_name == environment end end + + # An environment name is not necessarily suitable for use in URLs, DNS + # or other third-party contexts, so provide a slugified version. A slug has + # the following properties: + # * contains only lowercase letters (a-z), numbers (0-9), and '-' + # * begins with a letter + # * has a maximum length of 24 bytes (OpenShift limitation) + # * cannot end with `-` + def generate_slug + # Lowercase letters and numbers only + slugified = name.to_s.downcase.gsub(/[^a-z0-9]/, '-') + + # Must start with a letter + slugified = "env-" + slugified if NUMBERS.cover?(slugified[0]) + + # Maximum length: 24 characters (OpenShift limitation) + slugified = slugified[0..23] + + # Cannot end with a "-" character (Kubernetes label limitation) + slugified = slugified[0..-2] if slugified[-1] == "-" + + # Add a random suffix, shortening the current string if necessary, if it + # has been slugified. This ensures uniqueness. + slugified = slugified[0..16] + "-" + random_suffix if slugified != name + + self.slug = slugified + end + + private + + # Slugifying a name may remove the uniqueness guarantee afforded by it being + # based on name (which must be unique). To compensate, we add a random + # 6-byte suffix in those circumstances. This is not *guaranteed* uniqueness, + # but the chance of collisions is vanishingly small + def random_suffix + (0..5).map { SUFFIX_CHARS.sample }.join + end end -- cgit v1.2.1 From 58486918fc12bbcc5139b6ca32461ad5e037497b Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Thu, 8 Dec 2016 15:37:41 +0000 Subject: Create environments when the build referencing them is created --- app/services/ci/create_pipeline_builds_service.rb | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/services/ci/create_pipeline_builds_service.rb b/app/services/ci/create_pipeline_builds_service.rb index 005014fa1de..b7da3f8e7eb 100644 --- a/app/services/ci/create_pipeline_builds_service.rb +++ b/app/services/ci/create_pipeline_builds_service.rb @@ -10,18 +10,29 @@ module Ci end end + def project + pipeline.project + end + private def create_build(build_attributes) build_attributes = build_attributes.merge( pipeline: pipeline, - project: pipeline.project, + project: project, ref: pipeline.ref, tag: pipeline.tag, user: current_user, trigger_request: trigger_request ) - pipeline.builds.create(build_attributes) + build = pipeline.builds.create(build_attributes) + + # Create the environment before the build starts. This sets its slug and + # makes it available as an environment variable + project.environments.find_or_create_by(name: build.expanded_environment_name) if + build.has_environment? + + build end def new_builds -- cgit v1.2.1 From 80513a129592583ed100e7a90fc9ea144eb62ea9 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Thu, 8 Dec 2016 16:21:16 +0000 Subject: Add $CI_ENVIRONMENT_NAME and $CI_ENVIRONMENT_SLUG --- app/models/ci/build.rb | 20 ++++++++++++++++++-- app/models/environment.rb | 7 +++++++ 2 files changed, 25 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 45a416a4c41..fdbf28a1d68 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -9,6 +9,14 @@ module Ci has_many :deployments, as: :deployable + # The "environment" field for builds is a String, and is the unexpanded name + def persisted_environment + @persisted_environment ||= Environment.find_by( + name: expanded_environment_name, + project_id: gl_project_id + ) + end + serialize :options serialize :yaml_variables @@ -143,7 +151,7 @@ module Ci end def expanded_environment_name - ExpandVariables.expand(environment, variables) if environment + ExpandVariables.expand(environment, simple_variables) if environment end def has_environment? @@ -206,7 +214,8 @@ module Ci slugified.gsub(/[^a-z0-9]/, '-')[0..62] end - def variables + # Variables whose value does not depend on other variables + def simple_variables variables = predefined_variables variables += project.predefined_variables variables += pipeline.predefined_variables @@ -219,6 +228,13 @@ module Ci variables end + # All variables, including those dependent on other variables + def variables + variables = simple_variables + variables += persisted_environment.predefined_variables if persisted_environment.present? + variables + end + def merge_request merge_requests = MergeRequest.includes(:merge_request_diff) .where(source_branch: ref, source_project_id: pipeline.gl_project_id) diff --git a/app/models/environment.rb b/app/models/environment.rb index 0abbf674b9d..8ef1c841ea3 100644 --- a/app/models/environment.rb +++ b/app/models/environment.rb @@ -50,6 +50,13 @@ class Environment < ActiveRecord::Base state :stopped end + def predefined_variables + [ + { key: 'CI_ENVIRONMENT_NAME', value: name, public: true }, + { key: 'CI_ENVIRONMENT_SLUG', value: slug, public: true }, + ] + end + def recently_updated_on_branch?(ref) ref.to_s == last_deployment.try(:ref) end -- cgit v1.2.1 From 12db4cc0e70d3e249f3bf9fde85e336839422319 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 9 Dec 2016 01:56:31 +0000 Subject: Merge branch 'jej-note-search-uses-finder' into 'security' Fix missing Note access checks in by moving Note#search to updated NoteFinder Split from !2024 to partially solve https://gitlab.com/gitlab-org/gitlab-ce/issues/23867 ## Which fixes are in this MR? :warning: - Potentially untested :bomb: - No test coverage :traffic_light: - Test coverage of some sort exists (a test failed when error raised) :vertical_traffic_light: - Test coverage of return value (a test failed when nil used) :white_check_mark: - Permissions check tested ### Note lookup without access check - [x] :white_check_mark: app/finders/notes_finder.rb:13 :download_code check - [x] :white_check_mark: app/finders/notes_finder.rb:19 `SnippetsFinder` - [x] :white_check_mark: app/models/note.rb:121 [`Issue#visible_to_user`] - [x] :white_check_mark: lib/gitlab/project_search_results.rb:113 - This is the only use of `app/models/note.rb:121` above, but importantly has no access checks at all. This means it leaks MR comments and snippets when those features are `team-only` in addition to the issue comments which would be fixed by `app/models/note.rb:121`. - It is only called from SearchController where `can?(current_user, :download_code, @project)` is checked, so commit comments are not leaked. ### Previous discussions - [x] https://dev.gitlab.org/gitlab/gitlabhq/merge_requests/2024/diffs#b915c5267a63628b0bafd23d37792ae73ceae272_13_13 `: download_code` check on commit - [x] https://dev.gitlab.org/gitlab/gitlabhq/merge_requests/2024/diffs#b915c5267a63628b0bafd23d37792ae73ceae272_19_19 `SnippetsFinder` should be used - `SnippetsFinder` should check if the snippets feature is enabled -> https://gitlab.com/gitlab-org/gitlab-ce/issues/25223 ### Acceptance criteria met? - [x] Tests added for new code - [x] TODO comments removed - [x] Squashed and removed skipped tests - [x] Changelog entry - [ ] State Gitlab versions affected and issue severity in description - [ ] Create technical debt issue for NotesFinder. - Either split into `NotesFinder::ForTarget` and `NotesFinder::Search` or consider object per notable type such as `NotesFinder::OnIssue`. For the first option could create `NotesFinder::Base` which is either inherited from or which can be included in the other two. - Avoid case statement anti-pattern in this finder with use of `NotesFinder::OnCommit` etc. Consider something on the finder for this? `Model.finder(user, project)` - Move `inc_author` to the controller, and implement `related_notes` to replace `non_diff_notes`/`mr_and_commit_notes` See merge request !2035 --- app/controllers/projects/notes_controller.rb | 2 +- app/finders/notes_finder.rb | 113 +++++++++++++++++---- app/models/merge_request.rb | 4 +- app/models/note.rb | 17 ---- .../merge_requests/_merge_request.html.haml | 2 +- app/views/projects/merge_requests/_show.html.haml | 2 +- 6 files changed, 99 insertions(+), 41 deletions(-) (limited to 'app') diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb index 15ca080c696..b71509f2c9b 100644 --- a/app/controllers/projects/notes_controller.rb +++ b/app/controllers/projects/notes_controller.rb @@ -217,6 +217,6 @@ class Projects::NotesController < Projects::ApplicationController end def find_current_user_notes - @notes = NotesFinder.new.execute(project, current_user, params) + @notes = NotesFinder.new(project, current_user, params).execute.inc_author end end diff --git a/app/finders/notes_finder.rb b/app/finders/notes_finder.rb index 2484339e3a4..4bd8c83081a 100644 --- a/app/finders/notes_finder.rb +++ b/app/finders/notes_finder.rb @@ -1,27 +1,102 @@ class NotesFinder FETCH_OVERLAP = 5.seconds - def execute(project, current_user, params) - target_type = params[:target_type] - target_id = params[:target_id] - # Default to 0 to remain compatible with old clients - last_fetched_at = Time.at(params.fetch(:last_fetched_at, 0).to_i) - - notes = - case target_type - when "commit" - project.notes.for_commit_id(target_id).non_diff_notes - when "issue" - IssuesFinder.new(current_user, project_id: project.id).find(target_id).notes.inc_author - when "merge_request" - MergeRequestsFinder.new(current_user, project_id: project.id).find(target_id).mr_and_commit_notes.inc_author - when "snippet", "project_snippet" - project.snippets.find(target_id).notes + # Used to filter Notes + # When used with target_type and target_id this returns notes specifically for the controller + # + # Arguments: + # current_user - which user check authorizations with + # project - which project to look for notes on + # params: + # target_type: string + # target_id: integer + # last_fetched_at: time + # search: string + # + def initialize(project, current_user, params = {}) + @project = project + @current_user = current_user + @params = params + init_collection + end + + def execute + @notes = since_fetch_at(@params[:last_fetched_at]) if @params[:last_fetched_at] + @notes + end + + private + + def init_collection + if @params[:target_id] + @notes = on_target(@params[:target_type], @params[:target_id]) + else + @notes = notes_of_any_type + end + end + + def notes_of_any_type + types = %w(commit issue merge_request snippet) + note_relations = types.map { |t| notes_for_type(t) } + note_relations.map!{ |notes| search(@params[:search], notes) } if @params[:search] + UnionFinder.new.find_union(note_relations, Note) + end + + def noteables_for_type(noteable_type) + case noteable_type + when "issue" + IssuesFinder.new(@current_user, project_id: @project.id).execute + when "merge_request" + MergeRequestsFinder.new(@current_user, project_id: @project.id).execute + when "snippet", "project_snippet" + SnippetsFinder.new.execute(@current_user, filter: :by_project, project: @project) + else + raise 'invalid target_type' + end + end + + def notes_for_type(noteable_type) + if noteable_type == "commit" + if Ability.allowed?(@current_user, :download_code, @project) + @project.notes.where(noteable_type: 'Commit') + else + Note.none + end + else + finder = noteables_for_type(noteable_type) + @project.notes.where(noteable_type: finder.base_class.name, noteable_id: finder.reorder(nil)) + end + end + + def on_target(target_type, target_id) + if target_type == "commit" + notes_for_type('commit').for_commit_id(target_id) + else + target = noteables_for_type(target_type).find(target_id) + + if target.respond_to?(:related_notes) + target.related_notes else - raise 'invalid target_type' + target.notes end + end + end + + # Searches for notes matching the given query. + # + # This method uses ILIKE on PostgreSQL and LIKE on MySQL. + # + def search(query, notes_relation = @notes) + pattern = "%#{query}%" + notes_relation.where(Note.arel_table[:note].matches(pattern)) + end + + # Notes changed since last fetch + # Uses overlapping intervals to avoid worrying about race conditions + def since_fetch_at(fetch_time) + # Default to 0 to remain compatible with old clients + last_fetched_at = Time.at(@params.fetch(:last_fetched_at, 0).to_i) - # Use overlapping intervals to avoid worrying about race conditions - notes.where('updated_at > ?', last_fetched_at - FETCH_OVERLAP).fresh + @notes.where('updated_at > ?', last_fetched_at - FETCH_OVERLAP).fresh end end diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index ea3cf1cdaac..b73d7acefea 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -452,7 +452,7 @@ class MergeRequest < ActiveRecord::Base should_remove_source_branch? || force_remove_source_branch? end - def mr_and_commit_notes + def related_notes # Fetch comments only from last 100 commits commits_for_notes_limit = 100 commit_ids = commits.last(commits_for_notes_limit).map(&:id) @@ -468,7 +468,7 @@ class MergeRequest < ActiveRecord::Base end def discussions - @discussions ||= self.mr_and_commit_notes. + @discussions ||= self.related_notes. inc_relations_for_view. fresh. discussions diff --git a/app/models/note.rb b/app/models/note.rb index 08bd08743ef..0c1b05dabf2 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -107,23 +107,6 @@ class Note < ActiveRecord::Base Discussion.for_diff_notes(active_notes). map { |d| [d.line_code, d] }.to_h end - - # Searches for notes matching the given query. - # - # This method uses ILIKE on PostgreSQL and LIKE on MySQL. - # - # query - The search query as a String. - # as_user - Limit results to those viewable by a specific user - # - # Returns an ActiveRecord::Relation. - def search(query, as_user: nil) - table = arel_table - pattern = "%#{query}%" - - Note.joins('LEFT JOIN issues ON issues.id = noteable_id'). - where(table[:note].matches(pattern)). - merge(Issue.visible_to_user(as_user)) - end end def cross_reference? diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml index fa189ae62d8..959c796ecec 100644 --- a/app/views/projects/merge_requests/_merge_request.html.haml +++ b/app/views/projects/merge_requests/_merge_request.html.haml @@ -39,7 +39,7 @@ = icon('thumbs-down') = downvotes - - note_count = merge_request.mr_and_commit_notes.user.count + - note_count = merge_request.related_notes.user.count %li = link_to merge_request_path(merge_request, anchor: 'notes'), class: ('no-comments' if note_count.zero?) do = icon('comments') diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml index 896f10104fa..5febe806bdd 100644 --- a/app/views/projects/merge_requests/_show.html.haml +++ b/app/views/projects/merge_requests/_show.html.haml @@ -53,7 +53,7 @@ %li.notes-tab = link_to namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: 'div#notes', action: 'notes', toggle: 'tab' } do Discussion - %span.badge= @merge_request.mr_and_commit_notes.user.count + %span.badge= @merge_request.related_notes.user.count - if @merge_request.source_project %li.commits-tab = link_to commits_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: 'div#commits', action: 'commits', toggle: 'tab' } do -- cgit v1.2.1 From 4bf61b8bd4b04eace6d0f205573f15fc9d981682 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Mon, 12 Dec 2016 08:43:56 +0000 Subject: Merge branch 'jej-24637-move-issue-visible_to_user-to-finder' into 'security' Issue#visible_to_user moved to IssuesFinder Fixes https://gitlab.com/gitlab-org/gitlab-ce/issues/24637. See merge request !2039 --- app/finders/issues_finder.rb | 18 +++++++++++- app/models/concerns/milestoneish.rb | 2 +- app/models/issue.rb | 55 ------------------------------------- 3 files changed, 18 insertions(+), 57 deletions(-) (limited to 'app') diff --git a/app/finders/issues_finder.rb b/app/finders/issues_finder.rb index be00a219205..707eddd4d29 100644 --- a/app/finders/issues_finder.rb +++ b/app/finders/issues_finder.rb @@ -23,10 +23,26 @@ class IssuesFinder < IssuableFinder private def init_collection - Issue.visible_to_user(current_user) + IssuesFinder.not_restricted_by_confidentiality(current_user) end def iid_pattern @iid_pattern ||= %r{\A#{Regexp.escape(Issue.reference_prefix)}(?\d+)\z} end + + def self.not_restricted_by_confidentiality(user) + return Issue.where('issues.confidential IS NULL OR issues.confidential IS FALSE') if user.blank? + + return Issue.all if user.admin? + + Issue.where(' + issues.confidential IS NULL + OR issues.confidential IS FALSE + OR (issues.confidential = TRUE + AND (issues.author_id = :user_id + OR issues.assignee_id = :user_id + OR issues.project_id IN(:project_ids)))', + user_id: user.id, + project_ids: user.authorized_projects(Gitlab::Access::REPORTER).select(:id)) + end end diff --git a/app/models/concerns/milestoneish.rb b/app/models/concerns/milestoneish.rb index 875e9834487..4359f1d7b06 100644 --- a/app/models/concerns/milestoneish.rb +++ b/app/models/concerns/milestoneish.rb @@ -30,7 +30,7 @@ module Milestoneish end def issues_visible_to_user(user) - issues.visible_to_user(user) + IssuesFinder.new(user).execute.where(id: issues) end def upcoming? diff --git a/app/models/issue.rb b/app/models/issue.rb index 7fe92051037..738c96e4db3 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -60,61 +60,6 @@ class Issue < ActiveRecord::Base attributes end - class << self - private - - # Returns the project that the current scope belongs to if any, nil otherwise. - # - # Examples: - # - my_project.issues.without_due_date.owner_project => my_project - # - Issue.all.owner_project => nil - def owner_project - # No owner if we're not being called from an association - return unless all.respond_to?(:proxy_association) - - owner = all.proxy_association.owner - - # Check if the association is or belongs to a project - if owner.is_a?(Project) - owner - else - begin - owner.association(:project).target - rescue ActiveRecord::AssociationNotFoundError - nil - end - end - end - end - - def self.visible_to_user(user) - return where('issues.confidential IS NULL OR issues.confidential IS FALSE') if user.blank? - return all if user.admin? - - # Check if we are scoped to a specific project's issues - if owner_project - if owner_project.team.member?(user, Gitlab::Access::REPORTER) - # If the project is authorized for the user, they can see all issues in the project - return all - else - # else only non confidential and authored/assigned to them - return where('issues.confidential IS NULL OR issues.confidential IS FALSE - OR issues.author_id = :user_id OR issues.assignee_id = :user_id', - user_id: user.id) - end - end - - where(' - issues.confidential IS NULL - OR issues.confidential IS FALSE - OR (issues.confidential = TRUE - AND (issues.author_id = :user_id - OR issues.assignee_id = :user_id - OR issues.project_id IN(:project_ids)))', - user_id: user.id, - project_ids: user.authorized_projects(Gitlab::Access::REPORTER).select(:id)) - end - def self.reference_prefix '#' end -- cgit v1.2.1 From ccea4727a6999d6abaea9e7a43bd1e015e43f1d2 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 15 Dec 2016 15:57:35 +0100 Subject: Fix pipeline detailed status serializer and entities --- app/serializers/pipeline_entity.rb | 9 +++++++-- app/serializers/status_entity.rb | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/serializers/pipeline_entity.rb b/app/serializers/pipeline_entity.rb index e071c03e20b..613a18e6357 100644 --- a/app/serializers/pipeline_entity.rb +++ b/app/serializers/pipeline_entity.rb @@ -4,7 +4,7 @@ class PipelineEntity < Grape::Entity expose :id expose :user, using: UserEntity - expose :url do |pipeline| + expose :path do |pipeline| namespace_project_pipeline_path( pipeline.project.namespace, pipeline.project, @@ -12,7 +12,12 @@ class PipelineEntity < Grape::Entity end expose :details do - expose :detailed_status, as: :status, using: StatusEntity + expose :status do |pipeline, options| + StatusEntity.represent( + pipeline.detailed_status(request.user), + options) + end + expose :duration expose :finished_at expose :stages, using: PipelineStageEntity diff --git a/app/serializers/status_entity.rb b/app/serializers/status_entity.rb index ae14dd57f61..261faa67527 100644 --- a/app/serializers/status_entity.rb +++ b/app/serializers/status_entity.rb @@ -1,7 +1,7 @@ class StatusEntity < Grape::Entity include RequestAwareEntity - expose :icon, :text, :label, :title + expose :icon, :text, :label expose :has_details?, as: :has_details expose :details_path -- cgit v1.2.1 From e63f796ae4c89f3e51eb0e9977add0fe408c1b9e Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Thu, 15 Dec 2016 08:57:48 -0600 Subject: Unify margin widths --- app/assets/stylesheets/pages/editor.scss | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/editor.scss b/app/assets/stylesheets/pages/editor.scss index fea9a6b5009..38d5df9e106 100644 --- a/app/assets/stylesheets/pages/editor.scss +++ b/app/assets/stylesheets/pages/editor.scss @@ -134,15 +134,17 @@ .new-file-name { max-width: none; width: 100%; + margin-bottom: 3px; } .file-buttons { display: block; width: 100%; + margin-bottom: 10px; .soft-wrap-toggle { width: 100%; - margin: 7px 0; + margin: 3px 0; } .encoding-selector, @@ -150,15 +152,12 @@ .gitignore-selector, .gitlab-ci-yml-selector { display: block; - margin: 7px 0; + margin: 3px 0; button { width: 100%; } } - } - } - } -- cgit v1.2.1 From b33fd0ab3d2b40c91effadc92663a9a618422393 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 15 Dec 2016 15:59:18 +0100 Subject: Fix detailed status for pipeline stage entity --- app/serializers/pipeline_stage_entity.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/serializers/pipeline_stage_entity.rb b/app/serializers/pipeline_stage_entity.rb index e4681a0a633..5ef39bafdc1 100644 --- a/app/serializers/pipeline_stage_entity.rb +++ b/app/serializers/pipeline_stage_entity.rb @@ -2,7 +2,11 @@ class PipelineStageEntity < Grape::Entity include RequestAwareEntity expose :name - expose :detailed_status, as: :status, using: StatusEntity + expose :status do |stage, options| + StatusEntity.represent( + stage.detailed_status(request.user), + options) + end expose :path do |stage| namespace_project_pipeline_path( -- cgit v1.2.1 From 1356e40f22c555f676777ed9385a12b09c19fdce Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Thu, 13 Oct 2016 04:33:09 +0100 Subject: Changed autocomplete_sources into an action that returns a single 'at' type of sources at a time Finished up autocomplete_sources action and added frontend to fetch data only when its needed Added wait_for_ajax to specs Fixed builds and improved the setup/destroy lifecycle Changed global namespace and DRYed up loading logic Added safety for accidentally loading data twice Removed destroy as its not necessary and is messing with click events from a blur race condition Created AutocompleteSourcesController and updated routes Fixed @undefined from tabbing before load ends Disable tabSelectsMatch until we have loaded data Review changes --- app/assets/javascripts/gfm_auto_complete.js.es6 | 233 ++++++++++----------- app/assets/javascripts/gl_form.js | 2 +- app/assets/javascripts/issuable_form.js | 2 +- .../projects/autocomplete_sources_controller.rb | 48 +++++ app/controllers/projects_controller.rb | 33 --- app/views/layouts/_init_auto_complete.html.haml | 14 +- 6 files changed, 173 insertions(+), 159 deletions(-) create mode 100644 app/controllers/projects/autocomplete_sources_controller.rb (limited to 'app') diff --git a/app/assets/javascripts/gfm_auto_complete.js.es6 b/app/assets/javascripts/gfm_auto_complete.js.es6 index 245383438d1..dda061a556b 100644 --- a/app/assets/javascripts/gfm_auto_complete.js.es6 +++ b/app/assets/javascripts/gfm_auto_complete.js.es6 @@ -2,19 +2,28 @@ // Creates the variables for setting up GFM auto-completion (function() { - if (window.GitLab == null) { - window.GitLab = {}; + if (window.gl == null) { + window.gl = {}; } function sanitize(str) { return str.replace(/<(?:.|\n)*?>/gm, ''); } - window.GitLab.GfmAutoComplete = { - dataLoading: false, - dataLoaded: false, + window.gl.GfmAutoComplete = { + dataSources: {}, + defaultLoadingData: ['loading'], cachedData: {}, - dataSource: '', + isLoadingData: {}, + atTypeMap: { + ':': 'emojis', + '@': 'members', + '#': 'issues', + '!': 'mergeRequests', + '~': 'labels', + '%': 'milestones', + '/': 'commands' + }, // Emoji Emoji: { template: '
  • ${name} ${name}
  • ' @@ -35,33 +44,31 @@ template: '
  • ${title}
  • ' }, Loading: { - template: '
  • Loading...
  • ' + template: '
  • Loading...
  • ' }, DefaultOptions: { sorter: function(query, items, searchKey) { - // Highlight first item only if at least one char was typed - this.setting.highlightFirst = this.setting.alwaysHighlightFirst || query.length > 0; - if ((items[0].name != null) && items[0].name === 'loading') { + if (gl.GfmAutoComplete.isLoading(items)) { return items; } return $.fn.atwho["default"].callbacks.sorter(query, items, searchKey); }, filter: function(query, data, searchKey) { - if (data[0] === 'loading') { + if (gl.GfmAutoComplete.isLoading(data)) { + gl.GfmAutoComplete.togglePreventSelection.call(this, true); + gl.GfmAutoComplete.fetchData(this.$inputor, this.at); return data; + } else { + gl.GfmAutoComplete.togglePreventSelection.call(this, false); + return $.fn.atwho["default"].callbacks.filter(query, data, searchKey); } - return $.fn.atwho["default"].callbacks.filter(query, data, searchKey); }, beforeInsert: function(value) { if (value && !this.setting.skipSpecialCharacterTest) { var withoutAt = value.substring(1); if (withoutAt && /[^\w\d]/.test(withoutAt)) value = value.charAt() + '"' + withoutAt + '"'; } - if (!window.GitLab.GfmAutoComplete.dataLoaded) { - return this.at; - } else { - return value; - } + return value; }, matcher: function (flag, subtext) { // The below is taken from At.js source @@ -85,69 +92,46 @@ } } }, - setup: _.debounce(function(input) { + setup: function(input) { // Add GFM auto-completion to all input fields, that accept GFM input. this.input = input || $('.js-gfm-input'); - // destroy previous instances - this.destroyAtWho(); - // set up instances - this.setupAtWho(); - - if (this.dataSource && !this.dataLoading && !this.cachedData) { - this.dataLoading = true; - return this.fetchData(this.dataSource) - .done((data) => { - this.dataLoading = false; - this.loadData(data); - }); - }; - - if (this.cachedData != null) { - return this.loadData(this.cachedData); - } - }, 1000), - setupAtWho: function() { + this.setupLifecycle(); + }, + setupLifecycle() { + this.input.each((i, input) => { + const $input = $(input); + $input.off('focus.setupAtWho').on('focus.setupAtWho', this.setupAtWho.bind(this, $input)); + }); + }, + setupAtWho: function($input) { // Emoji - this.input.atwho({ + $input.atwho({ at: ':', - displayTpl: (function(_this) { - return function(value) { - if (value.path != null) { - return _this.Emoji.template; - } else { - return _this.Loading.template; - } - }; - })(this), + displayTpl: function(value) { + return value.path != null ? this.Emoji.template : this.Loading.template; + }.bind(this), insertTpl: ':${name}:', - data: ['loading'], startWithSpace: false, skipSpecialCharacterTest: true, + data: this.defaultLoadingData, callbacks: { sorter: this.DefaultOptions.sorter, - filter: this.DefaultOptions.filter, beforeInsert: this.DefaultOptions.beforeInsert, - matcher: this.DefaultOptions.matcher + filter: this.DefaultOptions.filter } }); // Team Members - this.input.atwho({ + $input.atwho({ at: '@', - displayTpl: (function(_this) { - return function(value) { - if (value.username != null) { - return _this.Members.template; - } else { - return _this.Loading.template; - } - }; - })(this), + displayTpl: function(value) { + return value.username != null ? this.Members.template : this.Loading.template; + }.bind(this), insertTpl: '${atwho-at}${username}', searchKey: 'search', - data: ['loading'], startWithSpace: false, alwaysHighlightFirst: true, skipSpecialCharacterTest: true, + data: this.defaultLoadingData, callbacks: { sorter: this.DefaultOptions.sorter, filter: this.DefaultOptions.filter, @@ -178,20 +162,14 @@ } } }); - this.input.atwho({ + $input.atwho({ at: '#', alias: 'issues', searchKey: 'search', - displayTpl: (function(_this) { - return function(value) { - if (value.title != null) { - return _this.Issues.template; - } else { - return _this.Loading.template; - } - }; - })(this), - data: ['loading'], + displayTpl: function(value) { + return value.title != null ? this.Issues.template : this.Loading.template; + }.bind(this), + data: this.defaultLoadingData, insertTpl: '${atwho-at}${id}', startWithSpace: false, callbacks: { @@ -213,26 +191,21 @@ } } }); - this.input.atwho({ + $input.atwho({ at: '%', alias: 'milestones', searchKey: 'search', - displayTpl: (function(_this) { - return function(value) { - if (value.title != null) { - return _this.Milestones.template; - } else { - return _this.Loading.template; - } - }; - })(this), insertTpl: '${atwho-at}${title}', - data: ['loading'], + displayTpl: function(value) { + return value.title != null ? this.Milestones.template : this.Loading.template; + }.bind(this), startWithSpace: false, + data: this.defaultLoadingData, callbacks: { matcher: this.DefaultOptions.matcher, sorter: this.DefaultOptions.sorter, beforeInsert: this.DefaultOptions.beforeInsert, + filter: this.DefaultOptions.filter, beforeSave: function(milestones) { return $.map(milestones, function(m) { if (m.title == null) { @@ -247,21 +220,15 @@ } } }); - this.input.atwho({ + $input.atwho({ at: '!', alias: 'mergerequests', searchKey: 'search', - displayTpl: (function(_this) { - return function(value) { - if (value.title != null) { - return _this.Issues.template; - } else { - return _this.Loading.template; - } - }; - })(this), - data: ['loading'], startWithSpace: false, + displayTpl: function(value) { + return value.title != null ? this.Issues.template : this.Loading.template; + }.bind(this), + data: this.defaultLoadingData, insertTpl: '${atwho-at}${id}', callbacks: { sorter: this.DefaultOptions.sorter, @@ -282,18 +249,31 @@ } } }); - this.input.atwho({ + $input.atwho({ at: '~', alias: 'labels', searchKey: 'search', - displayTpl: this.Labels.template, + data: this.defaultLoadingData, + displayTpl: function(value) { + return this.isLoading(value) ? this.Loading.template : this.Labels.template; + }.bind(this), insertTpl: '${atwho-at}${title}', startWithSpace: false, callbacks: { matcher: this.DefaultOptions.matcher, sorter: this.DefaultOptions.sorter, beforeInsert: this.DefaultOptions.beforeInsert, + filter: this.DefaultOptions.filter, beforeSave: function(merges) { + if (gl.GfmAutoComplete.isLoading(merges)) return merges; + var sanitizeLabelTitle; + sanitizeLabelTitle = function(title) { + if (/[\w\?&]+\s+[\w\?&]+/g.test(title)) { + return "\"" + (sanitize(title)) + "\""; + } else { + return sanitize(title); + } + }; return $.map(merges, function(m) { return { title: sanitize(m.title), @@ -305,12 +285,14 @@ } }); // We don't instantiate the slash commands autocomplete for note and issue/MR edit forms - this.input.filter('[data-supports-slash-commands="true"]').atwho({ + $input.filter('[data-supports-slash-commands="true"]').atwho({ at: '/', alias: 'commands', searchKey: 'search', skipSpecialCharacterTest: true, + data: this.defaultLoadingData, displayTpl: function(value) { + if (this.isLoading(value)) return this.Loading.template; var tpl = '
  • /${name}'; if (value.aliases.length > 0) { tpl += ' (or /<%- aliases.join(", /") %>)'; @@ -323,7 +305,7 @@ } tpl += '
  • '; return _.template(tpl)(value); - }, + }.bind(this), insertTpl: function(value) { var tpl = "/${name} "; var reference_prefix = null; @@ -341,6 +323,7 @@ filter: this.DefaultOptions.filter, beforeInsert: this.DefaultOptions.beforeInsert, beforeSave: function(commands) { + if (gl.GfmAutoComplete.isLoading(commands)) return commands; return $.map(commands, function(c) { var search = c.name; if (c.aliases.length > 0) { @@ -368,32 +351,40 @@ }); return; }, - destroyAtWho: function() { - return this.input.atwho('destroy'); - }, - fetchData: function(dataSource) { - return $.getJSON(dataSource); + fetchData: function($input, at) { + if (this.isLoadingData[at]) return; + this.isLoadingData[at] = true; + if (this.cachedData[at]) { + this.loadData($input, at, this.cachedData[at]); + } else { + $.getJSON(this.dataSources[this.atTypeMap[at]], (data) => { + this.loadData($input, at, data); + }).fail(() => { this.isLoadingData[at] = false; }); + } }, - loadData: function(data) { - this.cachedData = data; - this.dataLoaded = true; - // load members - this.input.atwho('load', '@', data.members); - // load issues - this.input.atwho('load', 'issues', data.issues); - // load milestones - this.input.atwho('load', 'milestones', data.milestones); - // load merge requests - this.input.atwho('load', 'mergerequests', data.mergerequests); - // load emojis - this.input.atwho('load', ':', data.emojis); - // load labels - this.input.atwho('load', '~', data.labels); - // load commands - this.input.atwho('load', '/', data.commands); + loadData: function($input, at, data) { + this.isLoadingData[at] = false; + this.cachedData[at] = data; + $input.atwho('load', at, data); // This trigger at.js again // otherwise we would be stuck with loading until the user types - return $(':focus').trigger('keyup'); + return $input.trigger('keyup'); + }, + isLoading(data) { + if (!data) return false; + if (Array.isArray(data)) data = data[0]; + return data === this.defaultLoadingData[0] || data.name === this.defaultLoadingData[0]; + }, + togglePreventSelection(isPrevented = !!this.setting.tabSelectsMatch) { + this.setting.tabSelectsMatch = !isPrevented; + this.setting.spaceSelectsMatch = !isPrevented; + const eventListenerAction = `${isPrevented ? 'add' : 'remove'}EventListener`; + this.$inputor[0][eventListenerAction]('keydown', gl.GfmAutoComplete.preventSpaceTabEnter); + }, + preventSpaceTabEnter(e) { + const key = e.which || e.keyCode; + const preventables = [9, 13, 32]; + if (preventables.indexOf(key) > -1) e.preventDefault(); } }; diff --git a/app/assets/javascripts/gl_form.js b/app/assets/javascripts/gl_form.js index 56a33eeaad5..7dc2d13e5d8 100644 --- a/app/assets/javascripts/gl_form.js +++ b/app/assets/javascripts/gl_form.js @@ -30,7 +30,7 @@ this.form.addClass('gfm-form'); // remove notify commit author checkbox for non-commit notes gl.utils.disableButtonIfEmptyField(this.form.find('.js-note-text'), this.form.find('.js-comment-button')); - GitLab.GfmAutoComplete.setup(this.form.find('.js-gfm-input')); + gl.GfmAutoComplete.setup(this.form.find('.js-gfm-input')); new DropzoneInput(this.form); autosize(this.textarea); // form and textarea event listeners diff --git a/app/assets/javascripts/issuable_form.js b/app/assets/javascripts/issuable_form.js index 2f3cad13cc0..1c4086517fe 100644 --- a/app/assets/javascripts/issuable_form.js +++ b/app/assets/javascripts/issuable_form.js @@ -19,7 +19,7 @@ this.renderWipExplanation = bind(this.renderWipExplanation, this); this.resetAutosave = bind(this.resetAutosave, this); this.handleSubmit = bind(this.handleSubmit, this); - GitLab.GfmAutoComplete.setup(); + gl.GfmAutoComplete.setup(); new UsersSelect(); new ZenMode(); this.titleField = this.form.find("input[name*='[title]']"); diff --git a/app/controllers/projects/autocomplete_sources_controller.rb b/app/controllers/projects/autocomplete_sources_controller.rb new file mode 100644 index 00000000000..d9dfa534669 --- /dev/null +++ b/app/controllers/projects/autocomplete_sources_controller.rb @@ -0,0 +1,48 @@ +class Projects::AutocompleteSourcesController < Projects::ApplicationController + before_action :load_autocomplete_service, except: [:emojis, :members] + + def emojis + render json: Gitlab::AwardEmoji.urls + end + + def members + render json: ::Projects::ParticipantsService.new(@project, current_user).execute(noteable) + end + + def issues + render json: @autocomplete_service.issues + end + + def merge_requests + render json: @autocomplete_service.merge_requests + end + + def labels + render json: @autocomplete_service.labels + end + + def milestones + render json: @autocomplete_service.milestones + end + + def commands + render json: @autocomplete_service.commands(noteable, params[:type]) + end + + private + + def load_autocomplete_service + @autocomplete_service = ::Projects::AutocompleteService.new(@project, current_user) + end + + def noteable + case params[:type] + when 'Issue' + IssuesFinder.new(current_user, project_id: @project.id).execute.find_by(iid: params[:type_id]) + when 'MergeRequest' + MergeRequestsFinder.new(current_user, project_id: @project.id).execute.find_by(iid: params[:type_id]) + when 'Commit' + @project.commit(params[:type_id]) + end + end +end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index a8a18b4fa16..d5ee503c44c 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -127,39 +127,6 @@ class ProjectsController < Projects::ApplicationController redirect_to edit_project_path(@project), alert: ex.message end - def autocomplete_sources - noteable = - case params[:type] - when 'Issue' - IssuesFinder.new(current_user, project_id: @project.id). - execute.find_by(iid: params[:type_id]) - when 'MergeRequest' - MergeRequestsFinder.new(current_user, project_id: @project.id). - execute.find_by(iid: params[:type_id]) - when 'Commit' - @project.commit(params[:type_id]) - else - nil - end - - autocomplete = ::Projects::AutocompleteService.new(@project, current_user) - participants = ::Projects::ParticipantsService.new(@project, current_user).execute(noteable) - - @suggestions = { - emojis: Gitlab::AwardEmoji.urls, - issues: autocomplete.issues, - milestones: autocomplete.milestones, - mergerequests: autocomplete.merge_requests, - labels: autocomplete.labels, - members: participants, - commands: autocomplete.commands(noteable, params[:type]) - } - - respond_to do |format| - format.json { render json: @suggestions } - end - end - def new_issue_address return render_404 unless Gitlab::IncomingEmail.supports_issue_creation? diff --git a/app/views/layouts/_init_auto_complete.html.haml b/app/views/layouts/_init_auto_complete.html.haml index e138ebab018..3daa1e90a8c 100644 --- a/app/views/layouts/_init_auto_complete.html.haml +++ b/app/views/layouts/_init_auto_complete.html.haml @@ -3,6 +3,14 @@ - if project :javascript - GitLab.GfmAutoComplete.dataSource = "#{autocomplete_sources_namespace_project_path(project.namespace, project, type: noteable_type, type_id: params[:id])}" - GitLab.GfmAutoComplete.cachedData = undefined; - GitLab.GfmAutoComplete.setup(); + gl.GfmAutoComplete.dataSources = { + emojis: "#{emojis_namespace_project_autocomplete_sources_path(project.namespace, project)}", + members: "#{members_namespace_project_autocomplete_sources_path(project.namespace, project, type: noteable_type, type_id: params[:id])}", + issues: "#{issues_namespace_project_autocomplete_sources_path(project.namespace, project)}", + mergeRequests: "#{merge_requests_namespace_project_autocomplete_sources_path(project.namespace, project)}", + labels: "#{labels_namespace_project_autocomplete_sources_path(project.namespace, project)}", + milestones: "#{milestones_namespace_project_autocomplete_sources_path(project.namespace, project)}", + commands: "#{commands_namespace_project_autocomplete_sources_path(project.namespace, project, type: noteable_type, type_id: params[:id])}" + }; + + gl.GfmAutoComplete.setup(); -- cgit v1.2.1 From 438199a50db495fedfd857d844f65947cd8ec6d2 Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 15 Dec 2016 09:27:57 -0700 Subject: camel case changepage and make span an a tag --- app/assets/javascripts/vue_pagination/index.js.es6 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pagination/index.js.es6 b/app/assets/javascripts/vue_pagination/index.js.es6 index f0f0b54dd2b..b1de0faade8 100644 --- a/app/assets/javascripts/vue_pagination/index.js.es6 +++ b/app/assets/javascripts/vue_pagination/index.js.es6 @@ -17,7 +17,7 @@ 'pageInfo', ], methods: { - changepage(e) { + changePage(e) { let pagenum = this.pageInfo.page; let apiScope = gl.getParameterByName('scope'); @@ -91,11 +91,11 @@ disabled: item.disabled }' > - {{item.title}} - +
      +
    1. Enable incoming webhooks in your Mattermost installation.
    2. +
    3. Add an incoming webhook in your Mattermost team. The default channel can be overridden for each event.
    4. +
    5. Paste the webhook URL into the field bellow.
    6. +
    7. Select events below to enable notifications. The channel and username are optional.
    8. +
    -- cgit v1.2.1 From 192d003ad1e33c09eab24fdf145c733a23ba94aa Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 15 Dec 2016 09:30:44 -0700 Subject: add comment about complex regex in pagination --- app/assets/javascripts/vue_pagination/index.js.es6 | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app') diff --git a/app/assets/javascripts/vue_pagination/index.js.es6 b/app/assets/javascripts/vue_pagination/index.js.es6 index b1de0faade8..db9b81065cc 100644 --- a/app/assets/javascripts/vue_pagination/index.js.es6 +++ b/app/assets/javascripts/vue_pagination/index.js.es6 @@ -27,6 +27,8 @@ const { totalPages, nextPage, previousPage } = this.pageInfo; if (text === SPREAD) return; + // the regex here is to read if the string coming in will become a valid string + // had issues with parsing using `+` because `typeof NaN === 'number'` if (/^-?[\d.]+(?:e-?\d+)?$/.test(text)) pagenum = +text; if (text === LAST) pagenum = totalPages; if (text === NEXT) pagenum = nextPage; -- cgit v1.2.1 From 0dcd30b4a8ea9a10f2db6506c91bcf005a697186 Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 15 Dec 2016 09:33:46 -0700 Subject: fix comment formatting --- app/assets/javascripts/vue_pagination/index.js.es6 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pagination/index.js.es6 b/app/assets/javascripts/vue_pagination/index.js.es6 index db9b81065cc..872c2b11a11 100644 --- a/app/assets/javascripts/vue_pagination/index.js.es6 +++ b/app/assets/javascripts/vue_pagination/index.js.es6 @@ -27,8 +27,10 @@ const { totalPages, nextPage, previousPage } = this.pageInfo; if (text === SPREAD) return; - // the regex here is to read if the string coming in will become a valid string - // had issues with parsing using `+` because `typeof NaN === 'number'` + /** + the regex here is to read if the string coming in will become a valid number + had issues with parsing using `+` because `typeof NaN === 'number'` + */ if (/^-?[\d.]+(?:e-?\d+)?$/.test(text)) pagenum = +text; if (text === LAST) pagenum = totalPages; if (text === NEXT) pagenum = nextPage; -- cgit v1.2.1 From 0380fdb4206fb0c589a40adda1e1c72520e35394 Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 15 Dec 2016 09:40:40 -0700 Subject: cache timeAgo object --- app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 b/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 index 33a1744fa82..be3cd41594c 100644 --- a/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 @@ -11,6 +11,9 @@ 'pipeline', ], computed: { + timeAgo() { + return gl.utils.getTimeago(); + }, localTimeFinished() { return gl.utils.formatDate(this.pipeline.details.finished_at); }, @@ -25,7 +28,7 @@ options.timeZoneName = 'short'; const finished = this.pipeline.details.finished_at; if (!finished && changeTime) return false; - return ({ words: gl.utils.getTimeago().format(finished) }); + return ({ words: this.timeAgo.format(finished) }); }, }, methods: { -- cgit v1.2.1 From 696864eacd88f771839b24a0ceb34cbd346048d1 Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 15 Dec 2016 10:00:30 -0700 Subject: remove need for complex regex in pagination - add else if --- app/assets/javascripts/vue_pagination/index.js.es6 | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pagination/index.js.es6 b/app/assets/javascripts/vue_pagination/index.js.es6 index 872c2b11a11..54c7ae9b510 100644 --- a/app/assets/javascripts/vue_pagination/index.js.es6 +++ b/app/assets/javascripts/vue_pagination/index.js.es6 @@ -26,16 +26,23 @@ const text = e.target.innerText; const { totalPages, nextPage, previousPage } = this.pageInfo; - if (text === SPREAD) return; /** the regex here is to read if the string coming in will become a valid number had issues with parsing using `+` because `typeof NaN === 'number'` */ - if (/^-?[\d.]+(?:e-?\d+)?$/.test(text)) pagenum = +text; - if (text === LAST) pagenum = totalPages; - if (text === NEXT) pagenum = nextPage; - if (text === PREV) pagenum = previousPage; - if (text === FIRST) pagenum = 1; + if (text === SPREAD) { + return; + } else if (text === LAST) { + pagenum = totalPages; + } else if (text === NEXT) { + pagenum = nextPage; + } else if (text === PREV) { + pagenum = previousPage; + } else if (text === FIRST) { + pagenum = 1; + } else { + pagenum = +text; + } this.change(pagenum, apiScope); }, -- cgit v1.2.1 From 5151b15c71d9d9805b060f4f47c00c4f72516296 Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 15 Dec 2016 10:04:26 -0700 Subject: comments on turbolinks event handling --- app/assets/javascripts/vue_pagination/index.js.es6 | 4 ---- app/assets/javascripts/vue_pipelines_index/store.js.es6 | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pagination/index.js.es6 b/app/assets/javascripts/vue_pagination/index.js.es6 index 54c7ae9b510..25d1af664b3 100644 --- a/app/assets/javascripts/vue_pagination/index.js.es6 +++ b/app/assets/javascripts/vue_pagination/index.js.es6 @@ -26,10 +26,6 @@ const text = e.target.innerText; const { totalPages, nextPage, previousPage } = this.pageInfo; - /** - the regex here is to read if the string coming in will become a valid number - had issues with parsing using `+` because `typeof NaN === 'number'` - */ if (text === SPREAD) { return; } else if (text === LAST) { diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index 7d8316d6d20..619fd094996 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -63,12 +63,16 @@ window.removeEventListener('beforeunload', () => {}); window.removeEventListener('focus', () => {}); window.removeEventListener('blur', () => {}); + + // turbolinks event handler document.removeEventListener('page:fetch', () => {}); }; window.addEventListener('beforeunload', removeTimeIntervals); window.addEventListener('focus', startIntervalLoops); window.addEventListener('blur', removeTimeIntervals); + + // turbolinks event handler document.addEventListener('page:fetch', removeAll); } }; -- cgit v1.2.1 From 3f21b9573313445b18df999b554e002bc05635c2 Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 15 Dec 2016 10:12:39 -0700 Subject: change to 'Latest pipeline for this branch' --- app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 index 99ecdf3fed0..bf24392b82f 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 @@ -40,7 +40,7 @@ v-if='pipeline.flags.latest === true' class="label label-success has-tooltip" title="" - data-original-title="Latest build for this branch" + data-original-title="Latest pipeline for this branch" > latest -- cgit v1.2.1 From 2dfb7e882626f41d3a1b5b4c2e30038079c7a1bc Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 15 Dec 2016 10:21:45 -0700 Subject: pageNum is now camelCased --- app/assets/javascripts/vue_pagination/index.js.es6 | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pagination/index.js.es6 b/app/assets/javascripts/vue_pagination/index.js.es6 index 25d1af664b3..712fa8442bc 100644 --- a/app/assets/javascripts/vue_pagination/index.js.es6 +++ b/app/assets/javascripts/vue_pagination/index.js.es6 @@ -18,7 +18,7 @@ ], methods: { changePage(e) { - let pagenum = this.pageInfo.page; + let pageNum = this.pageInfo.page; let apiScope = gl.getParameterByName('scope'); if (!apiScope) apiScope = 'all'; @@ -29,18 +29,18 @@ if (text === SPREAD) { return; } else if (text === LAST) { - pagenum = totalPages; + pageNum = totalPages; } else if (text === NEXT) { - pagenum = nextPage; + pageNum = nextPage; } else if (text === PREV) { - pagenum = previousPage; + pageNum = previousPage; } else if (text === FIRST) { - pagenum = 1; + pageNum = 1; } else { - pagenum = +text; + pageNum = +text; } - this.change(pagenum, apiScope); + this.change(pageNum, apiScope); }, }, computed: { -- cgit v1.2.1 From 40f433125e5747deb434e17669127cde250a6585 Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 15 Dec 2016 10:28:17 -0700 Subject: strict props for easier re-use --- app/assets/javascripts/vue_pagination/index.js.es6 | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pagination/index.js.es6 b/app/assets/javascripts/vue_pagination/index.js.es6 index 712fa8442bc..54407c5ceef 100644 --- a/app/assets/javascripts/vue_pagination/index.js.es6 +++ b/app/assets/javascripts/vue_pagination/index.js.es6 @@ -12,10 +12,16 @@ const LAST = 'Last >>'; gl.VueGlPagination = Vue.extend({ - props: [ - 'change', - 'pageInfo', - ], + props: { + change: { + type: Function, + required: true, + }, + pageInfo: { + type: Object, + required: true, + }, + }, methods: { changePage(e) { let pageNum = this.pageInfo.page; -- cgit v1.2.1 From 4ae28cb31d9f0915aac647e1befa61067b6932f1 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Thu, 15 Dec 2016 17:30:49 +0000 Subject: Changes after review --- app/assets/stylesheets/pages/pipelines.scss | 10 +--------- app/views/ci/status/_graph_badge.html.haml | 5 +++-- 2 files changed, 4 insertions(+), 11 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index d3f39570f11..be22e7bdc79 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -645,14 +645,6 @@ margin-bottom: 0; line-height: 1.2; } - - li:first-child { - padding-top: 6px; - } - - li:last-child { - padding-bottom: 6px; - } } .dropdown-build { @@ -741,4 +733,4 @@ .ci-play-icon { padding: 5px 5px 5px 7px; } -} \ No newline at end of file +} diff --git a/app/views/ci/status/_graph_badge.html.haml b/app/views/ci/status/_graph_badge.html.haml index a7e8544e7d4..df1b763e67c 100644 --- a/app/views/ci/status/_graph_badge.html.haml +++ b/app/views/ci/status/_graph_badge.html.haml @@ -3,9 +3,10 @@ - subject = local_assigns.fetch(:subject) - status = subject.detailed_status(current_user) - klass = "ci-status-icon ci-status-icon-#{status}" +- tooltip_title = "#{subject.name} - #{status.label}" - if status.has_details? - = link_to status.details_path, data: { toggle: 'tooltip', title: "#{subject.name} - #{status}" } do + = link_to status.details_path, data: { toggle: 'tooltip', title: tooltip_title } do %span{ class: klass }= custom_icon(status.icon) .ci-status-text= subject.name - else @@ -14,6 +15,6 @@ - if status.has_action? = link_to status.action_path, method: status.action_method, - title: "#{subject.name}: #{status.action_title}", class: 'ci-action-icon-container' do + title: tooltip_title, class: 'ci-action-icon-container' do %i.ci-action-icon-wrapper = icon(status.action_icon, class: status.action_class) -- cgit v1.2.1 From 9eed507dafbfdd09fcd51b970d633ba0fd764d78 Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 15 Dec 2016 10:32:44 -0700 Subject: add examples of what the props need to be --- app/assets/javascripts/vue_pagination/index.js.es6 | 35 ++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'app') diff --git a/app/assets/javascripts/vue_pagination/index.js.es6 b/app/assets/javascripts/vue_pagination/index.js.es6 index 54407c5ceef..3889e6d6d28 100644 --- a/app/assets/javascripts/vue_pagination/index.js.es6 +++ b/app/assets/javascripts/vue_pagination/index.js.es6 @@ -13,10 +13,45 @@ gl.VueGlPagination = Vue.extend({ props: { + + /** + This function will take the information given by the pagination component + And make a new API call from the parent + + Here is an example `change` method: + + change(pagenum, apiScope) { + window.history.pushState({}, null, `?scope=${apiScope}&p=${pagenum}`); + clearInterval(this.timeLoopInterval); + this.pageRequest = true; + this.store.fetchDataLoop.call(this, Vue, pagenum, this.scope, apiScope); + }, + */ + change: { type: Function, required: true, }, + + /** + pageInfo will come from the headers of the API call + in the `.then` clause of the VueResource API call + there should be a function that contructs the pageInfo for this component + + This is an example: + + const pageInfo = (headers) => { + const values = {}; + values.perPage = +headers['X-Per-Page']; + values.page = +headers['X-Page']; + values.total = +headers['X-Total']; + values.totalPages = +headers['X-Total-Pages']; + values.nextPage = +headers['X-Next-Page']; + values.previousPage = +headers['X-Prev-Page']; + return values; + }; + */ + pageInfo: { type: Object, required: true, -- cgit v1.2.1 From a5ccaded656fb215f1f8d503b88c8f28bf90ce68 Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Tue, 6 Dec 2016 15:59:03 -0200 Subject: Change SlackService to SlackNotificationsService --- app/models/project.rb | 4 +- .../project_services/chat_notification_service.rb | 147 +++++++++++++++++++++ app/models/project_services/chat_service.rb | 143 ++------------------ .../mattermost_notification_service.rb | 41 ++++++ app/models/project_services/mattermost_service.rb | 41 ------ .../mattermost_slash_commands_service.rb | 12 +- .../project_services/slack_notification_service.rb | 40 ++++++ app/models/project_services/slack_service.rb | 40 ------ app/models/service.rb | 4 +- 9 files changed, 241 insertions(+), 231 deletions(-) create mode 100644 app/models/project_services/chat_notification_service.rb create mode 100644 app/models/project_services/mattermost_notification_service.rb delete mode 100644 app/models/project_services/mattermost_service.rb create mode 100644 app/models/project_services/slack_notification_service.rb delete mode 100644 app/models/project_services/slack_service.rb (limited to 'app') diff --git a/app/models/project.rb b/app/models/project.rb index 19c2d24212d..5d092ca42c2 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -95,8 +95,8 @@ class Project < ActiveRecord::Base has_one :asana_service, dependent: :destroy has_one :gemnasium_service, dependent: :destroy has_one :mattermost_slash_commands_service, dependent: :destroy - has_one :mattermost_service, dependent: :destroy - has_one :slack_service, dependent: :destroy + has_one :mattermost_notification_service, dependent: :destroy + has_one :slack_notification_service, dependent: :destroy has_one :buildkite_service, dependent: :destroy has_one :bamboo_service, dependent: :destroy has_one :teamcity_service, dependent: :destroy diff --git a/app/models/project_services/chat_notification_service.rb b/app/models/project_services/chat_notification_service.rb new file mode 100644 index 00000000000..b0556987721 --- /dev/null +++ b/app/models/project_services/chat_notification_service.rb @@ -0,0 +1,147 @@ +# Base class for Chat notifications services +# This class is not meant to be used directly, but only to inherit from. +class ChatNotificationService < Service + include ChatMessage + + default_value_for :category, 'chat' + + prop_accessor :webhook, :username, :channel + boolean_accessor :notify_only_broken_builds, :notify_only_broken_pipelines + + validates :webhook, presence: true, url: true, if: :activated? + + def initialize_properties + # Custom serialized properties initialization + self.supported_events.each { |event| self.class.prop_accessor(event_channel_name(event)) } + + if properties.nil? + self.properties = {} + self.notify_only_broken_builds = true + self.notify_only_broken_pipelines = true + end + end + + def can_test? + valid? + end + + def supported_events + %w[push issue confidential_issue merge_request note tag_push + build pipeline wiki_page] + end + + def execute(data) + return unless supported_events.include?(data[:object_kind]) + return unless webhook.present? + + object_kind = data[:object_kind] + + data = data.merge( + project_url: project_url, + project_name: project_name + ) + + # WebHook events often have an 'update' event that follows a 'open' or + # 'close' action. Ignore update events for now to prevent duplicate + # messages from arriving. + + message = get_message(object_kind, data) + + return false unless message + + opt = {} + + opt[:channel] = get_channel_field(object_kind).presence || channel || default_channel + opt[:username] = username if username + notifier = Slack::Notifier.new(webhook, opt) + notifier.ping(message.pretext, attachments: message.attachments, fallback: message.fallback) + + true + end + + def event_channel_names + supported_events.map { |event| event_channel_name(event) } + end + + def event_field(event) + fields.find { |field| field[:name] == event_channel_name(event) } + end + + def global_fields + fields.reject { |field| field[:name].end_with?('channel') } + end + + def default_channel + raise NotImplementedError + end + + private + + def get_message(object_kind, data) + case object_kind + when "push", "tag_push" + PushMessage.new(data) + when "issue" + IssueMessage.new(data) unless is_update?(data) + when "merge_request" + MergeMessage.new(data) unless is_update?(data) + when "note" + NoteMessage.new(data) + when "build" + BuildMessage.new(data) if should_build_be_notified?(data) + when "pipeline" + PipelineMessage.new(data) if should_pipeline_be_notified?(data) + when "wiki_page" + WikiPageMessage.new(data) + end + end + + def get_channel_field(event) + field_name = event_channel_name(event) + self.public_send(field_name) + end + + def build_event_channels + supported_events.reduce([]) do |channels, event| + channels << { type: 'text', name: event_channel_name(event), placeholder: default_channel } + end + end + + def event_channel_name(event) + "#{event}_channel" + end + + def project_name + project.name_with_namespace.gsub(/\s/, '') + end + + def project_url + project.web_url + end + + def is_update?(data) + data[:object_attributes][:action] == 'update' + end + + def should_build_be_notified?(data) + case data[:commit][:status] + when 'success' + !notify_only_broken_builds? + when 'failed' + true + else + false + end + end + + def should_pipeline_be_notified?(data) + case data[:object_attributes][:status] + when 'success' + !notify_only_broken_pipelines? + when 'failed' + true + else + false + end + end +end diff --git a/app/models/project_services/chat_service.rb b/app/models/project_services/chat_service.rb index 8ac049ba939..574788462de 100644 --- a/app/models/project_services/chat_service.rb +++ b/app/models/project_services/chat_service.rb @@ -1,148 +1,21 @@ # Base class for Chat services -# This class is not meant to be used directly, but only to inherrit from. +# This class is not meant to be used directly, but only to inherit from. class ChatService < Service - include ChatMessage - default_value_for :category, 'chat' - prop_accessor :webhook, :username, :channel - boolean_accessor :notify_only_broken_builds, :notify_only_broken_pipelines - - validates :webhook, presence: true, url: true, if: :activated? - - def initialize_properties - # Custom serialized properties initialization - self.supported_events.each { |event| self.class.prop_accessor(event_channel_name(event)) } + has_many :chat_names, foreign_key: :service_id - if properties.nil? - self.properties = {} - self.notify_only_broken_builds = true - self.notify_only_broken_pipelines = true - end - end - - def can_test? - valid? + def valid_token?(token) + self.respond_to?(:token) && + self.token.present? && + ActiveSupport::SecurityUtils.variable_size_secure_compare(token, self.token) end def supported_events - %w[push issue confidential_issue merge_request note tag_push - build pipeline wiki_page] + [] end - def execute(data) - return unless supported_events.include?(data[:object_kind]) - return unless webhook.present? - - object_kind = data[:object_kind] - - data = data.merge( - project_url: project_url, - project_name: project_name - ) - - # WebHook events often have an 'update' event that follows a 'open' or - # 'close' action. Ignore update events for now to prevent duplicate - # messages from arriving. - - message = get_message(object_kind, data) - - return false unless message - - opt = {} - - opt[:channel] = get_channel_field(object_kind).presence || channel || default_channel - opt[:username] = username if username - - notifier = Slack::Notifier.new(webhook, opt) - notifier.ping(message.pretext, attachments: message.attachments, fallback: message.fallback) - - true - end - - def event_channel_names - supported_events.map { |event| event_channel_name(event) } - end - - def event_field(event) - fields.find { |field| field[:name] == event_channel_name(event) } - end - - def global_fields - fields.reject { |field| field[:name].end_with?('channel') } - end - - def default_channel + def trigger(params) raise NotImplementedError end - - private - - def get_message(object_kind, data) - case object_kind - when "push", "tag_push" - PushMessage.new(data) - when "issue" - IssueMessage.new(data) unless is_update?(data) - when "merge_request" - MergeMessage.new(data) unless is_update?(data) - when "note" - NoteMessage.new(data) - when "build" - BuildMessage.new(data) if should_build_be_notified?(data) - when "pipeline" - PipelineMessage.new(data) if should_pipeline_be_notified?(data) - when "wiki_page" - WikiPageMessage.new(data) - end - end - - def get_channel_field(event) - field_name = event_channel_name(event) - self.public_send(field_name) - end - - def build_event_channels - supported_events.reduce([]) do |channels, event| - channels << { type: 'text', name: event_channel_name(event), placeholder: default_channel } - end - end - - def event_channel_name(event) - "#{event}_channel" - end - - def project_name - project.name_with_namespace.gsub(/\s/, '') - end - - def project_url - project.web_url - end - - def is_update?(data) - data[:object_attributes][:action] == 'update' - end - - def should_build_be_notified?(data) - case data[:commit][:status] - when 'success' - !notify_only_broken_builds? - when 'failed' - true - else - false - end - end - - def should_pipeline_be_notified?(data) - case data[:object_attributes][:status] - when 'success' - !notify_only_broken_pipelines? - when 'failed' - true - else - false - end - end end diff --git a/app/models/project_services/mattermost_notification_service.rb b/app/models/project_services/mattermost_notification_service.rb new file mode 100644 index 00000000000..de18c4b1f00 --- /dev/null +++ b/app/models/project_services/mattermost_notification_service.rb @@ -0,0 +1,41 @@ +class MattermostNotificationService < ChatNotificationService + def title + 'Mattermost notifications' + end + + def description + 'Receive event notifications in Mattermost' + end + + def to_param + 'mattermost_notification' + end + + def help + 'This service sends notifications about projects events to Mattermost channels.
    + To set up this service: +
      +
    1. Enable incoming webhooks in your Mattermost installation.
    2. +
    3. Add an incoming webhook in your Mattermost team. The default channel can be overridden for each event.
    4. +
    5. Paste the webhook URL into the field bellow.
    6. +
    7. Select events below to enable notifications. The channel and username are optional.
    8. +
    ' + end + + def fields + default_fields + build_event_channels + end + + def default_fields + [ + { type: 'text', name: 'webhook', placeholder: 'http://mattermost_host/hooks/...' }, + { type: 'text', name: 'username', placeholder: 'username' }, + { type: 'checkbox', name: 'notify_only_broken_builds' }, + { type: 'checkbox', name: 'notify_only_broken_pipelines' }, + ] + end + + def default_channel + "#town-square" + end +end diff --git a/app/models/project_services/mattermost_service.rb b/app/models/project_services/mattermost_service.rb deleted file mode 100644 index 9d61c251a32..00000000000 --- a/app/models/project_services/mattermost_service.rb +++ /dev/null @@ -1,41 +0,0 @@ -class MattermostService < ChatService - def title - 'Mattermost notifications' - end - - def description - 'Receive event notifications in Mattermost' - end - - def to_param - 'mattermost' - end - - def help - 'This service sends notifications about projects events to Mattermost channels.
    - To set up this service: -
      -
    1. Enable incoming webhooks in your Mattermost installation.
    2. -
    3. Add an incoming webhook in your Mattermost team. The default channel can be overridden for each event.
    4. -
    5. Paste the webhook URL into the field bellow.
    6. -
    7. Select events below to enable notifications. The channel and username are optional.
    8. -
    ' - end - - def fields - default_fields + build_event_channels - end - - def default_fields - [ - { type: 'text', name: 'webhook', placeholder: 'http://mattermost_host/hooks/...' }, - { type: 'text', name: 'username', placeholder: 'username' }, - { type: 'checkbox', name: 'notify_only_broken_builds' }, - { type: 'checkbox', name: 'notify_only_broken_pipelines' }, - ] - end - - def default_channel - "#town-square" - end -end diff --git a/app/models/project_services/mattermost_slash_commands_service.rb b/app/models/project_services/mattermost_slash_commands_service.rb index 3993dfbda17..33431f41dc2 100644 --- a/app/models/project_services/mattermost_slash_commands_service.rb +++ b/app/models/project_services/mattermost_slash_commands_service.rb @@ -1,18 +1,8 @@ -class MattermostSlashCommandsService < Service +class MattermostSlashCommandsService < ChatService include TriggersHelper prop_accessor :token - def valid_token?(token) - self.respond_to?(:token) && - self.token.present? && - ActiveSupport::SecurityUtils.variable_size_secure_compare(token, self.token) - end - - def supported_events - [] - end - def can_test? false end diff --git a/app/models/project_services/slack_notification_service.rb b/app/models/project_services/slack_notification_service.rb new file mode 100644 index 00000000000..3cbf89efba4 --- /dev/null +++ b/app/models/project_services/slack_notification_service.rb @@ -0,0 +1,40 @@ +class SlackNotificationService < ChatNotificationService + def title + 'Slack notifications' + end + + def description + 'Receive event notifications in Slack' + end + + def to_param + 'slack_notification' + end + + def help + 'This service sends notifications about projects events to Slack channels.
    + To setup this service: +
      +
    1. Add an incoming webhook in your Slack team. The default channel can be overridden for each event.
    2. +
    3. Paste the Webhook URL into the field below.
    4. +
    5. Select events below to enable notifications. The channel and username are optional.
    6. +
    ' + end + + def fields + default_fields + build_event_channels + end + + def default_fields + [ + { type: 'text', name: 'webhook', placeholder: 'https://hooks.slack.com/services/...' }, + { type: 'text', name: 'username', placeholder: 'username' }, + { type: 'checkbox', name: 'notify_only_broken_builds' }, + { type: 'checkbox', name: 'notify_only_broken_pipelines' }, + ] + end + + def default_channel + "#general" + end +end diff --git a/app/models/project_services/slack_service.rb b/app/models/project_services/slack_service.rb deleted file mode 100644 index 0df1743c4ba..00000000000 --- a/app/models/project_services/slack_service.rb +++ /dev/null @@ -1,40 +0,0 @@ -class SlackService < ChatService - def title - 'Slack notifications' - end - - def description - 'Receive event notifications in Slack' - end - - def to_param - 'slack' - end - - def help - 'This service sends notifications about projects events to Slack channels.
    - To setup this service: -
      -
    1. Add an incoming webhook in your Slack team. The default channel can be overridden for each event.
    2. -
    3. Paste the Webhook URL into the field below.
    4. -
    5. Select events below to enable notifications. The channel and username are optional.
    6. -
    ' - end - - def fields - default_fields + build_event_channels - end - - def default_fields - [ - { type: 'text', name: 'webhook', placeholder: 'https://hooks.slack.com/services/...' }, - { type: 'text', name: 'username', placeholder: 'username' }, - { type: 'checkbox', name: 'notify_only_broken_builds' }, - { type: 'checkbox', name: 'notify_only_broken_pipelines' }, - ] - end - - def default_channel - "#general" - end -end diff --git a/app/models/service.rb b/app/models/service.rb index 8e58f2a1925..0bbab078cf6 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -220,8 +220,8 @@ class Service < ActiveRecord::Base pivotaltracker pushover redmine - mattermost - slack + mattermost_notification + slack_notification teamcity ] end -- cgit v1.2.1 From 82f9957d466810314b8f3af672bcdd706905007a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 13 Dec 2016 20:49:25 +0200 Subject: Refactor Namespace#parents method Signed-off-by: Dmitriy Zaporozhets --- app/models/namespace.rb | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'app') diff --git a/app/models/namespace.rb b/app/models/namespace.rb index b3cefc01b99..3830379be3e 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -172,17 +172,7 @@ class Namespace < ActiveRecord::Base end def parents - @parents ||= - begin - parents = [] - - if parent - parents << parent - parents += parent.parents - end - - parents - end + @parents ||= parent ? parent.parents + [parent] : [] end private -- cgit v1.2.1 From 24d2e662d4251ed8c73a57319576af6de3d488a1 Mon Sep 17 00:00:00 2001 From: tauriedavis Date: Fri, 2 Dec 2016 12:38:04 -0800 Subject: Limit description container for mrs while viewing side by side diff --- app/assets/stylesheets/framework/variables.scss | 3 +- app/assets/stylesheets/pages/issuable.scss | 52 ++++++++++++++++++----- app/assets/stylesheets/pages/notes.scss | 4 -- app/views/projects/merge_requests/_show.html.haml | 2 +- 4 files changed, 44 insertions(+), 17 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 55d97b9219c..13abe6033b2 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -166,8 +166,7 @@ $row-hover-border: #b2d7ff; $progress-color: #c0392b; $header-height: 50px; $fixed-layout-width: 1280px; -$limited-layout-width: 958px; -$line-length-width: 700px; +$limited-layout-width: 990px; $gl-avatar-size: 40px; $error-exclamation-point: #e62958; $border-radius-default: 2px; diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 2357dd2fe6f..0b15a72e6b4 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -1,15 +1,48 @@ -.container-limited.limit-container-width { - .issue-details { - .description, - .note-body { - p, - ul, - ol, - .code { - max-width: $line-length-width; +// Limit MR description for side-by-side diff view +.limit-container-width { + .detail-page-header { + max-width: calc(#{$limited-layout-width} - (#{$gl-padding} * 2)); + margin-left: auto; + margin-right: auto; + } + + .issuable-details { + .detail-page-description, + .mr-source-target, + .mr-state-widget, + .merge-manually { + max-width: calc(#{$limited-layout-width} - (#{$gl-padding} * 2)); + margin-left: auto; + margin-right: auto; + } + + .merge-request-tabs-holder { + &.affix { + border-bottom: 1px solid $border-color; + + .nav-links { + border: 0; + } + } + + .container-fluid { + padding-left: 0; + padding-right: 0; + max-width: calc(#{$limited-layout-width} - (#{$gl-padding} * 2)); + margin-left: auto; + margin-right: auto; } } } + + .diffs { + .mr-version-controls, + .files-changed { + max-width: calc(#{$limited-layout-width} - (#{$gl-padding} * 2)); + margin-left: auto; + margin-right: auto; + } + } } .issuable-details { @@ -23,7 +56,6 @@ .description img:not(.emoji) { border: 1px solid $table-border-gray; padding: 5px; - margin: 5px; max-height: calc(100vh - 100px); } } diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss index 10eb3d4203e..d697c8d25df 100644 --- a/app/assets/stylesheets/pages/notes.scss +++ b/app/assets/stylesheets/pages/notes.scss @@ -383,10 +383,6 @@ ul.notes { .note-action-button { margin-left: 10px; } - - @media (min-width: $screen-sm-min) { - position: relative; - } } .discussion-actions { diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml index 0db5548d36e..1187b04edb8 100644 --- a/app/views/projects/merge_requests/_show.html.haml +++ b/app/views/projects/merge_requests/_show.html.haml @@ -42,7 +42,7 @@ = render "projects/merge_requests/widget/show.html.haml" - if @merge_request.source_branch_exists? && @merge_request.mergeable? && @merge_request.can_be_merged_by?(current_user) - .light.prepend-top-default.append-bottom-default + .merge-manually.light.prepend-top-default.append-bottom-default You can also accept this merge request manually using the = succeed '.' do = link_to "command line", "#modal_merge_info", class: "how_to_merge_link vlink", title: "How To Merge", "data-toggle" => "modal" -- cgit v1.2.1 From 1235d96e973258b9c968049945426cb28bea9998 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 14 Dec 2016 12:10:56 +0000 Subject: Add dropdown statuses in mini-pipeline graph --- .../projects/ci/pipelines/_pipeline.html.haml | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/views/projects/ci/pipelines/_pipeline.html.haml b/app/views/projects/ci/pipelines/_pipeline.html.haml index 3f05a21990f..f17a0d668b7 100644 --- a/app/views/projects/ci/pipelines/_pipeline.html.haml +++ b/app/views/projects/ci/pipelines/_pipeline.html.haml @@ -43,10 +43,26 @@ %td.stage-cell - pipeline.stages.each do |stage| - if stage.status + - status = ci_label_for_status(stage.detailed_status) + - hasMultipleBuilds = stage.statuses.count > 1 - tooltip = "#{stage.name.titleize}: #{stage.status || 'not found'}" - .stage-container - = link_to namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id, anchor: stage.name), class: "has-tooltip ci-status-icon-#{stage.status}", title: tooltip do - = ci_icon_for_status(stage.status) + + - if status + .stage-container + - if hasMultipleBuilds + .dropdown.inline + %a.dropdown-toggle{id: "dropdown-#{stage.name}", "data-toggle"=> "dropdown", "aria-haspopup"=> "true", "aria-expanded" => "false" } + = ci_icon_for_status(stage.detailed_status) + %span.caret + .dropdown-menu.grouped-pipeline-dropdown{"aria-labelledby"=> "dropdown-#{stage.name}"} + .arrow + %ul + - stage.statuses.each do |status| + %li + status + - else + = link_to namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id, anchor: stage.name), class: "has-tooltip ci-status-icon-#{stage.status}", title: tooltip do + = ci_icon_for_status(stage.detailed_status) %td - if pipeline.duration -- cgit v1.2.1 From 01876eccad2bbc9ea2f35cb27c41b7373b20f26b Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 14 Dec 2016 13:54:23 +0000 Subject: Initial commit --- app/assets/stylesheets/framework/icons.scss | 24 ++++++++++++++++++++ app/assets/stylesheets/pages/pipelines.scss | 26 ++++++++++++++++++++++ .../projects/ci/pipelines/_pipeline.html.haml | 7 +++--- 3 files changed, 54 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/icons.scss b/app/assets/stylesheets/framework/icons.scss index 226bd2ead31..88b391ef2df 100644 --- a/app/assets/stylesheets/framework/icons.scss +++ b/app/assets/stylesheets/framework/icons.scss @@ -4,6 +4,10 @@ svg { fill: $gl-success; } + + .builds-dropdown-caret { + color: $gl-success; + } } .ci-status-icon-failed { @@ -12,6 +16,10 @@ svg { fill: $gl-danger; } + + .builds-dropdown-caret { + color: $gl-danger; + } } .ci-status-icon-pending, @@ -21,6 +29,10 @@ svg { fill: $gl-warning; } + + .builds-dropdown-caret { + color: $gl-warning; + } } .ci-status-icon-running { @@ -29,6 +41,10 @@ svg { fill: $blue-normal; } + + .builds-dropdown-caret { + color: $blue-normal; + } } .ci-status-icon-canceled, @@ -39,6 +55,10 @@ svg { fill: $gl-gray; } + + .builds-dropdown-caret { + color: $gl-gray; + } } .ci-status-icon-created, @@ -48,4 +68,8 @@ svg { fill: $gray-darkest; } + + .builds-dropdown-caret { + color: $gray-darkest; + } } diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index be22e7bdc79..50e8165a017 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -734,3 +734,29 @@ padding: 5px 5px 5px 7px; } } + +/** + * Builds dropdown in mini pipeline + */ +.builds-dropdown { + border: none; + background: transparent; + padding: 0; + font-size: inherit; + border-radius: 0; + cursor: pointer; + + .dropdown-caret { + display: none; + position: absolute; + top: 3px; + right: 6px; + font-size: 10px; + } + + &:hover { + .dropdown-caret { + display: block; + } + } +} diff --git a/app/views/projects/ci/pipelines/_pipeline.html.haml b/app/views/projects/ci/pipelines/_pipeline.html.haml index f17a0d668b7..931dd9d3a71 100644 --- a/app/views/projects/ci/pipelines/_pipeline.html.haml +++ b/app/views/projects/ci/pipelines/_pipeline.html.haml @@ -51,15 +51,16 @@ .stage-container - if hasMultipleBuilds .dropdown.inline - %a.dropdown-toggle{id: "dropdown-#{stage.name}", "data-toggle"=> "dropdown", "aria-haspopup"=> "true", "aria-expanded" => "false" } + %a.dropdown-toggle.builds-dropdown{id: "dropdown-#{stage.name}", title: tooltip, class: "has-tooltip ci-status-icon-#{stage.status}", "data-toggle"=> "dropdown", "aria-haspopup"=> "true", "aria-expanded" => "false"} = ci_icon_for_status(stage.detailed_status) - %span.caret + = icon('caret-down', class: 'dropdown-caret') .dropdown-menu.grouped-pipeline-dropdown{"aria-labelledby"=> "dropdown-#{stage.name}"} .arrow %ul - stage.statuses.each do |status| %li - status + = ci_icon_for_status(status) + -# =render 'ci/status/icon_with_name_and_action', subject: status - else = link_to namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id, anchor: stage.name), class: "has-tooltip ci-status-icon-#{stage.status}", title: tooltip do = ci_icon_for_status(stage.detailed_status) -- cgit v1.2.1 From fa4d41bf1836755cbf1f28af1d7841dcd81efeb8 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 14 Dec 2016 17:14:10 +0000 Subject: Render with new partials --- .../projects/ci/pipelines/_pipeline.html.haml | 37 +++++++++++----------- 1 file changed, 19 insertions(+), 18 deletions(-) (limited to 'app') diff --git a/app/views/projects/ci/pipelines/_pipeline.html.haml b/app/views/projects/ci/pipelines/_pipeline.html.haml index 931dd9d3a71..e82faf4f6d3 100644 --- a/app/views/projects/ci/pipelines/_pipeline.html.haml +++ b/app/views/projects/ci/pipelines/_pipeline.html.haml @@ -43,27 +43,28 @@ %td.stage-cell - pipeline.stages.each do |stage| - if stage.status - - status = ci_label_for_status(stage.detailed_status) + - detailed_status = stage.detailed_status(current_user) + - details_path = detailed_status.details_path if detailed_status.has_details? + - klass = "has-tooltip ci-status-icon ci-status-icon-#{detailed_status}" - hasMultipleBuilds = stage.statuses.count > 1 - tooltip = "#{stage.name.titleize}: #{stage.status || 'not found'}" - - if status - .stage-container - - if hasMultipleBuilds - .dropdown.inline - %a.dropdown-toggle.builds-dropdown{id: "dropdown-#{stage.name}", title: tooltip, class: "has-tooltip ci-status-icon-#{stage.status}", "data-toggle"=> "dropdown", "aria-haspopup"=> "true", "aria-expanded" => "false"} - = ci_icon_for_status(stage.detailed_status) - = icon('caret-down', class: 'dropdown-caret') - .dropdown-menu.grouped-pipeline-dropdown{"aria-labelledby"=> "dropdown-#{stage.name}"} - .arrow - %ul - - stage.statuses.each do |status| - %li - = ci_icon_for_status(status) - -# =render 'ci/status/icon_with_name_and_action', subject: status - - else - = link_to namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id, anchor: stage.name), class: "has-tooltip ci-status-icon-#{stage.status}", title: tooltip do - = ci_icon_for_status(stage.detailed_status) + .stage-container + - if hasMultipleBuilds + .dropdown.inline.build-content + %button.dropdown-menu-toggle.has-tooltip{id: "dropdown-#{stage.name}", title: tooltip, class: klass, "data-toggle"=> "dropdown", "aria-haspopup"=> "true", "aria-expanded" => "false"} + = custom_icon(detailed_status.icon) + = icon('caret-down', class: 'dropdown-caret') + .dropdown-menu.grouped-pipeline-dropdown{"aria-labelledby"=> "dropdown-#{stage.name}"} + .arrow + %ul + - stage.statuses.each do |status| + %li + = render 'ci/status/graph_badge', subject: status + - else + - if details_path + = link_to details_path, class: klass, title: tooltip do + = custom_icon(detailed_status.icon) %td - if pipeline.duration -- cgit v1.2.1 From 708125853117916ce3eeb809e5bb7518c8e5e3d8 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 14 Dec 2016 18:34:56 +0000 Subject: Dropdown with arrow --- app/assets/stylesheets/pages/pipelines.scss | 256 ++++++++++++--------- .../projects/ci/pipelines/_pipeline.html.haml | 15 +- 2 files changed, 153 insertions(+), 118 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 50e8165a017..df88e7b5925 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -576,17 +576,14 @@ } } - .ci-status-text { - max-width: 110px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - vertical-align: bottom; - display: inline-block; - position: relative; - font-weight: 100; + // Position in the pipeline graph + .grouped-pipeline-dropdown { + right: -206px; + top: -11px; } +} +<<<<<<< HEAD .dropdown-menu-toggle { background-color: transparent; border: none; @@ -594,110 +591,81 @@ color: $gl-text-color-light; white-space: normal; overflow: visible; +======= +.dropdown-counter-badge { + float: right; + color: $border-color; + font-weight: 100; + font-size: 15px; + margin-right: 2px; +} +>>>>>>> 5ba6f0d... Dropdown with arrow - &:focus { - outline: none; - } +.grouped-pipeline-dropdown { + padding: 0; + width: 191px; + left: auto; + right: -206px; + top: -11px; + box-shadow: 0 1px 5px $black-transparent; - &:hover { - color: $gl-text-color; + a { + display: inline-block; - .dropdown-counter-badge { - color: $gl-text-color; - } + &:hover { + background-color: $stage-hover-bg; } } - .dropdown-counter-badge { - float: right; - clear: right; - color: $border-color; - font-weight: 100; - font-size: 15px; - margin-right: 2px; - } - - .grouped-pipeline-dropdown { - padding: 0; - width: 191px; - left: auto; - right: -206px; - top: -11px; - box-shadow: 0 1px 5px $black-transparent; - - a { - display: inline-block; + ul { + max-height: 245px; + overflow: auto; + margin: 5px 0; - &:hover { - background-color: $stage-hover-bg; - } + li { + padding-top: 2px; + margin: 0 5px; } - ul { - max-height: 245px; - overflow: auto; - margin: 5px 0; - - li { - margin: 0 5px; - padding-left: 0; - padding-bottom: 0; - margin-bottom: 0; - line-height: 1.2; - } + li:first-child { + padding-top: 6px; } - .dropdown-build { - color: $gl-text-color-light; - - a.ci-action-icon-container { - padding: 0; - font-size: 11px; - float: right; - margin-top: 4px; - display: inline-block; - position: relative; + li:last-child { + padding-bottom: 6px; + } + } +} - i { - font-size: 11px; - margin-top: 0; - } - } +.ci-status-text { + max-width: 110px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + vertical-align: bottom; + display: inline-block; + position: relative; + font-weight: 100; +} - &:hover { - background-color: $stage-hover-bg; - border-radius: 3px; - color: $gl-text-color; - } - .ci-action-icon-container { - i { - width: 25px; - height: 25px; +.dropdown-menu-toggle { + background-color: transparent; + border: none; + padding: 0; + color: $gl-text-color-light; + flex-grow: 1; - &::before { - top: 1px; - left: 1px; - } - } - } - .stage { - max-width: 100px; - width: 100px; - } + &:focus { + outline: none; + } - .ci-status-icon svg { - height: 18px; - width: 18px; - } + &:hover { + color: $gl-text-color; - .ci-status-text { - max-width: 95px; - padding-bottom: 3px; - position: relative; - top: 3px; - } + .dropdown-counter-badge { + color: $gl-text-color; } } } @@ -735,28 +703,94 @@ } } +.dropdown-build { + color: $gl-text-color-light; + + a.ci-action-icon-container { + padding: 0; + font-size: 11px; + float: right; + margin-top: 5px; + + i { + font-size: 11px; + margin-top: 0; + } + } + + &:hover { + background-color: $stage-hover-bg; + border-radius: 3px; + color: $gl-text-color; + } + + .ci-action-icon-container { + i { + width: 25px; + height: 25px; + + &:before{ + top: 1px; + left: 1px; + } + } + } + + .stage { + max-width: 100px; + width: 100px; + } + + .ci-status-icon svg { + height: 18px; + width: 18px; + } + + .ci-status-text { + max-width: 95px; + } +} + /** * Builds dropdown in mini pipeline */ -.builds-dropdown { - border: none; - background: transparent; - padding: 0; - font-size: inherit; - border-radius: 0; - cursor: pointer; +.mini-pipeline-graph { + .builds-dropdown { + background-color: transparent; + border: none; + padding: 0; + color: #8c8c8c; + flex-grow: 1; + } - .dropdown-caret { - display: none; - position: absolute; - top: 3px; - right: 6px; - font-size: 10px; + .grouped-pipeline-dropdown { + right: -172px; + top: 23px; } - &:hover { - .dropdown-caret { - display: block; + .arrow-up { + &::before, + &::after { + content: ''; + display: inline-block; + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; + top: -6px; + left: 2px; + border-width: 0 5px 6px 5px; + } + + &::before { + border-width: 0 5px 5px 5px; + border-bottom-color: $border-color; + } + + &::after { + margin-top: 1px; + border-bottom-color: $white-light; } } } diff --git a/app/views/projects/ci/pipelines/_pipeline.html.haml b/app/views/projects/ci/pipelines/_pipeline.html.haml index e82faf4f6d3..9ecdb6269b9 100644 --- a/app/views/projects/ci/pipelines/_pipeline.html.haml +++ b/app/views/projects/ci/pipelines/_pipeline.html.haml @@ -49,17 +49,18 @@ - hasMultipleBuilds = stage.statuses.count > 1 - tooltip = "#{stage.name.titleize}: #{stage.status || 'not found'}" - .stage-container + .stage-container.mini-pipeline-graph - if hasMultipleBuilds .dropdown.inline.build-content - %button.dropdown-menu-toggle.has-tooltip{id: "dropdown-#{stage.name}", title: tooltip, class: klass, "data-toggle"=> "dropdown", "aria-haspopup"=> "true", "aria-expanded" => "false"} - = custom_icon(detailed_status.icon) - = icon('caret-down', class: 'dropdown-caret') - .dropdown-menu.grouped-pipeline-dropdown{"aria-labelledby"=> "dropdown-#{stage.name}"} - .arrow + %button.has-tooltip.builds-dropdown{ type: 'button', data: { toggle: 'dropdown', title: tooltip} } + %span{ class: klass } + = ci_icon_for_status(detailed_status.icon) + %span= icon('caret-down', class: 'dropdown-caret') + .dropdown-menu.grouped-pipeline-dropdown + .arrow-up %ul - stage.statuses.each do |status| - %li + %li.dropdown-build = render 'ci/status/graph_badge', subject: status - else - if details_path -- cgit v1.2.1 From 222eae7b7b17da923b0291c70ec2b6a4101186e6 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 14 Dec 2016 18:41:21 +0000 Subject: Dropdown li style --- app/assets/stylesheets/pages/pipelines.scss | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index df88e7b5925..b1575d5213d 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -192,10 +192,6 @@ border-bottom: 2px solid $border-color; } } - - a { - display: block; - } } } @@ -759,8 +755,7 @@ background-color: transparent; border: none; padding: 0; - color: #8c8c8c; - flex-grow: 1; + color: $gl-text-color-light; } .grouped-pipeline-dropdown { @@ -768,6 +763,10 @@ top: 23px; } + .grouped-pipeline-dropdown a { + color: $gl-text-color-light; + } + .arrow-up { &::before, &::after { -- cgit v1.2.1 From 9431fcb31c22d4d9bde7366d930264cc1f5e03a6 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 14 Dec 2016 23:47:04 +0000 Subject: style dropdown --- app/assets/stylesheets/pages/pipelines.scss | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index b1575d5213d..e0431e26769 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -756,6 +756,10 @@ border: none; padding: 0; color: $gl-text-color-light; + border: none; + background: transparent; + padding: 0; + margin: 0; } .grouped-pipeline-dropdown { -- cgit v1.2.1 From 5ce5e7a0e28062dd6b4a4195f9befe5017dd75ff Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Thu, 15 Dec 2016 00:17:40 +0000 Subject: Removes duplicate declaration --- app/assets/stylesheets/pages/pipelines.scss | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index e0431e26769..f98bf73756f 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -757,9 +757,7 @@ padding: 0; color: $gl-text-color-light; border: none; - background: transparent; - padding: 0; - margin: 0; + margin: 0; } .grouped-pipeline-dropdown { -- cgit v1.2.1 From 7bfe87242d9d897cdc68eb0df90345f2ec497c36 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Thu, 15 Dec 2016 11:58:25 +0000 Subject: Add new borderless icons --- app/views/shared/icons/_icon_status_canceled_borderless.svg | 1 + app/views/shared/icons/_icon_status_created_borderless.svg | 1 + app/views/shared/icons/_icon_status_failed_borderless.svg | 1 + app/views/shared/icons/_icon_status_manual_borderless.svg | 1 + app/views/shared/icons/_icon_status_pending_borderless.svg | 1 + app/views/shared/icons/_icon_status_running_borderless.svg | 1 + app/views/shared/icons/_icon_status_skipped_borderless.svg | 1 + app/views/shared/icons/_icon_status_success_borderless.svg | 1 + app/views/shared/icons/_icon_status_warning_borderless.svg | 1 + 9 files changed, 9 insertions(+) create mode 100644 app/views/shared/icons/_icon_status_canceled_borderless.svg create mode 100644 app/views/shared/icons/_icon_status_created_borderless.svg create mode 100644 app/views/shared/icons/_icon_status_failed_borderless.svg create mode 100644 app/views/shared/icons/_icon_status_manual_borderless.svg create mode 100644 app/views/shared/icons/_icon_status_pending_borderless.svg create mode 100644 app/views/shared/icons/_icon_status_running_borderless.svg create mode 100644 app/views/shared/icons/_icon_status_skipped_borderless.svg create mode 100644 app/views/shared/icons/_icon_status_success_borderless.svg create mode 100644 app/views/shared/icons/_icon_status_warning_borderless.svg (limited to 'app') diff --git a/app/views/shared/icons/_icon_status_canceled_borderless.svg b/app/views/shared/icons/_icon_status_canceled_borderless.svg new file mode 100644 index 00000000000..bf7fb29185f --- /dev/null +++ b/app/views/shared/icons/_icon_status_canceled_borderless.svg @@ -0,0 +1 @@ + diff --git a/app/views/shared/icons/_icon_status_created_borderless.svg b/app/views/shared/icons/_icon_status_created_borderless.svg new file mode 100644 index 00000000000..1810d023be8 --- /dev/null +++ b/app/views/shared/icons/_icon_status_created_borderless.svg @@ -0,0 +1 @@ + diff --git a/app/views/shared/icons/_icon_status_failed_borderless.svg b/app/views/shared/icons/_icon_status_failed_borderless.svg new file mode 100644 index 00000000000..b7022350c74 --- /dev/null +++ b/app/views/shared/icons/_icon_status_failed_borderless.svg @@ -0,0 +1 @@ + diff --git a/app/views/shared/icons/_icon_status_manual_borderless.svg b/app/views/shared/icons/_icon_status_manual_borderless.svg new file mode 100644 index 00000000000..5eec665688b --- /dev/null +++ b/app/views/shared/icons/_icon_status_manual_borderless.svg @@ -0,0 +1 @@ + diff --git a/app/views/shared/icons/_icon_status_pending_borderless.svg b/app/views/shared/icons/_icon_status_pending_borderless.svg new file mode 100644 index 00000000000..8d66e9e6c9c --- /dev/null +++ b/app/views/shared/icons/_icon_status_pending_borderless.svg @@ -0,0 +1 @@ + diff --git a/app/views/shared/icons/_icon_status_running_borderless.svg b/app/views/shared/icons/_icon_status_running_borderless.svg new file mode 100644 index 00000000000..2757a168ed5 --- /dev/null +++ b/app/views/shared/icons/_icon_status_running_borderless.svg @@ -0,0 +1 @@ + diff --git a/app/views/shared/icons/_icon_status_skipped_borderless.svg b/app/views/shared/icons/_icon_status_skipped_borderless.svg new file mode 100644 index 00000000000..fb3e930b3cb --- /dev/null +++ b/app/views/shared/icons/_icon_status_skipped_borderless.svg @@ -0,0 +1 @@ + diff --git a/app/views/shared/icons/_icon_status_success_borderless.svg b/app/views/shared/icons/_icon_status_success_borderless.svg new file mode 100644 index 00000000000..8ee5be7ab78 --- /dev/null +++ b/app/views/shared/icons/_icon_status_success_borderless.svg @@ -0,0 +1 @@ + diff --git a/app/views/shared/icons/_icon_status_warning_borderless.svg b/app/views/shared/icons/_icon_status_warning_borderless.svg new file mode 100644 index 00000000000..7b061624521 --- /dev/null +++ b/app/views/shared/icons/_icon_status_warning_borderless.svg @@ -0,0 +1 @@ + -- cgit v1.2.1 From 83ebc97ba76abc8375c147565603a14a18223649 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Thu, 15 Dec 2016 12:11:14 +0000 Subject: Adds new partial for borderless mini graph icons --- app/views/ci/status/_mini_graph_badge.html.haml | 6 ++++++ app/views/projects/ci/pipelines/_pipeline.html.haml | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 app/views/ci/status/_mini_graph_badge.html.haml (limited to 'app') diff --git a/app/views/ci/status/_mini_graph_badge.html.haml b/app/views/ci/status/_mini_graph_badge.html.haml new file mode 100644 index 00000000000..6031339a802 --- /dev/null +++ b/app/views/ci/status/_mini_graph_badge.html.haml @@ -0,0 +1,6 @@ +- status = subject.detailed_status(current_user) +- icon = "#{status.icon}_borderless" +- klass = "ci-status-icon ci-status-icon-#{status}" + +%span.mini-pipeline-graph-icon-container + %span{ class: klass }= custom_icon(icon) diff --git a/app/views/projects/ci/pipelines/_pipeline.html.haml b/app/views/projects/ci/pipelines/_pipeline.html.haml index 9ecdb6269b9..d664d925df9 100644 --- a/app/views/projects/ci/pipelines/_pipeline.html.haml +++ b/app/views/projects/ci/pipelines/_pipeline.html.haml @@ -54,7 +54,7 @@ .dropdown.inline.build-content %button.has-tooltip.builds-dropdown{ type: 'button', data: { toggle: 'dropdown', title: tooltip} } %span{ class: klass } - = ci_icon_for_status(detailed_status.icon) + = render 'ci/status/mini_graph_badge', subject: stage %span= icon('caret-down', class: 'dropdown-caret') .dropdown-menu.grouped-pipeline-dropdown .arrow-up @@ -65,7 +65,7 @@ - else - if details_path = link_to details_path, class: klass, title: tooltip do - = custom_icon(detailed_status.icon) + = render 'ci/status/mini_graph_badge', subject: stage %td - if pipeline.duration -- cgit v1.2.1 From 6fde0e094d5e2fb3edea3228ef8f7f193fc4f067 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Thu, 15 Dec 2016 13:22:39 +0000 Subject: CSS: dropdown on hover --- app/assets/stylesheets/pages/pipelines.scss | 52 ++++++++++++++++++++++ app/views/ci/status/_mini_graph_badge.html.haml | 3 +- .../projects/ci/pipelines/_pipeline.html.haml | 8 ++-- 3 files changed, 58 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index f98bf73756f..105c3fc3e7c 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -22,6 +22,7 @@ .table.ci-table { min-width: 1200px; + table-layout: fixed; .pipeline-id { color: $black; @@ -795,3 +796,54 @@ } } } + +.mini-pipeline-graph-icon-container .ci-status-icon { + display: inline-block; + border: 1px solid; + border-radius: 20px; + margin-right: 1px; + width: 20px; + height: 20px; + position: relative; + + svg { + top: -1px; + position: relative; + } +} + +.builds-dropdown { + &:focus { + margin-right: -6px; + + .ci-status-icon { + width: 27px; + padding: 0px 6px 0px 0px; + + + .dropdown-caret { + display: inline-block; + } + } + } + + .mini-pipeline-graph-icon-container { + .ci-status-icon:hover, + .ci-status-icon:focus { + width: 27px; + padding: 0px 6px 0px 0px; + + + .dropdown-caret { + display: inline-block; + } + } + + .dropdown-caret { + font-size: 12px; + position: relative; + top: 3px; + left: -11px; + margin-right: -6px; + display: none; + } + } +} diff --git a/app/views/ci/status/_mini_graph_badge.html.haml b/app/views/ci/status/_mini_graph_badge.html.haml index 6031339a802..34e07e75ae8 100644 --- a/app/views/ci/status/_mini_graph_badge.html.haml +++ b/app/views/ci/status/_mini_graph_badge.html.haml @@ -2,5 +2,4 @@ - icon = "#{status.icon}_borderless" - klass = "ci-status-icon ci-status-icon-#{status}" -%span.mini-pipeline-graph-icon-container - %span{ class: klass }= custom_icon(icon) +%span{ class: klass }= custom_icon(icon) diff --git a/app/views/projects/ci/pipelines/_pipeline.html.haml b/app/views/projects/ci/pipelines/_pipeline.html.haml index d664d925df9..0651447f616 100644 --- a/app/views/projects/ci/pipelines/_pipeline.html.haml +++ b/app/views/projects/ci/pipelines/_pipeline.html.haml @@ -54,8 +54,9 @@ .dropdown.inline.build-content %button.has-tooltip.builds-dropdown{ type: 'button', data: { toggle: 'dropdown', title: tooltip} } %span{ class: klass } - = render 'ci/status/mini_graph_badge', subject: stage - %span= icon('caret-down', class: 'dropdown-caret') + %span.mini-pipeline-graph-icon-container + = render 'ci/status/mini_graph_badge', subject: stage + = icon('caret-down', class: 'dropdown-caret') .dropdown-menu.grouped-pipeline-dropdown .arrow-up %ul @@ -65,7 +66,8 @@ - else - if details_path = link_to details_path, class: klass, title: tooltip do - = render 'ci/status/mini_graph_badge', subject: stage + %span.mini-pipeline-graph-icon-container + = render 'ci/status/mini_graph_badge', subject: stage %td - if pipeline.duration -- cgit v1.2.1 From e36b00e7137a7fd024ba4639ac6cb077edd2618a Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Thu, 15 Dec 2016 14:46:28 +0000 Subject: CSS - Adds background color. Removes unused CSS Fix scss linter errors Adds changelog entry Increase icons size. Adds transition animation Fix jumping icon. Reduce icon size Fix columns width Changes after review Fix transition --- app/assets/stylesheets/framework/icons.scss | 24 ----- app/assets/stylesheets/pages/pipelines.scss | 116 ++++++++++++++++--------- app/views/projects/commit/_pipelines_list.haml | 14 +-- app/views/projects/pipelines/index.html.haml | 12 +-- 4 files changed, 89 insertions(+), 77 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/icons.scss b/app/assets/stylesheets/framework/icons.scss index 88b391ef2df..226bd2ead31 100644 --- a/app/assets/stylesheets/framework/icons.scss +++ b/app/assets/stylesheets/framework/icons.scss @@ -4,10 +4,6 @@ svg { fill: $gl-success; } - - .builds-dropdown-caret { - color: $gl-success; - } } .ci-status-icon-failed { @@ -16,10 +12,6 @@ svg { fill: $gl-danger; } - - .builds-dropdown-caret { - color: $gl-danger; - } } .ci-status-icon-pending, @@ -29,10 +21,6 @@ svg { fill: $gl-warning; } - - .builds-dropdown-caret { - color: $gl-warning; - } } .ci-status-icon-running { @@ -41,10 +29,6 @@ svg { fill: $blue-normal; } - - .builds-dropdown-caret { - color: $blue-normal; - } } .ci-status-icon-canceled, @@ -55,10 +39,6 @@ svg { fill: $gl-gray; } - - .builds-dropdown-caret { - color: $gl-gray; - } } .ci-status-icon-created, @@ -68,8 +48,4 @@ svg { fill: $gray-darkest; } - - .builds-dropdown-caret { - color: $gray-darkest; - } } diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 105c3fc3e7c..33d3a800e7c 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -28,12 +28,16 @@ color: $black; } - .branch-commit { - width: 30%; + .pipeline-date, + .pipeline-status { + width: 10%; + } - .branch-name { - max-width: 195px; - } + .pipeline-info, + .pipeline-commit, + .pipeline-actions, + .pipeline-stages { + width: 20%; } } } @@ -107,7 +111,7 @@ .branch-name { font-weight: bold; - max-width: 150px; + max-width: 120px; overflow: hidden; display: inline-block; white-space: nowrap; @@ -133,7 +137,7 @@ .commit-title { margin-top: 4px; - max-width: 300px; + max-width: 225px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; @@ -580,15 +584,6 @@ } } -<<<<<<< HEAD - .dropdown-menu-toggle { - background-color: transparent; - border: none; - padding: 0; - color: $gl-text-color-light; - white-space: normal; - overflow: visible; -======= .dropdown-counter-badge { float: right; color: $border-color; @@ -596,7 +591,6 @@ font-size: 15px; margin-right: 2px; } ->>>>>>> 5ba6f0d... Dropdown with arrow .grouped-pipeline-dropdown { padding: 0; @@ -707,7 +701,9 @@ padding: 0; font-size: 11px; float: right; - margin-top: 5px; + margin-top: 4px; + display: inline-block; + position: relative; i { font-size: 11px; @@ -726,7 +722,7 @@ width: 25px; height: 25px; - &:before{ + &::before { top: 1px; left: 1px; } @@ -782,11 +778,11 @@ border-style: solid; top: -6px; left: 2px; - border-width: 0 5px 6px 5px; + border-width: 0 5px 6px; } &::before { - border-width: 0 5px 5px 5px; + border-width: 0 5px 5px; border-bottom-color: $border-color; } @@ -797,53 +793,93 @@ } } +/** + * Icons in mini pipeline graph + */ .mini-pipeline-graph-icon-container .ci-status-icon { - display: inline-block; - border: 1px solid; - border-radius: 20px; - margin-right: 1px; - width: 20px; - height: 20px; - position: relative; + display: inline-block; + border: 1px solid; + border-radius: 20px; + margin-right: 1px; + width: 20px; + height: 20px; + position: relative; + z-index: 2; + transition: all 0.2s cubic-bezier(0.25, 0, 1, 1); - svg { - top: -1px; - position: relative; - } + svg { + top: -1px; + } } .builds-dropdown { &:focus { - margin-right: -6px; + outline: none; + margin-right: -8px; .ci-status-icon { - width: 27px; - padding: 0px 6px 0px 0px; + width: 28px; + padding: 0 8px 0 0; + transition: all 0.2s cubic-bezier(0.25, 0, 1, 1); + .dropdown-caret { - display: inline-block; + display: inline-block; } } } + &:focus, + &:active { + .ci-status-icon-success { + background-color: rgba($gl-success, .1); + } + + .ci-status-icon-failed { + background-color: rgba($gl-danger, .1); + } + + .ci-status-icon-pending, + .ci-status-icon-success_with_warnings { + background-color: rgba($gl-warning, .1); + } + + .ci-status-icon-running { + background-color: rgba($blue-normal, .1); + } + + .ci-status-icon-canceled, + .ci-status-icon-disabled, + .ci-status-icon-not-found { + background-color: rgba($gl-gray, .1); + } + + .ci-status-icon-created, + .ci-status-icon-skipped { + background-color: rgba($gray-darkest, .1); + } + + } + .mini-pipeline-graph-icon-container { .ci-status-icon:hover, .ci-status-icon:focus { - width: 27px; - padding: 0px 6px 0px 0px; + width: 28px; + padding: 0 8px 0 0; + transition: all 0.2s cubic-bezier(0.25, 0, 1, 1); + .dropdown-caret { - display: inline-block; + display: inline-block; } } .dropdown-caret { - font-size: 12px; + font-size: 11px; position: relative; top: 3px; left: -11px; margin-right: -6px; display: none; + z-index: 2; } } } diff --git a/app/views/projects/commit/_pipelines_list.haml b/app/views/projects/commit/_pipelines_list.haml index 7f42fde0fea..0c2f45c6035 100644 --- a/app/views/projects/commit/_pipelines_list.haml +++ b/app/views/projects/commit/_pipelines_list.haml @@ -5,11 +5,11 @@ - else .table-holder %table.table.ci-table - %tbody - %th Status - %th Pipeline - %th Commit - %th Stages - %th - %th + %thead + %th.pipeline-status Status + %th.pipeline-info Pipeline + %th.pipeline-commit Commit + %th.pipeline-stages Stages + %th.pipeline-date + %th.pipeline-actions = render pipelines, commit_sha: true, stage: true, allow_retry: true, show_commit: false diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index 030cd8ef78f..4d009871f0d 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -44,12 +44,12 @@ .table-holder %table.table.ci-table %thead - %th Status - %th Pipeline - %th Commit - %th Stages - %th - %th.hidden-xs + %th.pipeline-status Status + %th.pipeline-info Pipeline + %th.pipeline-commit Commit + %th.pipeline-stages Stages + %th.pipeline-date + %th.pipeline-actions.hidden-xs = render @pipelines, commit_sha: true, stage: true, allow_retry: true = paginate @pipelines, theme: 'gitlab' -- cgit v1.2.1 From e42de89a15c858866d78a4d2a5837a0feec922a5 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Thu, 15 Dec 2016 17:30:49 +0000 Subject: Changes after review Changes after review Fix tooltip title Remove unneeded string interpolation --- app/assets/stylesheets/pages/pipelines.scss | 10 +--------- app/views/ci/status/_graph_badge.html.haml | 4 ++-- app/views/projects/ci/builds/_build_pipeline.html.haml | 13 ------------- .../_generic_commit_status_pipeline.html.haml | 10 ---------- 4 files changed, 3 insertions(+), 34 deletions(-) delete mode 100644 app/views/projects/ci/builds/_build_pipeline.html.haml delete mode 100644 app/views/projects/generic_commit_statuses/_generic_commit_status_pipeline.html.haml (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index d3f39570f11..be22e7bdc79 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -645,14 +645,6 @@ margin-bottom: 0; line-height: 1.2; } - - li:first-child { - padding-top: 6px; - } - - li:last-child { - padding-bottom: 6px; - } } .dropdown-build { @@ -741,4 +733,4 @@ .ci-play-icon { padding: 5px 5px 5px 7px; } -} \ No newline at end of file +} diff --git a/app/views/ci/status/_graph_badge.html.haml b/app/views/ci/status/_graph_badge.html.haml index a7e8544e7d4..c7d04ab61e9 100644 --- a/app/views/ci/status/_graph_badge.html.haml +++ b/app/views/ci/status/_graph_badge.html.haml @@ -5,7 +5,7 @@ - klass = "ci-status-icon ci-status-icon-#{status}" - if status.has_details? - = link_to status.details_path, data: { toggle: 'tooltip', title: "#{subject.name} - #{status}" } do + = link_to status.details_path, data: { toggle: 'tooltip', title: "#{subject.name} - #{status.label}" } do %span{ class: klass }= custom_icon(status.icon) .ci-status-text= subject.name - else @@ -14,6 +14,6 @@ - if status.has_action? = link_to status.action_path, method: status.action_method, - title: "#{subject.name}: #{status.action_title}", class: 'ci-action-icon-container' do + title: status.action_title, class: 'ci-action-icon-container' do %i.ci-action-icon-wrapper = icon(status.action_icon, class: status.action_class) diff --git a/app/views/projects/ci/builds/_build_pipeline.html.haml b/app/views/projects/ci/builds/_build_pipeline.html.haml deleted file mode 100644 index ad1a7360a8b..00000000000 --- a/app/views/projects/ci/builds/_build_pipeline.html.haml +++ /dev/null @@ -1,13 +0,0 @@ -- is_playable = subject.playable? && can?(current_user, :update_build, @project) -- if is_playable - = link_to play_namespace_project_build_path(subject.project.namespace, subject.project, subject, return_to: request.original_url), method: :post, data: { toggle: 'tooltip', title: "#{subject.name} - play", container: '.js-pipeline-graph', placement: 'bottom' } do - = ci_icon_for_status('play') - .ci-status-text= subject.name -- elsif can?(current_user, :read_build, @project) - = link_to namespace_project_build_path(subject.project.namespace, subject.project, subject), data: { toggle: 'tooltip', title: "#{subject.name} - #{subject.status}", container: '.js-pipeline-graph', placement: 'bottom' } do - %span{class: "ci-status-icon ci-status-icon-#{subject.status}"} - = ci_icon_for_status(subject.status) - .ci-status-text= subject.name -- else - %span{class: "ci-status-icon ci-status-icon-#{subject.status}"} - = ci_icon_for_status(subject.status) diff --git a/app/views/projects/generic_commit_statuses/_generic_commit_status_pipeline.html.haml b/app/views/projects/generic_commit_statuses/_generic_commit_status_pipeline.html.haml deleted file mode 100644 index 1bba0443154..00000000000 --- a/app/views/projects/generic_commit_statuses/_generic_commit_status_pipeline.html.haml +++ /dev/null @@ -1,10 +0,0 @@ -%a{ data: { toggle: 'tooltip', title: "#{subject.name} - #{subject.status}", container: '.js-pipeline-graph', placement: 'bottom' } } - - if subject.target_url - = link_to subject.target_url do - %span{class: "ci-status-icon ci-status-icon-#{subject.status}"} - = ci_icon_for_status(subject.status) - %span.ci-status-text= subject.name - - else - %span{class: "ci-status-icon ci-status-icon-#{subject.status}"} - = ci_icon_for_status(subject.status) - %span.ci-status-text= subject.name -- cgit v1.2.1 From b2508cbdaf600bbb8fb2fd56c9891304502429b3 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 15 Dec 2016 22:06:39 +0100 Subject: Improve performance of Pipelines API --- app/finders/pipelines_finder.rb | 1 + app/models/ci/pipeline.rb | 8 ++++++-- app/serializers/pipeline_entity.rb | 4 +--- 3 files changed, 8 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/finders/pipelines_finder.rb b/app/finders/pipelines_finder.rb index 32aea75486d..af4bb54e52d 100644 --- a/app/finders/pipelines_finder.rb +++ b/app/finders/pipelines_finder.rb @@ -20,6 +20,7 @@ class PipelinesFinder end scoped_pipelines.order(id: :desc) + .includes(project: [:namespace]) end private diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 54f73171fd4..9efda36fc0c 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -124,7 +124,7 @@ module Ci end def artifacts - builds.latest.with_artifacts_not_expired + builds.latest.with_artifacts_not_expired.includes(project: [:namespace]) end def project_id @@ -173,7 +173,11 @@ module Ci end def manual_actions - builds.latest.manual_actions + builds.latest.manual_actions.includes(project: [:namespace]) + end + + def stuck? + builds.pending.any?(&:stuck?) end def retryable? diff --git a/app/serializers/pipeline_entity.rb b/app/serializers/pipeline_entity.rb index 613a18e6357..3ede0fb0f53 100644 --- a/app/serializers/pipeline_entity.rb +++ b/app/serializers/pipeline_entity.rb @@ -33,9 +33,7 @@ class PipelineEntity < Grape::Entity pipeline.yaml_errors.present? end - expose :stuck?, as: :stuck do |pipeline| - pipeline.builds.any?(&:stuck?) - end + expose :stuck?, as: :stuck end expose :ref do -- cgit v1.2.1 From a85235b824cd4cf791a10dc69f64732d971bf323 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 15 Dec 2016 22:06:59 +0100 Subject: Remove unused updated_at --- app/controllers/projects/pipelines_controller.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'app') diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb index 642651101f0..9f3702f9f19 100644 --- a/app/controllers/projects/pipelines_controller.rb +++ b/app/controllers/projects/pipelines_controller.rb @@ -27,7 +27,6 @@ class Projects::PipelinesController < Projects::ApplicationController .new(project: @project, user: @current_user) .with_pagination(request, response) .represent(@pipelines), - updated_at: Time.now.utc, count: { all: @pipelines_count, running_or_pending: @running_or_pending_count -- cgit v1.2.1 From 75060b93a6ea958b0c61a3c276d009026eef9dbd Mon Sep 17 00:00:00 2001 From: Jacopo Date: Wed, 14 Dec 2016 21:32:01 +0100 Subject: Go to a project order The order of "Go to a project" dropdown is based on last_activity_at --- app/assets/javascripts/project_select.js | 3 ++- app/helpers/projects_helper.rb | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/project_select.js b/app/assets/javascripts/project_select.js index fe1f96872f3..17887a6e449 100644 --- a/app/assets/javascripts/project_select.js +++ b/app/assets/javascripts/project_select.js @@ -13,6 +13,7 @@ }, data: function(term, callback) { var finalCallback, projectsCallback; + var orderBy = $dropdown.data('order-by'); finalCallback = function(projects) { return callback(projects); }; @@ -32,7 +33,7 @@ if (this.groupId) { return Api.groupProjects(this.groupId, term, projectsCallback); } else { - return Api.projects(term, this.orderBy, projectsCallback); + return Api.projects(term, orderBy, projectsCallback); } }, url: function(project) { diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 9cda3b78761..0f3546ebec7 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -61,7 +61,7 @@ module ProjectsHelper project_link = link_to simple_sanitize(project.name), project_path(project), { class: "project-item-select-holder" } if current_user - project_link << button_tag(type: 'button', class: "dropdown-toggle-caret js-projects-dropdown-toggle", aria: { label: "Toggle switch project dropdown" }, data: { target: ".js-dropdown-menu-projects", toggle: "dropdown" }) do + project_link << button_tag(type: 'button', class: 'dropdown-toggle-caret js-projects-dropdown-toggle', aria: { label: 'Toggle switch project dropdown' }, data: { target: '.js-dropdown-menu-projects', toggle: 'dropdown', order_by: 'last_activity_at' }) do icon("chevron-down") end end -- cgit v1.2.1 From 27a4aef5848d36b38c861c952a098f85562a31df Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 15 Dec 2016 14:46:35 -0700 Subject: use boards interceptor --- app/assets/javascripts/vue_pipelines_index/index.js.es6 | 3 ++- app/assets/javascripts/vue_pipelines_index/interceptor.js.es6 | 8 -------- 2 files changed, 2 insertions(+), 9 deletions(-) delete mode 100644 app/assets/javascripts/vue_pipelines_index/interceptor.js.es6 (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/index.js.es6 b/app/assets/javascripts/vue_pipelines_index/index.js.es6 index ced3e8f2602..8f3e211aac8 100644 --- a/app/assets/javascripts/vue_pipelines_index/index.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/index.js.es6 @@ -5,7 +5,8 @@ //= require vue-resource -//= require ./interceptor.js.es6 +/*= require boards/vue_resource_interceptor */ + //= require ./status.js.es6 //= require ./store.js.es6 //= require ./pipeline_url.js.es6 diff --git a/app/assets/javascripts/vue_pipelines_index/interceptor.js.es6 b/app/assets/javascripts/vue_pipelines_index/interceptor.js.es6 deleted file mode 100644 index 80f137ca12e..00000000000 --- a/app/assets/javascripts/vue_pipelines_index/interceptor.js.es6 +++ /dev/null @@ -1,8 +0,0 @@ -/* eslint-disable */ -Vue.http.interceptors.push((request, next) => { - Vue.activeResources = Vue.activeResources ? Vue.activeResources + 1 : 1; - - next(function (response) { - Vue.activeResources--; - }); -}); -- cgit v1.2.1 From 958a499a7f2f9cfad35b2861c33f1a1d1e248eaf Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Thu, 15 Dec 2016 18:02:45 -0500 Subject: Fix eslint errors --- app/assets/javascripts/dispatcher.js.es6 | 2 +- app/assets/javascripts/issues_bulk_assignment.js.es6 | 14 +++++++------- app/assets/javascripts/labels_select.js | 2 +- app/assets/javascripts/render_math.js | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/dispatcher.js.es6 b/app/assets/javascripts/dispatcher.js.es6 index 1ec950494ff..1e259a16f06 100644 --- a/app/assets/javascripts/dispatcher.js.es6 +++ b/app/assets/javascripts/dispatcher.js.es6 @@ -75,7 +75,7 @@ case 'projects:issues:index': Issuable.init(); new gl.IssuableBulkActions({ - prefixId: page === 'projects:merge_requests:index' ? 'merge_request_' : 'issue_' + prefixId: page === 'projects:merge_requests:index' ? 'merge_request_' : 'issue_', }); shortcut_handler = new ShortcutsNavigation(); break; diff --git a/app/assets/javascripts/issues_bulk_assignment.js.es6 b/app/assets/javascripts/issues_bulk_assignment.js.es6 index 1c8e5dede6f..52fd5d71b18 100644 --- a/app/assets/javascripts/issues_bulk_assignment.js.es6 +++ b/app/assets/javascripts/issues_bulk_assignment.js.es6 @@ -6,7 +6,7 @@ class IssuableBulkActions { constructor({ container, form, issues, prefixId } = {}) { - this.prefixId = prefixId || 'issue_'; + this.prefixId = prefixId || 'issue_'; this.form = form || this.getElement('.bulk-update'); this.$labelDropdown = this.form.find('.js-label-select'); this.issues = issues || this.getElement('.issues-list .issue'); @@ -107,7 +107,7 @@ } setOriginalDropdownData() { - let $labelSelect = $('.bulk-update .js-label-select'); + const $labelSelect = $('.bulk-update .js-label-select'); $labelSelect.data('common', this.getOriginalCommonIds()); $labelSelect.data('marked', this.getOriginalMarkedIds()); $labelSelect.data('indeterminate', this.getOriginalIndeterminateIds()); @@ -115,7 +115,7 @@ // From issuable's initial bulk selection getOriginalCommonIds() { - let labelIds = []; + const labelIds = []; this.getElement('.selected_issue:checked').each((i, el) => { labelIds.push(this.getElement(`#${this.prefixId}${el.dataset.id}`).data('labels')); @@ -125,17 +125,17 @@ // From issuable's initial bulk selection getOriginalMarkedIds() { - var labelIds = []; + const labelIds = []; this.getElement('.selected_issue:checked').each((i, el) => { labelIds.push(this.getElement(`#${this.prefixId}${el.dataset.id}`).data('labels')); }); - return _.intersection.apply(_, labelIds); + return _.intersection.apply(this, labelIds); } // From issuable's initial bulk selection getOriginalIndeterminateIds() { - let uniqueIds = []; - let labelIds = []; + const uniqueIds = []; + const labelIds = []; let issuableLabels = []; // Collect unique label IDs for all checked issues diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js index 6853d6b9db2..ec2fc87bece 100644 --- a/app/assets/javascripts/labels_select.js +++ b/app/assets/javascripts/labels_select.js @@ -8,7 +8,7 @@ var _this; _this = this; $('.js-label-select').each(function(i, dropdown) { - var $block, $colorPreview, $dropdown, $form, $loading, $selectbox, $sidebarCollapsedValue, $value, abilityName, defaultLabel, enableLabelCreateButton, issueURLSplit, issueUpdateURL, labelHTMLTemplate, labelNoneHTMLTemplate, labelUrl, namespacePath, projectPath, saveLabelData, selectedLabel, showAny, showNo, $sidebarLabelTooltip, initialSelected, $toggleText, fieldName, useId, propertyName, showMenuAbove, $container; + var $block, $colorPreview, $dropdown, $form, $loading, $selectbox, $sidebarCollapsedValue, $value, abilityName, defaultLabel, enableLabelCreateButton, issueURLSplit, issueUpdateURL, labelHTMLTemplate, labelNoneHTMLTemplate, labelUrl, namespacePath, projectPath, saveLabelData, selectedLabel, showAny, showNo, $sidebarLabelTooltip, initialSelected, $toggleText, fieldName, useId, propertyName, showMenuAbove, $container, $dropdownContainer; $dropdown = $(dropdown); $dropdownContainer = $dropdown.closest('.labels-filter'); $toggleText = $dropdown.find('.dropdown-toggle-text'); diff --git a/app/assets/javascripts/render_math.js b/app/assets/javascripts/render_math.js index a8a56430f88..209e7a8661d 100644 --- a/app/assets/javascripts/render_math.js +++ b/app/assets/javascripts/render_math.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, space-before-function-paren, consistent-return, no-var, no-undef, no-else-return, prefer-arrow-callback, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, consistent-return, no-var, no-undef, no-else-return, prefer-arrow-callback, padded-blocks, max-len, no-console */ // Renders math using KaTeX in any element with the // `js-render-math` class // -- cgit v1.2.1 From 9a2eaecc8b720367a7d079019b22f40627a871b1 Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Wed, 14 Dec 2016 13:30:08 +0000 Subject: Correct slack slash commands pretty path --- .../projects/services/mattermost_slash_commands/_help.html.haml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/views/projects/services/mattermost_slash_commands/_help.html.haml b/app/views/projects/services/mattermost_slash_commands/_help.html.haml index a676c0290a0..01a77a952d1 100644 --- a/app/views/projects/services/mattermost_slash_commands/_help.html.haml +++ b/app/views/projects/services/mattermost_slash_commands/_help.html.haml @@ -1,5 +1,4 @@ -- pretty_path_with_namespace = "#{@project ? @project.namespace.name : 'namespace'} / #{@project ? @project.name : 'name'}" -- run_actions_text = "Perform common operations on this project: #{pretty_path_with_namespace}" +- run_actions_text = "Perform common operations on this project: #{@project.name_with_namespace}" .well This service allows GitLab users to perform common operations on this @@ -27,7 +26,7 @@ .form-group = label_tag :display_name, 'Display name', class: 'col-sm-2 col-xs-12 control-label' .col-sm-10.col-xs-12.input-group - = text_field_tag :display_name, "GitLab / #{pretty_path_with_namespace}", class: 'form-control input-sm', readonly: 'readonly' + = text_field_tag :display_name, "GitLab / #{@project.name_with_namespace}", class: 'form-control input-sm', readonly: 'readonly' .input-group-btn = clipboard_button(clipboard_target: '#display_name') -- cgit v1.2.1 From e52e3ab5082599fd5a895de961b07584421a5cd2 Mon Sep 17 00:00:00 2001 From: Gabriel Gizotti Date: Wed, 23 Nov 2016 21:03:53 +1000 Subject: Remove whole description from #merge_commit_message and add add closed issues --- app/models/merge_request.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index b73d7acefea..62dd02936e2 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -615,7 +615,8 @@ class MergeRequest < ActiveRecord::Base def merge_commit_message message = "Merge branch '#{source_branch}' into '#{target_branch}'\n\n" message << "#{title}\n\n" - message << "#{description}\n\n" if description.present? + mr_closes_issues = closes_issues + message << "Closed Issues: #{mr_closes_issues.map { |issue| issue.to_reference(target_project) }.join(", ")}\n\n" if mr_closes_issues.present? message << "See merge request #{to_reference}" message -- cgit v1.2.1 From 1a8f43ff3e5481d65f547ac01c03e2d64e14fff0 Mon Sep 17 00:00:00 2001 From: Gabriel Gizotti Date: Thu, 24 Nov 2016 07:50:49 +1000 Subject: introduce MergeRequest#issues_mentioned_but_not_closing --- app/models/merge_request.rb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'app') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 62dd02936e2..6f660bf0e77 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -568,6 +568,22 @@ class MergeRequest < ActiveRecord::Base end end + def issues_mentioned_but_not_closing(current_user = self.author) + issues = [] + + if target_branch == project.default_branch + messages = [description] + messages.concat(commits.map(&:safe_message)) if merge_request_diff + + ext = Gitlab::ReferenceExtractor.new(project, current_user) + ext.analyze(messages.join("\n")) + + issues = ext.issues + end + + issues - closes_issues + end + def target_project_path if target_project target_project.path_with_namespace -- cgit v1.2.1 From 80915c35f48463c3a983129961f3130bd9703754 Mon Sep 17 00:00:00 2001 From: Gabriel Gizotti Date: Thu, 24 Nov 2016 19:21:27 +1000 Subject: diplays mentioned but not merged message on MR show page --- app/helpers/merge_requests_helper.rb | 11 +++++++++++ app/views/projects/merge_requests/widget/_open.html.haml | 9 +++++++++ 2 files changed, 20 insertions(+) (limited to 'app') diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb index a6659ea2fd1..dcd35dc6282 100644 --- a/app/helpers/merge_requests_helper.rb +++ b/app/helpers/merge_requests_helper.rb @@ -59,6 +59,17 @@ module MergeRequestsHelper @mr_closes_issues ||= @merge_request.closes_issues end + def mr_issues_mentioned_but_not_closing + @mr_issues_mentioned_but_not_closing ||= @merge_request.issues_mentioned_but_not_closing + end + + def mr_issues_mentioned_but_not_closing_message + verb = mr_issues_mentioned_but_not_closing.size > 1 ? 'are' : 'is' + issue_text = 'issue'.pluralize(mr_issues_mentioned_but_not_closing.size) + + "The following #{issue_text} #{verb} mentioned but not being closed:" + end + def mr_change_branches_path(merge_request) new_namespace_project_merge_request_path( @project.namespace, @project, diff --git a/app/views/projects/merge_requests/widget/_open.html.haml b/app/views/projects/merge_requests/widget/_open.html.haml index eee711dc5af..1f794cad663 100644 --- a/app/views/projects/merge_requests/widget/_open.html.haml +++ b/app/views/projects/merge_requests/widget/_open.html.haml @@ -30,6 +30,15 @@ - elsif @merge_request.can_be_merged? || resolved_conflicts = render 'projects/merge_requests/widget/open/accept' + - if mr_issues_mentioned_but_not_closing.present? + .mr-widget-footer + %span + %i.fa.fa-warning + = mr_issues_mentioned_but_not_closing_message + = succeed '.' do + != markdown issues_sentence(mr_issues_mentioned_but_not_closing), pipeline: :gfm, author: @merge_request.author + = mr_assign_issues_link + - if mr_closes_issues.present? .mr-widget-footer %span -- cgit v1.2.1 From c1515cd865ec11110f9b34c41a41747dcbc3b402 Mon Sep 17 00:00:00 2001 From: Gabriel Gizotti Date: Fri, 25 Nov 2016 06:46:16 +1000 Subject: better mentioned but not closing message and icon --- app/helpers/merge_requests_helper.rb | 7 ------- app/views/projects/merge_requests/widget/_open.html.haml | 4 ++-- 2 files changed, 2 insertions(+), 9 deletions(-) (limited to 'app') diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb index dcd35dc6282..20218775659 100644 --- a/app/helpers/merge_requests_helper.rb +++ b/app/helpers/merge_requests_helper.rb @@ -63,13 +63,6 @@ module MergeRequestsHelper @mr_issues_mentioned_but_not_closing ||= @merge_request.issues_mentioned_but_not_closing end - def mr_issues_mentioned_but_not_closing_message - verb = mr_issues_mentioned_but_not_closing.size > 1 ? 'are' : 'is' - issue_text = 'issue'.pluralize(mr_issues_mentioned_but_not_closing.size) - - "The following #{issue_text} #{verb} mentioned but not being closed:" - end - def mr_change_branches_path(merge_request) new_namespace_project_merge_request_path( @project.namespace, @project, diff --git a/app/views/projects/merge_requests/widget/_open.html.haml b/app/views/projects/merge_requests/widget/_open.html.haml index 1f794cad663..ebea48a4321 100644 --- a/app/views/projects/merge_requests/widget/_open.html.haml +++ b/app/views/projects/merge_requests/widget/_open.html.haml @@ -33,8 +33,8 @@ - if mr_issues_mentioned_but_not_closing.present? .mr-widget-footer %span - %i.fa.fa-warning - = mr_issues_mentioned_but_not_closing_message + %i.fa.fa-info-circle + #{"Issue".pluralize(mr_issues_mentioned_but_not_closing.size)} mentioned but not being closed: = succeed '.' do != markdown issues_sentence(mr_issues_mentioned_but_not_closing), pipeline: :gfm, author: @merge_request.author = mr_assign_issues_link -- cgit v1.2.1 From 0e76daf3da35920d10053dc4d8707e1b6aa7c913 Mon Sep 17 00:00:00 2001 From: Gabriel Gizotti Date: Fri, 25 Nov 2016 06:49:56 +1000 Subject: only look for issues mentioned on description on MergeRequest#issues_mentioned_but_not_closing --- app/models/merge_request.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 6f660bf0e77..b8c139d01e2 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -570,18 +570,20 @@ class MergeRequest < ActiveRecord::Base def issues_mentioned_but_not_closing(current_user = self.author) issues = [] + closing_issues = [] if target_branch == project.default_branch messages = [description] - messages.concat(commits.map(&:safe_message)) if merge_request_diff ext = Gitlab::ReferenceExtractor.new(project, current_user) ext.analyze(messages.join("\n")) issues = ext.issues + closing_issues = Gitlab::ClosingIssueExtractor.new(project, current_user). + closed_by_message(messages.join("\n")) end - issues - closes_issues + issues - closing_issues end def target_project_path -- cgit v1.2.1 From b4764a8dd22c29b7edc3065af9a99713aa5708d3 Mon Sep 17 00:00:00 2001 From: Gabriel Gizotti Date: Fri, 25 Nov 2016 07:01:05 +1000 Subject: shorter lines on MergeRequest#merge_commit_message --- app/models/merge_request.rb | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index b8c139d01e2..5a5b8bd6010 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -631,10 +631,17 @@ class MergeRequest < ActiveRecord::Base end def merge_commit_message + closes_issues_references = closes_issues.map do |issue| + issue.to_reference(target_project) + end + message = "Merge branch '#{source_branch}' into '#{target_branch}'\n\n" message << "#{title}\n\n" - mr_closes_issues = closes_issues - message << "Closed Issues: #{mr_closes_issues.map { |issue| issue.to_reference(target_project) }.join(", ")}\n\n" if mr_closes_issues.present? + + if closes_issues_references.present? + message << "Closed Issues: #{closes_issues_references.join(", ")}\n\n" + end + message << "See merge request #{to_reference}" message -- cgit v1.2.1 From 00a842eacc4b2ff1514b258fbf08e4017f3be447 Mon Sep 17 00:00:00 2001 From: Gabriel Gizotti Date: Fri, 25 Nov 2016 19:49:56 +1000 Subject: Add toggle links for using default message and description on change merge commit message container --- .../merge_requests/widget/open/_accept.html.haml | 1 + .../shared/_commit_message_container.html.haml | 28 ++++++++++++++++++++++ 2 files changed, 29 insertions(+) (limited to 'app') diff --git a/app/views/projects/merge_requests/widget/open/_accept.html.haml b/app/views/projects/merge_requests/widget/open/_accept.html.haml index 435fe835fae..66096ff7476 100644 --- a/app/views/projects/merge_requests/widget/open/_accept.html.haml +++ b/app/views/projects/merge_requests/widget/open/_accept.html.haml @@ -41,6 +41,7 @@ Modify commit message .js-toggle-content.hide.prepend-top-default = render 'shared/commit_message_container', params: params, + description: @merge_request.description, text: @merge_request.merge_commit_message, rows: 14, hint: true diff --git a/app/views/shared/_commit_message_container.html.haml b/app/views/shared/_commit_message_container.html.haml index 0a38327baa2..adee374413f 100644 --- a/app/views/shared/_commit_message_container.html.haml +++ b/app/views/shared/_commit_message_container.html.haml @@ -14,3 +14,31 @@ %p.hint Try to keep the first line under 52 characters and the others under 72. + - if local_assigns[:description] + %p.hint.use-description-hint + = link_to "#", class: "use-description-link" do + Use Merge Request description as merge commit message + %p.hint.use-default-message-hint.hide + = link_to "#", class: "use-default-message-link" do + Use default Gitlab merge commit message + + + :javascript + $('.use-description-link').on('click', function(e) { + e.preventDefault(); + + $('.use-description-hint').hide(); + $('.use-default-message-hint').show(); + $('.js-commit-message').val("#{escape_javascript local_assigns[:description]}"); + }); + + $('.use-default-message-link').on('click', function(e) { + e.preventDefault(); + + var defaultMessage = "#{escape_javascript (params[:commit_message] || local_assigns[:text] || local_assigns[:placeholder])}"; + + $('.use-description-hint').show(); + $('.use-default-message-hint').hide(); + $('.js-commit-message').val(defaultMessage); + }); + -- cgit v1.2.1 From 1a72dc2486601eadec03122f8124d3b553df3571 Mon Sep 17 00:00:00 2001 From: Gabriel Gizotti Date: Sun, 27 Nov 2016 20:40:56 +1000 Subject: keep branch being merged, MR title and MR reference in merge commit message when using description --- app/views/shared/_commit_message_container.html.haml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/views/shared/_commit_message_container.html.haml b/app/views/shared/_commit_message_container.html.haml index adee374413f..706eef5a331 100644 --- a/app/views/shared/_commit_message_container.html.haml +++ b/app/views/shared/_commit_message_container.html.haml @@ -27,15 +27,21 @@ $('.use-description-link').on('click', function(e) { e.preventDefault(); + var message = "Merge branch '#{j @merge_request.source_branch}' into '#{j @merge_request.target_branch}'\n\n" + message = message + "#{j @merge_request.title}\n\n" + message = message + "#{j local_assigns[:description]}\n\n"; + message = message + "See merge request #{j @merge_request.to_reference}" + + $('.use-description-hint').hide(); $('.use-default-message-hint').show(); - $('.js-commit-message').val("#{escape_javascript local_assigns[:description]}"); + $('.js-commit-message').val(message) }); $('.use-default-message-link').on('click', function(e) { e.preventDefault(); - var defaultMessage = "#{escape_javascript (params[:commit_message] || local_assigns[:text] || local_assigns[:placeholder])}"; + var defaultMessage = "#{j (params[:commit_message] || local_assigns[:text] || local_assigns[:placeholder])}"; $('.use-description-hint').show(); $('.use-default-message-hint').hide(); -- cgit v1.2.1 From d1980ef9c8c059fb9d4be1a8339dea05e9a442f1 Mon Sep 17 00:00:00 2001 From: Gabriel Gizotti Date: Mon, 28 Nov 2016 07:37:57 +1000 Subject: only render MR description toggle javascript if description is available --- .../shared/_commit_message_container.html.haml | 39 +++++++++++----------- 1 file changed, 19 insertions(+), 20 deletions(-) (limited to 'app') diff --git a/app/views/shared/_commit_message_container.html.haml b/app/views/shared/_commit_message_container.html.haml index 706eef5a331..a151731ba0a 100644 --- a/app/views/shared/_commit_message_container.html.haml +++ b/app/views/shared/_commit_message_container.html.haml @@ -14,7 +14,7 @@ %p.hint Try to keep the first line under 52 characters and the others under 72. - - if local_assigns[:description] + - if local_assigns[:description] %p.hint.use-description-hint = link_to "#", class: "use-description-link" do Use Merge Request description as merge commit message @@ -22,29 +22,28 @@ = link_to "#", class: "use-default-message-link" do Use default Gitlab merge commit message + :javascript + $('.use-description-link').on('click', function(e) { + e.preventDefault(); - :javascript - $('.use-description-link').on('click', function(e) { - e.preventDefault(); + var message = "Merge branch '#{j @merge_request.source_branch}' into '#{j @merge_request.target_branch}'\n\n" + message = message + "#{j @merge_request.title}\n\n" + message = message + "#{j local_assigns[:description]}\n\n"; + message = message + "See merge request #{j @merge_request.to_reference}" - var message = "Merge branch '#{j @merge_request.source_branch}' into '#{j @merge_request.target_branch}'\n\n" - message = message + "#{j @merge_request.title}\n\n" - message = message + "#{j local_assigns[:description]}\n\n"; - message = message + "See merge request #{j @merge_request.to_reference}" + $('.use-description-hint').hide(); + $('.use-default-message-hint').show(); + $('.js-commit-message').val(message) + }); - $('.use-description-hint').hide(); - $('.use-default-message-hint').show(); - $('.js-commit-message').val(message) - }); + $('.use-default-message-link').on('click', function(e) { + e.preventDefault(); - $('.use-default-message-link').on('click', function(e) { - e.preventDefault(); + var defaultMessage = "#{j (params[:commit_message] || local_assigns[:text] || local_assigns[:placeholder])}"; - var defaultMessage = "#{j (params[:commit_message] || local_assigns[:text] || local_assigns[:placeholder])}"; - - $('.use-description-hint').show(); - $('.use-default-message-hint').hide(); - $('.js-commit-message').val(defaultMessage); - }); + $('.use-description-hint').show(); + $('.use-default-message-hint').hide(); + $('.js-commit-message').val(defaultMessage); + }); -- cgit v1.2.1 From 512c870ed46b5e441fd0b8daa8bd9cab449f7ac0 Mon Sep 17 00:00:00 2001 From: Gabriel Gizotti Date: Mon, 28 Nov 2016 19:06:18 +1000 Subject: Remove unnecessary code from MergeRequest#issues_mentioned_but_not_closing --- app/models/merge_request.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 5a5b8bd6010..dba0c463fd6 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -573,14 +573,12 @@ class MergeRequest < ActiveRecord::Base closing_issues = [] if target_branch == project.default_branch - messages = [description] - ext = Gitlab::ReferenceExtractor.new(project, current_user) - ext.analyze(messages.join("\n")) + ext.analyze(description) issues = ext.issues closing_issues = Gitlab::ClosingIssueExtractor.new(project, current_user). - closed_by_message(messages.join("\n")) + closed_by_message(description) end issues - closing_issues -- cgit v1.2.1 From 58609f842e1344579ed14745bb6bcb365059166f Mon Sep 17 00:00:00 2001 From: Gabriel Gizotti Date: Mon, 28 Nov 2016 19:48:55 +1000 Subject: backend completely drives creation of merge commit message --- app/models/merge_request.rb | 3 +- .../projects/merge_requests/widget/_open.html.haml | 3 +- .../merge_requests/widget/open/_accept.html.haml | 3 +- .../shared/_commit_message_container.html.haml | 40 ++++++++++------------ 4 files changed, 23 insertions(+), 26 deletions(-) (limited to 'app') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index dba0c463fd6..2d7be2c2c7e 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -628,7 +628,7 @@ class MergeRequest < ActiveRecord::Base self.target_project.repository.branch_names.include?(self.target_branch) end - def merge_commit_message + def merge_commit_message(include_description: false) closes_issues_references = closes_issues.map do |issue| issue.to_reference(target_project) end @@ -640,6 +640,7 @@ class MergeRequest < ActiveRecord::Base message << "Closed Issues: #{closes_issues_references.join(", ")}\n\n" end + message << "#{description}\n\n" if include_description && description.present? message << "See merge request #{to_reference}" message diff --git a/app/views/projects/merge_requests/widget/_open.html.haml b/app/views/projects/merge_requests/widget/_open.html.haml index ebea48a4321..bf1e49c98ce 100644 --- a/app/views/projects/merge_requests/widget/_open.html.haml +++ b/app/views/projects/merge_requests/widget/_open.html.haml @@ -37,12 +37,11 @@ #{"Issue".pluralize(mr_issues_mentioned_but_not_closing.size)} mentioned but not being closed: = succeed '.' do != markdown issues_sentence(mr_issues_mentioned_but_not_closing), pipeline: :gfm, author: @merge_request.author - = mr_assign_issues_link - if mr_closes_issues.present? .mr-widget-footer %span - %i.fa.fa-check + = icon('check') Accepting this merge request will close #{"issue".pluralize(mr_closes_issues.size)} = succeed '.' do != markdown issues_sentence(mr_closes_issues), pipeline: :gfm, author: @merge_request.author diff --git a/app/views/projects/merge_requests/widget/open/_accept.html.haml b/app/views/projects/merge_requests/widget/open/_accept.html.haml index 66096ff7476..d6f7f23533c 100644 --- a/app/views/projects/merge_requests/widget/open/_accept.html.haml +++ b/app/views/projects/merge_requests/widget/open/_accept.html.haml @@ -41,7 +41,8 @@ Modify commit message .js-toggle-content.hide.prepend-top-default = render 'shared/commit_message_container', params: params, - description: @merge_request.description, + message_with_description: @merge_request.merge_commit_message(include_description: true), + message_without_description: @merge_request.merge_commit_message, text: @merge_request.merge_commit_message, rows: 14, hint: true diff --git a/app/views/shared/_commit_message_container.html.haml b/app/views/shared/_commit_message_container.html.haml index a151731ba0a..3e0186983e4 100644 --- a/app/views/shared/_commit_message_container.html.haml +++ b/app/views/shared/_commit_message_container.html.haml @@ -8,42 +8,38 @@ = text_area_tag 'commit_message', (params[:commit_message] || local_assigns[:text] || local_assigns[:placeholder]), class: 'form-control js-commit-message', placeholder: local_assigns[:placeholder], + data: local_assigns.slice(:message_with_description, :message_without_description), required: true, rows: (local_assigns[:rows] || 3), id: "commit_message-#{nonce}" - if local_assigns[:hint] %p.hint Try to keep the first line under 52 characters and the others under 72. - - if local_assigns[:description] - %p.hint.use-description-hint - = link_to "#", class: "use-description-link" do - Use Merge Request description as merge commit message - %p.hint.use-default-message-hint.hide - = link_to "#", class: "use-default-message-link" do - Use default Gitlab merge commit message + -if local_assigns.slice(:message_with_description, :message_without_description).present? + %p.hint.with-description-hint + = link_to "#", class: "with-description-link" do + Include description in commit message + %p.hint.without-description-hint.hide + = link_to "#", class: "without-description-link" do + Don't include description in commit message :javascript - $('.use-description-link').on('click', function(e) { + $('.with-description-link').on('click', function(e) { e.preventDefault(); - var message = "Merge branch '#{j @merge_request.source_branch}' into '#{j @merge_request.target_branch}'\n\n" - message = message + "#{j @merge_request.title}\n\n" - message = message + "#{j local_assigns[:description]}\n\n"; - message = message + "See merge request #{j @merge_request.to_reference}" + var textarea = $('.js-commit-message') - - $('.use-description-hint').hide(); - $('.use-default-message-hint').show(); - $('.js-commit-message').val(message) + textarea.val(textarea.data('messageWithDescription')) + $('.with-description-hint').hide(); + $('.without-description-hint').show(); }); - $('.use-default-message-link').on('click', function(e) { + $('.without-description-link').on('click', function(e) { e.preventDefault(); - var defaultMessage = "#{j (params[:commit_message] || local_assigns[:text] || local_assigns[:placeholder])}"; + var textarea = $('.js-commit-message') - $('.use-description-hint').show(); - $('.use-default-message-hint').hide(); - $('.js-commit-message').val(defaultMessage); + textarea.val(textarea.data('messageWithoutDescription')) + $('.with-description-hint').show(); + $('.without-description-hint').hide(); }); - -- cgit v1.2.1 From e97c7100aed6fb4ca072c80a78b95d5f51805197 Mon Sep 17 00:00:00 2001 From: Gabriel Gizotti Date: Mon, 28 Nov 2016 21:30:25 +1000 Subject: move javascript code from _commit_message_container view to javascripts/merge_request.js --- app/assets/javascripts/merge_request.js | 26 ++++++++++++++++++++++ .../shared/_commit_message_container.html.haml | 21 ----------------- 2 files changed, 26 insertions(+), 21 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/merge_request.js b/app/assets/javascripts/merge_request.js index 70f9a8d1955..309724071d2 100644 --- a/app/assets/javascripts/merge_request.js +++ b/app/assets/javascripts/merge_request.js @@ -27,6 +27,8 @@ // Prevent duplicate event bindings this.disableTaskList(); this.initMRBtnListeners(); + this.initMessageWithDescriptionListener(); + this.initMessageWithoutDescriptionListener(); if ($("a.btn-close").length) { this.initTaskList(); } @@ -108,6 +110,30 @@ // note so that we can re-use its form here }; + MergeRequest.prototype.initMessageWithDescriptionListener = function() { + return $('a.with-description-link').on('click', function(e) { + e.preventDefault(); + + var textarea = $('textarea.js-commit-message'); + + textarea.val(textarea.data('messageWithDescription')); + $('p.with-description-hint').hide(); + $('p.without-description-hint').show(); + }); + }; + + MergeRequest.prototype.initMessageWithoutDescriptionListener = function() { + return $('a.without-description-link').on('click', function(e) { + e.preventDefault(); + + var textarea = $('textarea.js-commit-message'); + + textarea.val(textarea.data('messageWithoutDescription')); + $('p.with-description-hint').show(); + $('p.without-description-hint').hide(); + }); + }; + return MergeRequest; })(); diff --git a/app/views/shared/_commit_message_container.html.haml b/app/views/shared/_commit_message_container.html.haml index 3e0186983e4..803cbb47e55 100644 --- a/app/views/shared/_commit_message_container.html.haml +++ b/app/views/shared/_commit_message_container.html.haml @@ -22,24 +22,3 @@ %p.hint.without-description-hint.hide = link_to "#", class: "without-description-link" do Don't include description in commit message - - :javascript - $('.with-description-link').on('click', function(e) { - e.preventDefault(); - - var textarea = $('.js-commit-message') - - textarea.val(textarea.data('messageWithDescription')) - $('.with-description-hint').hide(); - $('.without-description-hint').show(); - }); - - $('.without-description-link').on('click', function(e) { - e.preventDefault(); - - var textarea = $('.js-commit-message') - - textarea.val(textarea.data('messageWithoutDescription')) - $('.with-description-hint').show(); - $('.without-description-hint').hide(); - }); -- cgit v1.2.1 From 4181528569a81004d4e64f3e9726fc653a322cc7 Mon Sep 17 00:00:00 2001 From: Gabriel Gizotti Date: Mon, 28 Nov 2016 22:11:45 +1000 Subject: Better `Closes issues` text for MergeRequest#merge_commit_message --- app/models/merge_request.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 2d7be2c2c7e..48c30b08502 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -637,7 +637,8 @@ class MergeRequest < ActiveRecord::Base message << "#{title}\n\n" if closes_issues_references.present? - message << "Closed Issues: #{closes_issues_references.join(", ")}\n\n" + issue_text = 'issue'.pluralize(closes_issues_references.size) + message << "Closes #{issue_text} #{closes_issues_references.to_sentence}\n\n" end message << "#{description}\n\n" if include_description && description.present? -- cgit v1.2.1 From 9e321043c72322ae12aba230b49f9da326e66e56 Mon Sep 17 00:00:00 2001 From: Gabriel Gizotti Date: Tue, 29 Nov 2016 07:10:59 +1000 Subject: extract duplicate logic into a variable on _commit_message_container --- app/views/shared/_commit_message_container.html.haml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/views/shared/_commit_message_container.html.haml b/app/views/shared/_commit_message_container.html.haml index 803cbb47e55..2b2da446d09 100644 --- a/app/views/shared/_commit_message_container.html.haml +++ b/app/views/shared/_commit_message_container.html.haml @@ -1,5 +1,6 @@ .form-group.commit_message-group - nonce = SecureRandom.hex + - descriptions = local_assigns.slice(:message_with_description, :message_without_description) = label_tag "commit_message-#{nonce}", class: 'control-label' do Commit message .col-sm-10 @@ -8,14 +9,14 @@ = text_area_tag 'commit_message', (params[:commit_message] || local_assigns[:text] || local_assigns[:placeholder]), class: 'form-control js-commit-message', placeholder: local_assigns[:placeholder], - data: local_assigns.slice(:message_with_description, :message_without_description), + data: descriptions, required: true, rows: (local_assigns[:rows] || 3), id: "commit_message-#{nonce}" - if local_assigns[:hint] %p.hint Try to keep the first line under 52 characters and the others under 72. - -if local_assigns.slice(:message_with_description, :message_without_description).present? + - if descriptions.present? %p.hint.with-description-hint = link_to "#", class: "with-description-link" do Include description in commit message -- cgit v1.2.1 From fedba9fc2568ec784eddbe6aff0fc9ca5f95b116 Mon Sep 17 00:00:00 2001 From: Gabriel Gizotti Date: Tue, 29 Nov 2016 07:29:15 +1000 Subject: add mentioned but not closed message to the same line as closes issueswq --- .../projects/merge_requests/widget/_open.html.haml | 27 +++++++++++----------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'app') diff --git a/app/views/projects/merge_requests/widget/_open.html.haml b/app/views/projects/merge_requests/widget/_open.html.haml index bf1e49c98ce..4aae3ba63a9 100644 --- a/app/views/projects/merge_requests/widget/_open.html.haml +++ b/app/views/projects/merge_requests/widget/_open.html.haml @@ -30,19 +30,20 @@ - elsif @merge_request.can_be_merged? || resolved_conflicts = render 'projects/merge_requests/widget/open/accept' - - if mr_issues_mentioned_but_not_closing.present? - .mr-widget-footer - %span - %i.fa.fa-info-circle - #{"Issue".pluralize(mr_issues_mentioned_but_not_closing.size)} mentioned but not being closed: - = succeed '.' do - != markdown issues_sentence(mr_issues_mentioned_but_not_closing), pipeline: :gfm, author: @merge_request.author - - - if mr_closes_issues.present? + - if mr_closes_issues.present? || mr_issues_mentioned_but_not_closing .mr-widget-footer %span = icon('check') - Accepting this merge request will close #{"issue".pluralize(mr_closes_issues.size)} - = succeed '.' do - != markdown issues_sentence(mr_closes_issues), pipeline: :gfm, author: @merge_request.author - = mr_assign_issues_link + - if mr_closes_issues.present? + Accepting this merge request will close #{"issue".pluralize(mr_closes_issues.size)} + = succeed '.' do + != markdown issues_sentence(mr_closes_issues), pipeline: :gfm, author: @merge_request.author + = mr_assign_issues_link + - if mr_issues_mentioned_but_not_closing.present? + #{"Issue".pluralize(mr_issues_mentioned_but_not_closing.size)} + = succeed '' do + != markdown issues_sentence(mr_issues_mentioned_but_not_closing), pipeline: :gfm, author: @merge_request.author + = succeed '' do + mentioned but not closed. + + -- cgit v1.2.1 From 943ef94912410dd028626711c97cd1ae881a5e4c Mon Sep 17 00:00:00 2001 From: Gabriel Gizotti Date: Tue, 29 Nov 2016 07:30:55 +1000 Subject: better text for mentioned but not closed --- app/views/projects/merge_requests/widget/_open.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/projects/merge_requests/widget/_open.html.haml b/app/views/projects/merge_requests/widget/_open.html.haml index 4aae3ba63a9..695359a48a3 100644 --- a/app/views/projects/merge_requests/widget/_open.html.haml +++ b/app/views/projects/merge_requests/widget/_open.html.haml @@ -44,6 +44,6 @@ = succeed '' do != markdown issues_sentence(mr_issues_mentioned_but_not_closing), pipeline: :gfm, author: @merge_request.author = succeed '' do - mentioned but not closed. + mentioned but will not closed. -- cgit v1.2.1 From 99dd58ec557779eadd83aa597d8c16996be60df1 Mon Sep 17 00:00:00 2001 From: Gabriel Gizotti Date: Mon, 5 Dec 2016 20:46:43 +1000 Subject: Unify commit message listeners in one function --- app/assets/javascripts/merge_request.js | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/merge_request.js b/app/assets/javascripts/merge_request.js index 309724071d2..194a27ae22b 100644 --- a/app/assets/javascripts/merge_request.js +++ b/app/assets/javascripts/merge_request.js @@ -27,8 +27,7 @@ // Prevent duplicate event bindings this.disableTaskList(); this.initMRBtnListeners(); - this.initMessageWithDescriptionListener(); - this.initMessageWithoutDescriptionListener(); + this.initCommitMessageListeners(); if ($("a.btn-close").length) { this.initTaskList(); } @@ -110,24 +109,20 @@ // note so that we can re-use its form here }; - MergeRequest.prototype.initMessageWithDescriptionListener = function() { - return $('a.with-description-link').on('click', function(e) { - e.preventDefault(); + MergeRequest.prototype.initCommitMessageListeners = function() { + var textarea = $('textarea.js-commit-message'); - var textarea = $('textarea.js-commit-message'); + $('a.with-description-link').on('click', function(e) { + e.preventDefault(); textarea.val(textarea.data('messageWithDescription')); $('p.with-description-hint').hide(); $('p.without-description-hint').show(); }); - }; - MergeRequest.prototype.initMessageWithoutDescriptionListener = function() { - return $('a.without-description-link').on('click', function(e) { + $('a.without-description-link').on('click', function(e) { e.preventDefault(); - var textarea = $('textarea.js-commit-message'); - textarea.val(textarea.data('messageWithoutDescription')); $('p.with-description-hint').show(); $('p.without-description-hint').hide(); -- cgit v1.2.1 From 603ef5d49ed453cbb47b68d3af078529c6b834a1 Mon Sep 17 00:00:00 2001 From: Gabriel Gizotti Date: Mon, 5 Dec 2016 21:29:17 +1000 Subject: Show either description or closes issues references on MergeRequest#merge_commit_message so closes issues references are not duplicated --- app/models/merge_request.rb | 14 ++++++++------ app/views/projects/merge_requests/widget/_open.html.haml | 8 +++----- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'app') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 48c30b08502..da293c3738f 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -633,18 +633,20 @@ class MergeRequest < ActiveRecord::Base issue.to_reference(target_project) end - message = "Merge branch '#{source_branch}' into '#{target_branch}'\n\n" - message << "#{title}\n\n" + message = [ + "Merge branch '#{source_branch}' into '#{target_branch}'", + title + ] - if closes_issues_references.present? + if !include_description && closes_issues_references.present? issue_text = 'issue'.pluralize(closes_issues_references.size) - message << "Closes #{issue_text} #{closes_issues_references.to_sentence}\n\n" + message << "Closes #{issue_text} #{closes_issues_references.to_sentence}" end - message << "#{description}\n\n" if include_description && description.present? + message << "#{description}" if include_description && description.present? message << "See merge request #{to_reference}" - message + message.join("\n\n") end def reset_merge_when_build_succeeds diff --git a/app/views/projects/merge_requests/widget/_open.html.haml b/app/views/projects/merge_requests/widget/_open.html.haml index 695359a48a3..f4aa1609a1b 100644 --- a/app/views/projects/merge_requests/widget/_open.html.haml +++ b/app/views/projects/merge_requests/widget/_open.html.haml @@ -30,7 +30,7 @@ - elsif @merge_request.can_be_merged? || resolved_conflicts = render 'projects/merge_requests/widget/open/accept' - - if mr_closes_issues.present? || mr_issues_mentioned_but_not_closing + - if mr_closes_issues.present? || mr_issues_mentioned_but_not_closing.present? .mr-widget-footer %span = icon('check') @@ -41,9 +41,7 @@ = mr_assign_issues_link - if mr_issues_mentioned_but_not_closing.present? #{"Issue".pluralize(mr_issues_mentioned_but_not_closing.size)} - = succeed '' do - != markdown issues_sentence(mr_issues_mentioned_but_not_closing), pipeline: :gfm, author: @merge_request.author - = succeed '' do - mentioned but will not closed. + != markdown issues_sentence(mr_issues_mentioned_but_not_closing), pipeline: :gfm, author: @merge_request.author + #{mr_issues_mentioned_but_not_closing.size > 1 ? 'are' : 'is'} mentioned but will not closed. -- cgit v1.2.1 From 5d478e5ceec3db9c38ef2ab1fafd7235fe3bb244 Mon Sep 17 00:00:00 2001 From: Gabriel Gizotti Date: Mon, 5 Dec 2016 21:43:40 +1000 Subject: add js prefix to classes used to toggle description on commit message in merge request --- app/assets/javascripts/merge_request.js | 12 ++++++------ app/views/shared/_commit_message_container.html.haml | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/merge_request.js b/app/assets/javascripts/merge_request.js index 194a27ae22b..462dbc44e9f 100644 --- a/app/assets/javascripts/merge_request.js +++ b/app/assets/javascripts/merge_request.js @@ -112,20 +112,20 @@ MergeRequest.prototype.initCommitMessageListeners = function() { var textarea = $('textarea.js-commit-message'); - $('a.with-description-link').on('click', function(e) { + $('a.js-with-description-link').on('click', function(e) { e.preventDefault(); textarea.val(textarea.data('messageWithDescription')); - $('p.with-description-hint').hide(); - $('p.without-description-hint').show(); + $('p.js-with-description-hint').hide(); + $('p.js-without-description-hint').show(); }); - $('a.without-description-link').on('click', function(e) { + $('a.js-without-description-link').on('click', function(e) { e.preventDefault(); textarea.val(textarea.data('messageWithoutDescription')); - $('p.with-description-hint').show(); - $('p.without-description-hint').hide(); + $('p.js-with-description-hint').show(); + $('p.js-without-description-hint').hide(); }); }; diff --git a/app/views/shared/_commit_message_container.html.haml b/app/views/shared/_commit_message_container.html.haml index 2b2da446d09..c196bc06b17 100644 --- a/app/views/shared/_commit_message_container.html.haml +++ b/app/views/shared/_commit_message_container.html.haml @@ -17,9 +17,9 @@ Try to keep the first line under 52 characters and the others under 72. - if descriptions.present? - %p.hint.with-description-hint - = link_to "#", class: "with-description-link" do + %p.hint.js-with-description-hint + = link_to "#", class: "js-with-description-link" do Include description in commit message - %p.hint.without-description-hint.hide - = link_to "#", class: "without-description-link" do + %p.hint.js-without-description-hint.hide + = link_to "#", class: "js-without-description-link" do Don't include description in commit message -- cgit v1.2.1 From 7d7ae494d476f2e0588740612846da4284b3da0c Mon Sep 17 00:00:00 2001 From: Gabriel Gizotti Date: Mon, 5 Dec 2016 21:44:29 +1000 Subject: add guard clause to MergeRequest#issues_mentioned_but_not_closing --- app/models/merge_request.rb | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'app') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index da293c3738f..acaf14a12e9 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -569,17 +569,14 @@ class MergeRequest < ActiveRecord::Base end def issues_mentioned_but_not_closing(current_user = self.author) - issues = [] - closing_issues = [] + return [] unless target_branch == project.default_branch - if target_branch == project.default_branch - ext = Gitlab::ReferenceExtractor.new(project, current_user) - ext.analyze(description) + ext = Gitlab::ReferenceExtractor.new(project, current_user) + ext.analyze(description) - issues = ext.issues - closing_issues = Gitlab::ClosingIssueExtractor.new(project, current_user). - closed_by_message(description) - end + issues = ext.issues + closing_issues = Gitlab::ClosingIssueExtractor.new(project, current_user). + closed_by_message(description) issues - closing_issues end -- cgit v1.2.1 From 4525cdaec3f9af4a38711137b5fcdcff68cd7d1a Mon Sep 17 00:00:00 2001 From: Gabriel Gizotti Date: Thu, 8 Dec 2016 21:39:16 +1000 Subject: add eslint disable prefix for prefer-arrow-callback rule on header of merge_request.js file --- app/assets/javascripts/merge_request.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/merge_request.js b/app/assets/javascripts/merge_request.js index 462dbc44e9f..244c2f6746c 100644 --- a/app/assets/javascripts/merge_request.js +++ b/app/assets/javascripts/merge_request.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, quotes, no-underscore-dangle, one-var, one-var-declaration-per-line, consistent-return, dot-notation, quote-props, comma-dangle, object-shorthand, padded-blocks, max-len */ +/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, quotes, no-underscore-dangle, one-var, one-var-declaration-per-line, consistent-return, dot-notation, quote-props, comma-dangle, object-shorthand, padded-blocks, max-len, prefer-arrow-callback */ /* global MergeRequestTabs */ /*= require jquery.waitforimages */ -- cgit v1.2.1 From 3e3d6b53dcdc50bbe45c4b3ff43faf3d2728f72c Mon Sep 17 00:00:00 2001 From: Gabriel Gizotti Date: Tue, 13 Dec 2016 23:00:00 +1000 Subject: Change closes issues reference text on MergeRequest#merge_commit_message to match existing text generated by the system --- app/models/merge_request.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'app') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index acaf14a12e9..b7c775777c7 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -636,8 +636,7 @@ class MergeRequest < ActiveRecord::Base ] if !include_description && closes_issues_references.present? - issue_text = 'issue'.pluralize(closes_issues_references.size) - message << "Closes #{issue_text} #{closes_issues_references.to_sentence}" + message << "Closes #{closes_issues_references.to_sentence}" end message << "#{description}" if include_description && description.present? -- cgit v1.2.1 From 1d0ccec6dd8375b751846f69bb170ebd11e9a391 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Tue, 22 Nov 2016 14:23:53 +0530 Subject: Add a `scopes` column to the `personal_access_tokens` table --- app/models/personal_access_token.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app') diff --git a/app/models/personal_access_token.rb b/app/models/personal_access_token.rb index c4b095e0c04..10a34c42fd8 100644 --- a/app/models/personal_access_token.rb +++ b/app/models/personal_access_token.rb @@ -2,6 +2,8 @@ class PersonalAccessToken < ActiveRecord::Base include TokenAuthenticatable add_authentication_token_field :token + serialize :scopes, Array + belongs_to :user scope :active, -> { where(revoked: false).where("expires_at >= NOW() OR expires_at IS NULL") } -- cgit v1.2.1 From 6c809dfae84e702f7a49d3fac5725745264e0ff9 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Tue, 22 Nov 2016 14:27:31 +0530 Subject: Allow creating personal access tokens / OAuth applications with scopes. --- app/assets/stylesheets/pages/profile.scss | 10 ++++++++++ app/controllers/admin/applications_controller.rb | 6 +++++- app/controllers/concerns/oauth_applications.rb | 14 ++++++++++++++ app/controllers/oauth/applications_controller.rb | 6 ++++++ .../profiles/personal_access_tokens_controller.rb | 12 ++++++------ app/views/admin/applications/_form.html.haml | 10 ++++++++++ app/views/admin/applications/show.html.haml | 15 +++++++++++++-- app/views/doorkeeper/applications/_form.html.haml | 9 +++++++++ app/views/doorkeeper/applications/show.html.haml | 15 ++++++++++++++- .../personal_access_tokens/_form.html.haml | 22 ++++++++++++++++++++++ .../personal_access_tokens/index.html.haml | 17 +++-------------- 11 files changed, 112 insertions(+), 24 deletions(-) create mode 100644 app/controllers/concerns/oauth_applications.rb create mode 100644 app/views/profiles/personal_access_tokens/_form.html.haml (limited to 'app') diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss index 8a5b0e20a86..8b1976bd925 100644 --- a/app/assets/stylesheets/pages/profile.scss +++ b/app/assets/stylesheets/pages/profile.scss @@ -262,3 +262,13 @@ table.u2f-registrations { border-right: solid 1px transparent; } } + +.oauth-application-show { + .scope-name { + font-weight: 600; + } + + .scopes-list { + padding-left: 18px; + } +} \ No newline at end of file diff --git a/app/controllers/admin/applications_controller.rb b/app/controllers/admin/applications_controller.rb index 471d24934a0..759044910bb 100644 --- a/app/controllers/admin/applications_controller.rb +++ b/app/controllers/admin/applications_controller.rb @@ -1,4 +1,6 @@ class Admin::ApplicationsController < Admin::ApplicationController + include OauthApplications + before_action :set_application, only: [:show, :edit, :update, :destroy] def index @@ -10,9 +12,11 @@ class Admin::ApplicationsController < Admin::ApplicationController def new @application = Doorkeeper::Application.new + @scopes = Doorkeeper.configuration.scopes end def edit + @scopes = Doorkeeper.configuration.scopes end def create @@ -47,6 +51,6 @@ class Admin::ApplicationsController < Admin::ApplicationController # Only allow a trusted parameter "white list" through. def application_params - params[:doorkeeper_application].permit(:name, :redirect_uri) + params[:doorkeeper_application].permit(:name, :redirect_uri, :scopes) end end diff --git a/app/controllers/concerns/oauth_applications.rb b/app/controllers/concerns/oauth_applications.rb new file mode 100644 index 00000000000..34ad43ededd --- /dev/null +++ b/app/controllers/concerns/oauth_applications.rb @@ -0,0 +1,14 @@ +module OauthApplications + extend ActiveSupport::Concern + + included do + before_action :prepare_scopes, only: [:create, :update] + end + + def prepare_scopes + scopes = params.dig(:doorkeeper_application, :scopes) + if scopes + params[:doorkeeper_application][:scopes] = scopes.join(' ') + end + end +end diff --git a/app/controllers/oauth/applications_controller.rb b/app/controllers/oauth/applications_controller.rb index 0f54dfa4efc..b5449a6c30e 100644 --- a/app/controllers/oauth/applications_controller.rb +++ b/app/controllers/oauth/applications_controller.rb @@ -2,6 +2,7 @@ class Oauth::ApplicationsController < Doorkeeper::ApplicationsController include Gitlab::CurrentSettings include Gitlab::GonHelper include PageLayoutHelper + include OauthApplications before_action :verify_user_oauth_applications_enabled before_action :authenticate_user! @@ -13,6 +14,10 @@ class Oauth::ApplicationsController < Doorkeeper::ApplicationsController set_index_vars end + def edit + @scopes = Doorkeeper.configuration.scopes + end + def create @application = Doorkeeper::Application.new(application_params) @@ -40,6 +45,7 @@ class Oauth::ApplicationsController < Doorkeeper::ApplicationsController @authorized_tokens = current_user.oauth_authorized_tokens @authorized_anonymous_tokens = @authorized_tokens.reject(&:application) @authorized_apps = @authorized_tokens.map(&:application).uniq.reject(&:nil?) + @scopes = Doorkeeper.configuration.scopes # Don't overwrite a value possibly set by `create` @application ||= Doorkeeper::Application.new diff --git a/app/controllers/profiles/personal_access_tokens_controller.rb b/app/controllers/profiles/personal_access_tokens_controller.rb index 508b82a9a6c..6e007f17913 100644 --- a/app/controllers/profiles/personal_access_tokens_controller.rb +++ b/app/controllers/profiles/personal_access_tokens_controller.rb @@ -1,8 +1,6 @@ class Profiles::PersonalAccessTokensController < Profiles::ApplicationController - before_action :load_personal_access_tokens, only: :index - def index - @personal_access_token = current_user.personal_access_tokens.build + set_index_vars end def create @@ -12,7 +10,7 @@ class Profiles::PersonalAccessTokensController < Profiles::ApplicationController flash[:personal_access_token] = @personal_access_token.token redirect_to profile_personal_access_tokens_path, notice: "Your new personal access token has been created." else - load_personal_access_tokens + set_index_vars render :index end end @@ -32,10 +30,12 @@ class Profiles::PersonalAccessTokensController < Profiles::ApplicationController private def personal_access_token_params - params.require(:personal_access_token).permit(:name, :expires_at) + params.require(:personal_access_token).permit(:name, :expires_at, scopes: []) end - def load_personal_access_tokens + def set_index_vars + @personal_access_token ||= current_user.personal_access_tokens.build + @scopes = Gitlab::Auth::SCOPES @active_personal_access_tokens = current_user.personal_access_tokens.active.order(:expires_at) @inactive_personal_access_tokens = current_user.personal_access_tokens.inactive end diff --git a/app/views/admin/applications/_form.html.haml b/app/views/admin/applications/_form.html.haml index 4aacbb8cd77..36d2f415a05 100644 --- a/app/views/admin/applications/_form.html.haml +++ b/app/views/admin/applications/_form.html.haml @@ -18,6 +18,16 @@ Use %code= Doorkeeper.configuration.native_redirect_uri for local tests + + .form-group + = f.label :scopes, class: 'col-sm-2 control-label' + .col-sm-10 + - @scopes.each do |scope| + %fieldset + = check_box_tag 'doorkeeper_application[scopes][]', scope, application.scopes.include?(scope), id: "doorkeeper_application_scopes_#{scope}" + = label_tag "doorkeeper_application_scopes_#{scope}", scope + %span= "(#{t(scope, scope: [:doorkeeper, :scopes])})" + .form-actions = f.submit 'Submit', class: "btn btn-save wide" = link_to "Cancel", admin_applications_path, class: "btn btn-default" diff --git a/app/views/admin/applications/show.html.haml b/app/views/admin/applications/show.html.haml index 3eb9d61972b..3418dc96496 100644 --- a/app/views/admin/applications/show.html.haml +++ b/app/views/admin/applications/show.html.haml @@ -2,8 +2,7 @@ %h3.page-title Application: #{@application.name} - -.table-holder +.table-holder.oauth-application-show %table.table %tr %td @@ -23,6 +22,18 @@ - @application.redirect_uri.split.each do |uri| %div %span.monospace= uri + + - if @application.scopes.present? + %tr + %td + Scopes + %td + %ul.scopes-list.append-bottom-0 + - @application.scopes.each do |scope| + %li + %span.scope-name= scope + = "(#{t(scope, scope: [:doorkeeper, :scopes])})" + .form-actions = link_to 'Edit', edit_admin_application_path(@application), class: 'btn btn-primary wide pull-left' = render 'delete_form', application: @application, submit_btn_css: 'btn btn-danger prepend-left-10' diff --git a/app/views/doorkeeper/applications/_form.html.haml b/app/views/doorkeeper/applications/_form.html.haml index 5c98265727a..6fdb04077b6 100644 --- a/app/views/doorkeeper/applications/_form.html.haml +++ b/app/views/doorkeeper/applications/_form.html.haml @@ -17,5 +17,14 @@ %code= Doorkeeper.configuration.native_redirect_uri for local tests + .form-group + = f.label :scopes, class: 'label-light' + - @scopes.each do |scope| + %fieldset + = check_box_tag 'doorkeeper_application[scopes][]', scope, application.scopes.include?(scope), id: "doorkeeper_application_scopes_#{scope}" + = label_tag "doorkeeper_application_scopes_#{scope}", scope + %span= "(#{t(scope, scope: [:doorkeeper, :scopes])})" + + .prepend-top-default = f.submit 'Save application', class: "btn btn-create" diff --git a/app/views/doorkeeper/applications/show.html.haml b/app/views/doorkeeper/applications/show.html.haml index 47442b78d48..a18e133c8de 100644 --- a/app/views/doorkeeper/applications/show.html.haml +++ b/app/views/doorkeeper/applications/show.html.haml @@ -2,7 +2,7 @@ %h3.page-title Application: #{@application.name} -.table-holder +.table-holder.oauth-application-show %table.table %tr %td @@ -22,6 +22,19 @@ - @application.redirect_uri.split.each do |uri| %div %span.monospace= uri + + - if @application.scopes.present? + %tr + %td + Scopes + %td + %ul.scopes-list.append-bottom-0 + - @application.scopes.each do |scope| + %li + %span.scope-name= scope + = "(#{t(scope, scope: [:doorkeeper, :scopes])})" + + .form-actions = link_to 'Edit', edit_oauth_application_path(@application), class: 'btn btn-primary wide pull-left' = render 'delete_form', application: @application, submit_btn_css: 'btn btn-danger prepend-left-10' diff --git a/app/views/profiles/personal_access_tokens/_form.html.haml b/app/views/profiles/personal_access_tokens/_form.html.haml new file mode 100644 index 00000000000..6083fdaa31d --- /dev/null +++ b/app/views/profiles/personal_access_tokens/_form.html.haml @@ -0,0 +1,22 @@ += form_for [:profile, @personal_access_token], method: :post, html: { class: 'js-requires-input' } do |f| + + = form_errors(@personal_access_token) + + .form-group + = f.label :name, class: 'label-light' + = f.text_field :name, class: "form-control", required: true + + .form-group + = f.label :expires_at, class: 'label-light' + = f.text_field :expires_at, class: "datepicker form-control", required: false + + .form-group + = f.label :scopes, class: 'label-light' + - @scopes.each do |scope| + %fieldset + = check_box_tag 'personal_access_token[scopes][]', scope, @personal_access_token.scopes.include?(scope), id: "personal_access_token_scopes_#{scope}" + = label_tag "personal_access_token_scopes_#{scope}", scope + %span= "(#{t(scope, scope: [:doorkeeper, :scopes])})" + + .prepend-top-default + = f.submit 'Create Personal Access Token', class: "btn btn-create" diff --git a/app/views/profiles/personal_access_tokens/index.html.haml b/app/views/profiles/personal_access_tokens/index.html.haml index 05a2ea67aa2..39eef0f6baf 100644 --- a/app/views/profiles/personal_access_tokens/index.html.haml +++ b/app/views/profiles/personal_access_tokens/index.html.haml @@ -28,21 +28,8 @@ Add a Personal Access Token %p.profile-settings-content Pick a name for the application, and we'll give you a unique token. - = form_for [:profile, @personal_access_token], - method: :post, html: { class: 'js-requires-input' } do |f| - = form_errors(@personal_access_token) - - .form-group - = f.label :name, class: 'label-light' - = f.text_field :name, class: "form-control", required: true - - .form-group - = f.label :expires_at, class: 'label-light' - = f.text_field :expires_at, class: "datepicker form-control", required: false - - .prepend-top-default - = f.submit 'Create Personal Access Token', class: "btn btn-create" + = render "form" %hr @@ -56,6 +43,7 @@ %th Name %th Created %th Expires + %th Scopes %th %tbody - @active_personal_access_tokens.each do |token| @@ -67,6 +55,7 @@ = token.expires_at.to_date.to_s(:medium) - else %span.personal-access-tokens-never-expires-label Never + %td= token.scopes.present? ? token.scopes.join(", ") : "" %td= link_to "Revoke", revoke_profile_personal_access_token_path(token), method: :put, class: "btn btn-danger pull-right", data: { confirm: "Are you sure you want to revoke this token? This action cannot be undone." } - else -- cgit v1.2.1 From 9f97fa4d9f4e86e8f1ff1db4621bcf81390936da Mon Sep 17 00:00:00 2001 From: Mark Fletcher Date: Wed, 14 Dec 2016 20:45:39 +0000 Subject: Ensure issuable state changes only fire webhooks once * Webhooks for close and reopen events now fired in respective services only * Prevents generic 'update' webhooks firing too --- app/services/issuable_base_service.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/services/issuable_base_service.rb b/app/services/issuable_base_service.rb index b5f63cc5a1a..ab3d2a9a0cd 100644 --- a/app/services/issuable_base_service.rb +++ b/app/services/issuable_base_service.rb @@ -184,7 +184,8 @@ class IssuableBaseService < BaseService old_labels = issuable.labels.to_a old_mentioned_users = issuable.mentioned_users.to_a - params[:label_ids] = process_label_ids(params, existing_label_ids: issuable.label_ids) + label_ids = process_label_ids(params, existing_label_ids: issuable.label_ids) + params[:label_ids] = label_ids if labels_changing?(issuable.label_ids, label_ids) if params.present? && update_issuable(issuable, params) # We do not touch as it will affect a update on updated_at field @@ -201,6 +202,10 @@ class IssuableBaseService < BaseService issuable end + def labels_changing?(old_label_ids, new_label_ids) + old_label_ids.sort != new_label_ids.sort + end + def change_state(issuable) case params.delete(:state_event) when 'reopen' -- cgit v1.2.1 From 2490f804cd4c12533fd6c70fc8014a06f2d19d47 Mon Sep 17 00:00:00 2001 From: Dimitrie Hoekstra Date: Fri, 16 Dec 2016 11:59:10 +0100 Subject: Additional rounded label fixes --- app/assets/stylesheets/framework/variables.scss | 2 +- app/assets/stylesheets/pages/labels.scss | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 936aaf38254..d201a538195 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -436,7 +436,7 @@ $jq-ui-default-color: #777; $label-gray-bg: #f8fafc; $label-inverse-bg: #333; $label-remove-border: rgba(0, 0, 0, .1); -$label-border-radius: 14px; +$label-border-radius: 100px; /* * Lint diff --git a/app/assets/stylesheets/pages/labels.scss b/app/assets/stylesheets/pages/labels.scss index 25c91203ff4..703a429d63c 100644 --- a/app/assets/stylesheets/pages/labels.scss +++ b/app/assets/stylesheets/pages/labels.scss @@ -98,7 +98,7 @@ } .label { - padding: 9px; + padding: 8px 9px 9px 9px; font-size: 14px; } } @@ -201,6 +201,8 @@ .label-remove { border-left: 1px solid $label-remove-border; z-index: 3; + border-radius: $label-border-radius; + padding: 6px 10px 6px 9px; } .btn { -- cgit v1.2.1 From 7fa06ed55d18af4d055041eb27d38fecf9b5548f Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Tue, 22 Nov 2016 14:34:23 +0530 Subject: Calls to the API are checked for scope. - Move the `Oauth2::AccessTokenValidationService` class to `AccessTokenValidationService`, since it is now being used for personal access token validation as well. - Each API endpoint declares the scopes it accepts (if any). Currently, the top level API module declares the `api` scope, and the `Users` API module declares the `read_user` scope (for GET requests). - Move the `find_user_by_private_token` from the API `Helpers` module to the `APIGuard` module, to avoid littering `Helpers` with more auth-related methods to support `find_user_by_private_token` --- app/services/access_token_validation_service.rb | 34 ++++++++++++++++++ .../oauth2/access_token_validation_service.rb | 42 ---------------------- 2 files changed, 34 insertions(+), 42 deletions(-) create mode 100644 app/services/access_token_validation_service.rb delete mode 100644 app/services/oauth2/access_token_validation_service.rb (limited to 'app') diff --git a/app/services/access_token_validation_service.rb b/app/services/access_token_validation_service.rb new file mode 100644 index 00000000000..69449f3a445 --- /dev/null +++ b/app/services/access_token_validation_service.rb @@ -0,0 +1,34 @@ +module AccessTokenValidationService + # Results: + VALID = :valid + EXPIRED = :expired + REVOKED = :revoked + INSUFFICIENT_SCOPE = :insufficient_scope + + class << self + def validate(token, scopes: []) + if token.expired? + return EXPIRED + + elsif token.revoked? + return REVOKED + + elsif !self.sufficient_scope?(token, scopes) + return INSUFFICIENT_SCOPE + + else + return VALID + end + end + + # True if the token's scope contains any of the required scopes. + def sufficient_scope?(token, required_scopes) + if required_scopes.blank? + true + else + # Check whether the token is allowed access to any of the required scopes. + Set.new(required_scopes).intersection(Set.new(token.scopes)).present? + end + end + end +end diff --git a/app/services/oauth2/access_token_validation_service.rb b/app/services/oauth2/access_token_validation_service.rb deleted file mode 100644 index 264fdccde8f..00000000000 --- a/app/services/oauth2/access_token_validation_service.rb +++ /dev/null @@ -1,42 +0,0 @@ -module Oauth2::AccessTokenValidationService - # Results: - VALID = :valid - EXPIRED = :expired - REVOKED = :revoked - INSUFFICIENT_SCOPE = :insufficient_scope - - class << self - def validate(token, scopes: []) - if token.expired? - return EXPIRED - - elsif token.revoked? - return REVOKED - - elsif !self.sufficient_scope?(token, scopes) - return INSUFFICIENT_SCOPE - - else - return VALID - end - end - - protected - - # True if the token's scope is a superset of required scopes, - # or the required scopes is empty. - def sufficient_scope?(token, scopes) - if scopes.blank? - # if no any scopes required, the scopes of token is sufficient. - return true - else - # If there are scopes required, then check whether - # the set of authorized scopes is a superset of the set of required scopes - required_scopes = Set.new(scopes) - authorized_scopes = Set.new(token.scopes) - - return authorized_scopes >= required_scopes - end - end - end -end -- cgit v1.2.1 From 4d6da770de94f4bf140507cdf43461b67269ce28 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Thu, 24 Nov 2016 13:07:22 +0530 Subject: Implement minor changes from @dbalexandre's review. - Mainly whitespace changes. - Require the migration adding the `scope` column to the `personal_access_tokens` table to have downtime, since API calls will fail if the new code is in place, but the migration hasn't run. - Minor refactoring - load `@scopes` in a `before_action`, since we're doing it in three different places. --- app/controllers/admin/applications_controller.rb | 3 +-- app/controllers/concerns/oauth_applications.rb | 5 +++++ app/controllers/oauth/applications_controller.rb | 6 +----- app/views/doorkeeper/applications/_form.html.haml | 1 - app/views/doorkeeper/applications/show.html.haml | 1 - 5 files changed, 7 insertions(+), 9 deletions(-) (limited to 'app') diff --git a/app/controllers/admin/applications_controller.rb b/app/controllers/admin/applications_controller.rb index 759044910bb..62f62e99a97 100644 --- a/app/controllers/admin/applications_controller.rb +++ b/app/controllers/admin/applications_controller.rb @@ -2,6 +2,7 @@ class Admin::ApplicationsController < Admin::ApplicationController include OauthApplications before_action :set_application, only: [:show, :edit, :update, :destroy] + before_action :load_scopes, only: [:new, :edit] def index @applications = Doorkeeper::Application.where("owner_id IS NULL") @@ -12,11 +13,9 @@ class Admin::ApplicationsController < Admin::ApplicationController def new @application = Doorkeeper::Application.new - @scopes = Doorkeeper.configuration.scopes end def edit - @scopes = Doorkeeper.configuration.scopes end def create diff --git a/app/controllers/concerns/oauth_applications.rb b/app/controllers/concerns/oauth_applications.rb index 34ad43ededd..7210ed3eb32 100644 --- a/app/controllers/concerns/oauth_applications.rb +++ b/app/controllers/concerns/oauth_applications.rb @@ -7,8 +7,13 @@ module OauthApplications def prepare_scopes scopes = params.dig(:doorkeeper_application, :scopes) + if scopes params[:doorkeeper_application][:scopes] = scopes.join(' ') end end + + def load_scopes + @scopes = Doorkeeper.configuration.scopes + end end diff --git a/app/controllers/oauth/applications_controller.rb b/app/controllers/oauth/applications_controller.rb index b5449a6c30e..2ae4785b12c 100644 --- a/app/controllers/oauth/applications_controller.rb +++ b/app/controllers/oauth/applications_controller.rb @@ -7,6 +7,7 @@ class Oauth::ApplicationsController < Doorkeeper::ApplicationsController before_action :verify_user_oauth_applications_enabled before_action :authenticate_user! before_action :add_gon_variables + before_action :load_scopes, only: [:index, :create, :edit] layout 'profile' @@ -14,10 +15,6 @@ class Oauth::ApplicationsController < Doorkeeper::ApplicationsController set_index_vars end - def edit - @scopes = Doorkeeper.configuration.scopes - end - def create @application = Doorkeeper::Application.new(application_params) @@ -45,7 +42,6 @@ class Oauth::ApplicationsController < Doorkeeper::ApplicationsController @authorized_tokens = current_user.oauth_authorized_tokens @authorized_anonymous_tokens = @authorized_tokens.reject(&:application) @authorized_apps = @authorized_tokens.map(&:application).uniq.reject(&:nil?) - @scopes = Doorkeeper.configuration.scopes # Don't overwrite a value possibly set by `create` @application ||= Doorkeeper::Application.new diff --git a/app/views/doorkeeper/applications/_form.html.haml b/app/views/doorkeeper/applications/_form.html.haml index 6fdb04077b6..96677dc1a4d 100644 --- a/app/views/doorkeeper/applications/_form.html.haml +++ b/app/views/doorkeeper/applications/_form.html.haml @@ -25,6 +25,5 @@ = label_tag "doorkeeper_application_scopes_#{scope}", scope %span= "(#{t(scope, scope: [:doorkeeper, :scopes])})" - .prepend-top-default = f.submit 'Save application', class: "btn btn-create" diff --git a/app/views/doorkeeper/applications/show.html.haml b/app/views/doorkeeper/applications/show.html.haml index a18e133c8de..5473a8e0ddc 100644 --- a/app/views/doorkeeper/applications/show.html.haml +++ b/app/views/doorkeeper/applications/show.html.haml @@ -34,7 +34,6 @@ %span.scope-name= scope = "(#{t(scope, scope: [:doorkeeper, :scopes])})" - .form-actions = link_to 'Edit', edit_oauth_application_path(@application), class: 'btn btn-primary wide pull-left' = render 'delete_form', application: @application, submit_btn_css: 'btn btn-danger prepend-left-10' -- cgit v1.2.1 From 990ae6b8e5f2797a6c168f9c16a725a159570058 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Thu, 24 Nov 2016 14:22:03 +0530 Subject: Move the scopes form/list view into a partial. - The list of scopes that's displayed while creating a personal access token is identical to the list that's displayed while creating an OAuth application. Extract these into a partial. - The list of scopes that's displayed while in the show page for an OAuth token in the profile settings and admin settings are identical. Extract these into a partial. --- app/views/admin/applications/show.html.haml | 11 +---------- app/views/doorkeeper/applications/_form.html.haml | 6 +----- app/views/doorkeeper/applications/show.html.haml | 11 +---------- app/views/profiles/personal_access_tokens/_form.html.haml | 6 +----- app/views/shared/tokens/_scopes_form.html.haml | 5 +++++ app/views/shared/tokens/_scopes_list.html.haml | 10 ++++++++++ 6 files changed, 19 insertions(+), 30 deletions(-) create mode 100644 app/views/shared/tokens/_scopes_form.html.haml create mode 100644 app/views/shared/tokens/_scopes_list.html.haml (limited to 'app') diff --git a/app/views/admin/applications/show.html.haml b/app/views/admin/applications/show.html.haml index 3418dc96496..6e7b7003ac5 100644 --- a/app/views/admin/applications/show.html.haml +++ b/app/views/admin/applications/show.html.haml @@ -23,16 +23,7 @@ %div %span.monospace= uri - - if @application.scopes.present? - %tr - %td - Scopes - %td - %ul.scopes-list.append-bottom-0 - - @application.scopes.each do |scope| - %li - %span.scope-name= scope - = "(#{t(scope, scope: [:doorkeeper, :scopes])})" + = render partial: "shared/tokens/scopes_list" .form-actions = link_to 'Edit', edit_admin_application_path(@application), class: 'btn btn-primary wide pull-left' diff --git a/app/views/doorkeeper/applications/_form.html.haml b/app/views/doorkeeper/applications/_form.html.haml index 96677dc1a4d..a6ad0bb8d1b 100644 --- a/app/views/doorkeeper/applications/_form.html.haml +++ b/app/views/doorkeeper/applications/_form.html.haml @@ -19,11 +19,7 @@ .form-group = f.label :scopes, class: 'label-light' - - @scopes.each do |scope| - %fieldset - = check_box_tag 'doorkeeper_application[scopes][]', scope, application.scopes.include?(scope), id: "doorkeeper_application_scopes_#{scope}" - = label_tag "doorkeeper_application_scopes_#{scope}", scope - %span= "(#{t(scope, scope: [:doorkeeper, :scopes])})" + = render partial: 'shared/tokens/scopes_form', locals: { prefix: 'doorkeeper_application', token: application } .prepend-top-default = f.submit 'Save application', class: "btn btn-create" diff --git a/app/views/doorkeeper/applications/show.html.haml b/app/views/doorkeeper/applications/show.html.haml index 5473a8e0ddc..e528cb825f5 100644 --- a/app/views/doorkeeper/applications/show.html.haml +++ b/app/views/doorkeeper/applications/show.html.haml @@ -23,16 +23,7 @@ %div %span.monospace= uri - - if @application.scopes.present? - %tr - %td - Scopes - %td - %ul.scopes-list.append-bottom-0 - - @application.scopes.each do |scope| - %li - %span.scope-name= scope - = "(#{t(scope, scope: [:doorkeeper, :scopes])})" + = render partial: "shared/tokens/scopes_list" .form-actions = link_to 'Edit', edit_oauth_application_path(@application), class: 'btn btn-primary wide pull-left' diff --git a/app/views/profiles/personal_access_tokens/_form.html.haml b/app/views/profiles/personal_access_tokens/_form.html.haml index 6083fdaa31d..5651b242129 100644 --- a/app/views/profiles/personal_access_tokens/_form.html.haml +++ b/app/views/profiles/personal_access_tokens/_form.html.haml @@ -12,11 +12,7 @@ .form-group = f.label :scopes, class: 'label-light' - - @scopes.each do |scope| - %fieldset - = check_box_tag 'personal_access_token[scopes][]', scope, @personal_access_token.scopes.include?(scope), id: "personal_access_token_scopes_#{scope}" - = label_tag "personal_access_token_scopes_#{scope}", scope - %span= "(#{t(scope, scope: [:doorkeeper, :scopes])})" + = render partial: 'shared/tokens/scopes_form', locals: { prefix: 'personal_access_token', token: @personal_access_token } .prepend-top-default = f.submit 'Create Personal Access Token', class: "btn btn-create" diff --git a/app/views/shared/tokens/_scopes_form.html.haml b/app/views/shared/tokens/_scopes_form.html.haml new file mode 100644 index 00000000000..5dbbd9e4808 --- /dev/null +++ b/app/views/shared/tokens/_scopes_form.html.haml @@ -0,0 +1,5 @@ +- @scopes.each do |scope| + %fieldset + = check_box_tag "#{prefix}[scopes][]", scope, token.scopes.include?(scope), id: "#{prefix}_scopes_#{scope}" + = label_tag "#{prefix}_scopes_#{scope}", scope + %span= "(#{t(scope, scope: [:doorkeeper, :scopes])})" diff --git a/app/views/shared/tokens/_scopes_list.html.haml b/app/views/shared/tokens/_scopes_list.html.haml new file mode 100644 index 00000000000..9e3b562f0f5 --- /dev/null +++ b/app/views/shared/tokens/_scopes_list.html.haml @@ -0,0 +1,10 @@ +- if @application.scopes.present? + %tr + %td + Scopes + %td + %ul.scopes-list.append-bottom-0 + - @application.scopes.each do |scope| + %li + %span.scope-name= scope + = "(#{t(scope, scope: [:doorkeeper, :scopes])})" -- cgit v1.2.1 From f706a973c26f9de9a1f1599d532b33e9e66a80bb Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Mon, 5 Dec 2016 09:49:51 +0530 Subject: View-related (and other minor) changes to !5951 based on @rymai's review. - The `scopes_form` partial can be used in the `admin/applications` view as well - Don't allow partials to access instance variables directly. Instead, pass in the instance variables as local variables, and use `local_assigns.fetch` to assert that the variables are passed in as expected. - Change a few instances of `render :partial` to `render` - Remove an instance of `required: false` in a view, since this is the default - Inline many instances of a local variable (`ip = 'ip'`) in `auth_spec` --- app/views/admin/applications/_form.html.haml | 6 +----- app/views/admin/applications/show.html.haml | 2 +- app/views/doorkeeper/applications/_form.html.haml | 2 +- app/views/doorkeeper/applications/show.html.haml | 2 +- .../personal_access_tokens/_form.html.haml | 11 +++++++---- .../personal_access_tokens/index.html.haml | 2 +- app/views/shared/tokens/_scopes_form.html.haml | 6 +++++- app/views/shared/tokens/_scopes_list.html.haml | 23 ++++++++++++---------- 8 files changed, 30 insertions(+), 24 deletions(-) (limited to 'app') diff --git a/app/views/admin/applications/_form.html.haml b/app/views/admin/applications/_form.html.haml index 36d2f415a05..c689b26d6e6 100644 --- a/app/views/admin/applications/_form.html.haml +++ b/app/views/admin/applications/_form.html.haml @@ -22,11 +22,7 @@ .form-group = f.label :scopes, class: 'col-sm-2 control-label' .col-sm-10 - - @scopes.each do |scope| - %fieldset - = check_box_tag 'doorkeeper_application[scopes][]', scope, application.scopes.include?(scope), id: "doorkeeper_application_scopes_#{scope}" - = label_tag "doorkeeper_application_scopes_#{scope}", scope - %span= "(#{t(scope, scope: [:doorkeeper, :scopes])})" + = render 'shared/tokens/scopes_form', prefix: 'doorkeeper_application', token: application, scopes: @scopes .form-actions = f.submit 'Submit', class: "btn btn-save wide" diff --git a/app/views/admin/applications/show.html.haml b/app/views/admin/applications/show.html.haml index 6e7b7003ac5..14683cc66e9 100644 --- a/app/views/admin/applications/show.html.haml +++ b/app/views/admin/applications/show.html.haml @@ -23,7 +23,7 @@ %div %span.monospace= uri - = render partial: "shared/tokens/scopes_list" + = render "shared/tokens/scopes_list", token: @application .form-actions = link_to 'Edit', edit_admin_application_path(@application), class: 'btn btn-primary wide pull-left' diff --git a/app/views/doorkeeper/applications/_form.html.haml b/app/views/doorkeeper/applications/_form.html.haml index a6ad0bb8d1b..b3313c7c985 100644 --- a/app/views/doorkeeper/applications/_form.html.haml +++ b/app/views/doorkeeper/applications/_form.html.haml @@ -19,7 +19,7 @@ .form-group = f.label :scopes, class: 'label-light' - = render partial: 'shared/tokens/scopes_form', locals: { prefix: 'doorkeeper_application', token: application } + = render 'shared/tokens/scopes_form', prefix: 'doorkeeper_application', token: application, scopes: @scopes .prepend-top-default = f.submit 'Save application', class: "btn btn-create" diff --git a/app/views/doorkeeper/applications/show.html.haml b/app/views/doorkeeper/applications/show.html.haml index e528cb825f5..559de63d96d 100644 --- a/app/views/doorkeeper/applications/show.html.haml +++ b/app/views/doorkeeper/applications/show.html.haml @@ -23,7 +23,7 @@ %div %span.monospace= uri - = render partial: "shared/tokens/scopes_list" + = render "shared/tokens/scopes_list", token: @application .form-actions = link_to 'Edit', edit_oauth_application_path(@application), class: 'btn btn-primary wide pull-left' diff --git a/app/views/profiles/personal_access_tokens/_form.html.haml b/app/views/profiles/personal_access_tokens/_form.html.haml index 5651b242129..3f6efa33953 100644 --- a/app/views/profiles/personal_access_tokens/_form.html.haml +++ b/app/views/profiles/personal_access_tokens/_form.html.haml @@ -1,6 +1,9 @@ -= form_for [:profile, @personal_access_token], method: :post, html: { class: 'js-requires-input' } do |f| +- personal_access_token = local_assigns.fetch(:personal_access_token) +- scopes = local_assigns.fetch(:scopes) - = form_errors(@personal_access_token) += form_for [:profile, personal_access_token], method: :post, html: { class: 'js-requires-input' } do |f| + + = form_errors(personal_access_token) .form-group = f.label :name, class: 'label-light' @@ -8,11 +11,11 @@ .form-group = f.label :expires_at, class: 'label-light' - = f.text_field :expires_at, class: "datepicker form-control", required: false + = f.text_field :expires_at, class: "datepicker form-control" .form-group = f.label :scopes, class: 'label-light' - = render partial: 'shared/tokens/scopes_form', locals: { prefix: 'personal_access_token', token: @personal_access_token } + = render 'shared/tokens/scopes_form', prefix: 'personal_access_token', token: personal_access_token, scopes: scopes .prepend-top-default = f.submit 'Create Personal Access Token', class: "btn btn-create" diff --git a/app/views/profiles/personal_access_tokens/index.html.haml b/app/views/profiles/personal_access_tokens/index.html.haml index 39eef0f6baf..bb4effeeeb1 100644 --- a/app/views/profiles/personal_access_tokens/index.html.haml +++ b/app/views/profiles/personal_access_tokens/index.html.haml @@ -29,7 +29,7 @@ %p.profile-settings-content Pick a name for the application, and we'll give you a unique token. - = render "form" + = render "form", personal_access_token: @personal_access_token, scopes: @scopes %hr diff --git a/app/views/shared/tokens/_scopes_form.html.haml b/app/views/shared/tokens/_scopes_form.html.haml index 5dbbd9e4808..5074afb63a1 100644 --- a/app/views/shared/tokens/_scopes_form.html.haml +++ b/app/views/shared/tokens/_scopes_form.html.haml @@ -1,4 +1,8 @@ -- @scopes.each do |scope| +- scopes = local_assigns.fetch(:scopes) +- prefix = local_assigns.fetch(:prefix) +- token = local_assigns.fetch(:token) + +- scopes.each do |scope| %fieldset = check_box_tag "#{prefix}[scopes][]", scope, token.scopes.include?(scope), id: "#{prefix}_scopes_#{scope}" = label_tag "#{prefix}_scopes_#{scope}", scope diff --git a/app/views/shared/tokens/_scopes_list.html.haml b/app/views/shared/tokens/_scopes_list.html.haml index 9e3b562f0f5..f99e905e95c 100644 --- a/app/views/shared/tokens/_scopes_list.html.haml +++ b/app/views/shared/tokens/_scopes_list.html.haml @@ -1,10 +1,13 @@ -- if @application.scopes.present? - %tr - %td - Scopes - %td - %ul.scopes-list.append-bottom-0 - - @application.scopes.each do |scope| - %li - %span.scope-name= scope - = "(#{t(scope, scope: [:doorkeeper, :scopes])})" +- token = local_assigns.fetch(:token) + +- return unless token.scopes.present? + +%tr + %td + Scopes + %td + %ul.scopes-list.append-bottom-0 + - token.scopes.each do |scope| + %li + %span.scope-name= scope + = "(#{t(scope, scope: [:doorkeeper, :scopes])})" -- cgit v1.2.1 From b303948ff549ce57d3b6985c2c366dfcdc5a2ca3 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Mon, 5 Dec 2016 22:55:53 +0530 Subject: Convert AccessTokenValidationService into a class. - Previously, AccessTokenValidationService was a module, and all its public methods accepted a token. It makes sense to convert it to a class which accepts a token during initialization. - Also rename the `sufficient_scope?` method to `include_any_scope?` - Based on feedback from @rymai --- app/services/access_token_validation_service.rb | 38 ++++++++++++------------- 1 file changed, 18 insertions(+), 20 deletions(-) (limited to 'app') diff --git a/app/services/access_token_validation_service.rb b/app/services/access_token_validation_service.rb index 69449f3a445..ddaaed90e5b 100644 --- a/app/services/access_token_validation_service.rb +++ b/app/services/access_token_validation_service.rb @@ -1,34 +1,32 @@ -module AccessTokenValidationService +AccessTokenValidationService = Struct.new(:token) do # Results: VALID = :valid EXPIRED = :expired REVOKED = :revoked INSUFFICIENT_SCOPE = :insufficient_scope - class << self - def validate(token, scopes: []) - if token.expired? - return EXPIRED + def validate(scopes: []) + if token.expired? + return EXPIRED - elsif token.revoked? - return REVOKED + elsif token.revoked? + return REVOKED - elsif !self.sufficient_scope?(token, scopes) - return INSUFFICIENT_SCOPE + elsif !self.include_any_scope?(scopes) + return INSUFFICIENT_SCOPE - else - return VALID - end + else + return VALID end + end - # True if the token's scope contains any of the required scopes. - def sufficient_scope?(token, required_scopes) - if required_scopes.blank? - true - else - # Check whether the token is allowed access to any of the required scopes. - Set.new(required_scopes).intersection(Set.new(token.scopes)).present? - end + # True if the token's scope contains any of the passed scopes. + def include_any_scope?(scopes) + if scopes.blank? + true + else + # Check whether the token is allowed access to any of the required scopes. + Set.new(scopes).intersection(Set.new(token.scopes)).present? end end end -- cgit v1.2.1 From 87d160634dfdaacd0dc382c26932786382d1be34 Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Tue, 13 Dec 2016 19:52:41 +0100 Subject: Base work for auto config MM slash commands --- app/controllers/projects/services_controller.rb | 28 ++- app/helpers/mattermost_helper.rb | 13 ++ .../mattermost_slash_commands_service.rb | 15 ++ app/models/service.rb | 4 + app/views/projects/services/_form.html.haml | 20 +-- .../mattermost_slash_commands/_form.html.haml | 3 + .../mattermost_slash_commands/_help.html.haml | 195 +++++++++++---------- app/views/shared/_service_settings.html.haml | 73 ++++---- 8 files changed, 206 insertions(+), 145 deletions(-) create mode 100644 app/helpers/mattermost_helper.rb create mode 100644 app/views/projects/services/mattermost_slash_commands/_form.html.haml (limited to 'app') diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb index 30c2a5d9982..94ea36bbdd9 100644 --- a/app/controllers/projects/services_controller.rb +++ b/app/controllers/projects/services_controller.rb @@ -3,7 +3,7 @@ class Projects::ServicesController < Projects::ApplicationController # Authorize before_action :authorize_admin_project! - before_action :service, only: [:edit, :update, :test] + before_action :service, only: [:edit, :update, :test, :configure] respond_to :html @@ -44,9 +44,35 @@ class Projects::ServicesController < Projects::ApplicationController redirect_back_or_default(options: message) end + def configure + host = Gitlab.config.mattermost.host + if @service.auto_config? && host + @service.configure(host, current_user, params) + + redirect_to( + edit_namespace_project_service_path(@project.namespace, @project, @service.to_param), + notice: 'This service is now configured.' + ) + else + redirect_to( + edit_namespace_project_service_path(@project.namespace, @project, @service.to_param), + alert: 'This service can not be automatticly configured.' + ) + end + rescue Mattermost::NoSessionError + redirect_to( + edit_namespace_project_service_path(@project.namespace, @project, @service.to_param), + alert: 'An error occurred, is Mattermost configured with Single Sign on?' + ) + end + private def service @service ||= @project.find_or_initialize_service(params[:id]) end + + def configure_params + params.require(:auto_configure).permit(:trigger, :team_id) + end end diff --git a/app/helpers/mattermost_helper.rb b/app/helpers/mattermost_helper.rb new file mode 100644 index 00000000000..83434c20c2b --- /dev/null +++ b/app/helpers/mattermost_helper.rb @@ -0,0 +1,13 @@ +module MattermostHelper + def mattermost_teams_for(current_user) + return unless Gitlab.config.mattermost.enabled + # Hack to make frontend work better + return [{"id"=>"qz8gdr1fopncueb8n9on8ohk3h", "create_at"=>1479992105904, "update_at"=>1479992105904, "delete_at"=>0, "display_name"=>"chatops", "name"=>"chatops", "email"=>"admin@example.com", "type"=>"O", "company_name"=>"", "allowed_domains"=>"", "invite_id"=>"gthxi47gj7rxtcx6zama63zd1w", "allow_open_invite"=>false}] + + + host = Gitlab.config.mattermost.host + Mattermost::Mattermost.new(host, current_user).with_session do + Mattermost::Team.all + end + end +end diff --git a/app/models/project_services/mattermost_slash_commands_service.rb b/app/models/project_services/mattermost_slash_commands_service.rb index 33431f41dc2..c0e8e1a9324 100644 --- a/app/models/project_services/mattermost_slash_commands_service.rb +++ b/app/models/project_services/mattermost_slash_commands_service.rb @@ -25,6 +25,21 @@ class MattermostSlashCommandsService < ChatService ] end + def auto_config? + Gitlab.config.mattermost.enabled + end + + def configure(host, current_user, params) + token = Mattermost::Mattermost.new(host, current_user).with_session do + Mattermost::Commands.create(params[:team_id], + trigger: params[:trigger] || @service.project.path, + url: service_trigger_url(@service), + icon_url: asset_url('gitlab_logo.png')) + end + + update_attributes(token: token) + end + def trigger(params) return nil unless valid_token?(params[:token]) diff --git a/app/models/service.rb b/app/models/service.rb index e49a8fa2904..9004d9caa19 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -54,6 +54,10 @@ class Service < ActiveRecord::Base template end + def auto_config? + false + end + def category read_attribute(:category).to_sym end diff --git a/app/views/projects/services/_form.html.haml b/app/views/projects/services/_form.html.haml index db51c4f8a4e..0160a366aaa 100644 --- a/app/views/projects/services/_form.html.haml +++ b/app/views/projects/services/_form.html.haml @@ -6,16 +6,12 @@ %p= @service.description .col-lg-9 - = form_for(@service, as: :service, url: namespace_project_service_path(@project.namespace, @project, @service.to_param), method: :put, html: { class: 'form-horizontal' }) do |form| - = render 'shared/service_settings', form: form, subject: @service + - # This returns an array of hashes, could you make a fancy dropdown :D + - # Also, this is mocked for now, checkout the MattermostHelper to edit the data + = mattermost_teams_for(current_user) + = form_for(:auto_configure, method: :post, url: configure_namespace_project_service_path(@project.namespace, @project, @service.to_param)) do |f| + = "Team ID" + = f.text_field(:team_id) + = "Team ID" + = f.submit 'Save changes', class: 'btn btn-save' - .footer-block.row-content-block - = form.submit 'Save changes', class: 'btn btn-save' -   - - if @service.valid? && @service.activated? - - unless @service.can_test? - - disabled_class = 'disabled' - - disabled_title = @service.disabled_title - - = link_to 'Test settings', test_namespace_project_service_path(@project.namespace, @project, @service), class: "btn #{disabled_class}", title: disabled_title - = link_to "Cancel", namespace_project_services_path(@project.namespace, @project), class: "btn btn-cancel" diff --git a/app/views/projects/services/mattermost_slash_commands/_form.html.haml b/app/views/projects/services/mattermost_slash_commands/_form.html.haml new file mode 100644 index 00000000000..9d9c877e791 --- /dev/null +++ b/app/views/projects/services/mattermost_slash_commands/_form.html.haml @@ -0,0 +1,3 @@ +- teams = Mattermost::Mattermost.new(Gitlab.config.mattermost.host, current_user).with_session do + Mattermost::Mattermost::Team.all + end diff --git a/app/views/projects/services/mattermost_slash_commands/_help.html.haml b/app/views/projects/services/mattermost_slash_commands/_help.html.haml index a676c0290a0..70f2ef52135 100644 --- a/app/views/projects/services/mattermost_slash_commands/_help.html.haml +++ b/app/views/projects/services/mattermost_slash_commands/_help.html.haml @@ -1,100 +1,101 @@ - pretty_path_with_namespace = "#{@project ? @project.namespace.name : 'namespace'} / #{@project ? @project.name : 'name'}" - run_actions_text = "Perform common operations on this project: #{pretty_path_with_namespace}" -.well - This service allows GitLab users to perform common operations on this - project by entering slash commands in Mattermost. - %br - See list of available commands in Mattermost after setting up this service, - by entering - %code /<command_trigger_word> help - %br - %br - To setup this service: - %ul.list-unstyled - %li - 1. - = link_to 'Enable custom slash commands', 'https://docs.mattermost.com/developer/slash-commands.html#enabling-custom-commands' - on your Mattermost installation - %li - 2. - = link_to 'Add a slash command', 'https://docs.mattermost.com/developer/slash-commands.html#set-up-a-custom-command' - in Mattermost with these options: - - %hr - - .help-form - .form-group - = label_tag :display_name, 'Display name', class: 'col-sm-2 col-xs-12 control-label' - .col-sm-10.col-xs-12.input-group - = text_field_tag :display_name, "GitLab / #{pretty_path_with_namespace}", class: 'form-control input-sm', readonly: 'readonly' - .input-group-btn - = clipboard_button(clipboard_target: '#display_name') - - .form-group - = label_tag :description, 'Description', class: 'col-sm-2 col-xs-12 control-label' - .col-sm-10.col-xs-12.input-group - = text_field_tag :description, run_actions_text, class: 'form-control input-sm', readonly: 'readonly' - .input-group-btn - = clipboard_button(clipboard_target: '#description') - - .form-group - = label_tag nil, 'Command trigger word', class: 'col-sm-2 col-xs-12 control-label' - .col-sm-10.col-xs-12.text-block - %p Fill in the word that works best for your team. - %p - Suggestions: - %code= 'gitlab' - %code= @project.path # Path contains no spaces, but dashes - %code= @project.path_with_namespace - - .form-group - = label_tag :request_url, 'Request URL', class: 'col-sm-2 col-xs-12 control-label' - .col-sm-10.col-xs-12.input-group - = text_field_tag :request_url, service_trigger_url(subject), class: 'form-control input-sm', readonly: 'readonly' - .input-group-btn - = clipboard_button(clipboard_target: '#request_url') - - .form-group - = label_tag nil, 'Request method', class: 'col-sm-2 col-xs-12 control-label' - .col-sm-10.col-xs-12.text-block POST - - .form-group - = label_tag :response_username, 'Response username', class: 'col-sm-2 col-xs-12 control-label' - .col-sm-10.col-xs-12.input-group - = text_field_tag :response_username, 'GitLab', class: 'form-control input-sm', readonly: 'readonly' - .input-group-btn - = clipboard_button(clipboard_target: '#response_username') - - .form-group - = label_tag :response_icon, 'Response icon', class: 'col-sm-2 col-xs-12 control-label' - .col-sm-10.col-xs-12.input-group - = text_field_tag :response_icon, asset_url('gitlab_logo.png'), class: 'form-control input-sm', readonly: 'readonly' - .input-group-btn - = clipboard_button(clipboard_target: '#response_icon') - - .form-group - = label_tag nil, 'Autocomplete', class: 'col-sm-2 col-xs-12 control-label' - .col-sm-10.col-xs-12.text-block Yes - - .form-group - = label_tag :autocomplete_hint, 'Autocomplete hint', class: 'col-sm-2 col-xs-12 control-label' - .col-sm-10.col-xs-12.input-group - = text_field_tag :autocomplete_hint, '[help]', class: 'form-control input-sm', readonly: 'readonly' - .input-group-btn - = clipboard_button(clipboard_target: '#autocomplete_hint') - - .form-group - = label_tag :autocomplete_description, 'Autocomplete description', class: 'col-sm-2 col-xs-12 control-label' - .col-sm-10.col-xs-12.input-group - = text_field_tag :autocomplete_description, run_actions_text, class: 'form-control input-sm', readonly: 'readonly' - .input-group-btn - = clipboard_button(clipboard_target: '#autocomplete_description') - - %hr - - %ul.list-unstyled - %li - 3. After adding the slash command, paste the - %strong token - into the field below +- unless GitLab.config.mattermost.enabled + .well + This service allows GitLab users to perform common operations on this + project by entering slash commands in Mattermost. + %br + See list of available commands in Mattermost after setting up this service, + by entering + %code /<command_trigger_word> help + %br + %br + To setup this service: + %ul.list-unstyled + %li + 1. + = link_to 'Enable custom slash commands', 'https://docs.mattermost.com/developer/slash-commands.html#enabling-custom-commands' + on your Mattermost installation + %li + 2. + = link_to 'Add a slash command', 'https://docs.mattermost.com/developer/slash-commands.html#set-up-a-custom-command' + in Mattermost with these options: + + %hr + + .help-form + .form-group + = label_tag :display_name, 'Display name', class: 'col-sm-2 col-xs-12 control-label' + .col-sm-10.col-xs-12.input-group + = text_field_tag :display_name, "GitLab / #{pretty_path_with_namespace}", class: 'form-control input-sm', readonly: 'readonly' + .input-group-btn + = clipboard_button(clipboard_target: '#display_name') + + .form-group + = label_tag :description, 'Description', class: 'col-sm-2 col-xs-12 control-label' + .col-sm-10.col-xs-12.input-group + = text_field_tag :description, run_actions_text, class: 'form-control input-sm', readonly: 'readonly' + .input-group-btn + = clipboard_button(clipboard_target: '#description') + + .form-group + = label_tag nil, 'Command trigger word', class: 'col-sm-2 col-xs-12 control-label' + .col-sm-10.col-xs-12.text-block + %p Fill in the word that works best for your team. + %p + Suggestions: + %code= 'gitlab' + %code= @project.path # Path contains no spaces, but dashes + %code= @project.path_with_namespace + + .form-group + = label_tag :request_url, 'Request URL', class: 'col-sm-2 col-xs-12 control-label' + .col-sm-10.col-xs-12.input-group + = text_field_tag :request_url, service_trigger_url(subject), class: 'form-control input-sm', readonly: 'readonly' + .input-group-btn + = clipboard_button(clipboard_target: '#request_url') + + .form-group + = label_tag nil, 'Request method', class: 'col-sm-2 col-xs-12 control-label' + .col-sm-10.col-xs-12.text-block POST + + .form-group + = label_tag :response_username, 'Response username', class: 'col-sm-2 col-xs-12 control-label' + .col-sm-10.col-xs-12.input-group + = text_field_tag :response_username, 'GitLab', class: 'form-control input-sm', readonly: 'readonly' + .input-group-btn + = clipboard_button(clipboard_target: '#response_username') + + .form-group + = label_tag :response_icon, 'Response icon', class: 'col-sm-2 col-xs-12 control-label' + .col-sm-10.col-xs-12.input-group + = text_field_tag :response_icon, asset_url('gitlab_logo.png'), class: 'form-control input-sm', readonly: 'readonly' + .input-group-btn + = clipboard_button(clipboard_target: '#response_icon') + + .form-group + = label_tag nil, 'Autocomplete', class: 'col-sm-2 col-xs-12 control-label' + .col-sm-10.col-xs-12.text-block Yes + + .form-group + = label_tag :autocomplete_hint, 'Autocomplete hint', class: 'col-sm-2 col-xs-12 control-label' + .col-sm-10.col-xs-12.input-group + = text_field_tag :autocomplete_hint, '[help]', class: 'form-control input-sm', readonly: 'readonly' + .input-group-btn + = clipboard_button(clipboard_target: '#autocomplete_hint') + + .form-group + = label_tag :autocomplete_description, 'Autocomplete description', class: 'col-sm-2 col-xs-12 control-label' + .col-sm-10.col-xs-12.input-group + = text_field_tag :autocomplete_description, run_actions_text, class: 'form-control input-sm', readonly: 'readonly' + .input-group-btn + = clipboard_button(clipboard_target: '#autocomplete_description') + + %hr + + %ul.list-unstyled + %li + 3. After adding the slash command, paste the + %strong token + into the field below diff --git a/app/views/shared/_service_settings.html.haml b/app/views/shared/_service_settings.html.haml index 9c5053dace5..e8ab1b2ed46 100644 --- a/app/views/shared/_service_settings.html.haml +++ b/app/views/shared/_service_settings.html.haml @@ -13,38 +13,41 @@ .col-sm-10 = form.check_box :active - - if @service.supported_events.present? - .form-group - = form.label :url, "Trigger", class: 'control-label' - - .col-sm-10 - - @service.supported_events.each do |event| - %div - = form.check_box service_event_field_name(event), class: 'pull-left' - .prepend-left-20 - = form.label service_event_field_name(event), class: 'list-label' do - %strong - = event.humanize - - - field = @service.event_field(event) - - - if field - %p - = form.text_field field[:name], class: "form-control", placeholder: field[:placeholder] - - %p.light - = service_event_description(event) - - - @service.global_fields.each do |field| - - type = field[:type] - - - if type == 'fieldset' - - fields = field[:fields] - - legend = field[:legend] - - %fieldset - %legend= legend - - fields.each do |subfield| - = render 'shared/field', form: form, field: subfield - - else - = render 'shared/field', form: form, field: field + - if @service.auto_config? + + - else + - if @service.supported_events.present? + .form-group + = form.label :url, "Trigger", class: 'control-label' + + .col-sm-10 + - @service.supported_events.each do |event| + %div + = form.check_box service_event_field_name(event), class: 'pull-left' + .prepend-left-20 + = form.label service_event_field_name(event), class: 'list-label' do + %strong + = event.humanize + + - field = @service.event_field(event) + + - if field + %p + = form.text_field field[:name], class: "form-control", placeholder: field[:placeholder] + + %p.light + = service_event_description(event) + + - @service.global_fields.each do |field| + - type = field[:type] + + - if type == 'fieldset' + - fields = field[:fields] + - legend = field[:legend] + + %fieldset + %legend= legend + - fields.each do |subfield| + = render 'shared/field', form: form, field: subfield + - else + = render 'shared/field', form: form, field: field -- cgit v1.2.1 From 99d8d6f0d48e28f5ba798d1d4461071a01435054 Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Tue, 13 Dec 2016 19:52:41 +0100 Subject: Add MattermostController --- app/controllers/projects/mattermost_controller.rb | 47 +++++ app/views/projects/mattermost/new.html.haml | 6 + .../mattermost_slash_commands/_help.html.haml | 198 +++++++++++---------- 3 files changed, 153 insertions(+), 98 deletions(-) create mode 100644 app/controllers/projects/mattermost_controller.rb create mode 100644 app/views/projects/mattermost/new.html.haml (limited to 'app') diff --git a/app/controllers/projects/mattermost_controller.rb b/app/controllers/projects/mattermost_controller.rb new file mode 100644 index 00000000000..f50f921c7cf --- /dev/null +++ b/app/controllers/projects/mattermost_controller.rb @@ -0,0 +1,47 @@ +class Projects::MattermostController < Projects::ApplicationController + layout 'project_settings' + before_action :authorize_admin_project! + before_action :service + before_action :teams, only: [:new] + + def new + end + + def configure + @service.configure(host, current_user, params) + + redirect_to( + new_namespace_project_service_path(@project.namespace, @project, @service.to_param), + notice: 'This service is now configured.' + ) + rescue Mattermost::NoSessionError + redirect_to( + edit_namespace_project_service_path(@project.namespace, @project, @service.to_param), + alert: 'No session could be set up, is Mattermost configured with Single Sign on?' + ) + end + + private + + def configure_params + params.require(:configure_params).permit(:trigger, :team_id) + end + + def service + @service ||= @project.services.find_by(type: 'MattermostSlashCommandsService') + end + + def teams + # Mocking for frontend development + @teams = [{"id"=>"qz8gdr1fopncueb8n9on8ohk3h", "create_at"=>1479992105904, "update_at"=>1479992105904, "delete_at"=>0, "display_name"=>"chatops", "name"=>"chatops", "email"=>"admin@example.com", "type"=>"O", "company_name"=>"", "allowed_domains"=>"", "invite_id"=>"gthxi47gj7rxtcx6zama63zd1w", "allow_open_invite"=>false}] + + # @teams = + # begin + # Mattermost::Mattermost.new(Gitlab.config.mattermost.host, current_user).with_session do + # Mattermost::Team.all + # end + # rescue Mattermost::NoSessionError + # @teams = [] + # end + end +end diff --git a/app/views/projects/mattermost/new.html.haml b/app/views/projects/mattermost/new.html.haml new file mode 100644 index 00000000000..a7e028bc0cb --- /dev/null +++ b/app/views/projects/mattermost/new.html.haml @@ -0,0 +1,6 @@ += "hello world" += form_for(:create, method: :post, url: configure_namespace_project_mattermost_path(@project.namespace, @project, @service.to_param)) do |f| + = "Team ID" + = f.text_field(:team_id) + = f.submit 'Configure', class: 'btn btn-save' + diff --git a/app/views/projects/services/mattermost_slash_commands/_help.html.haml b/app/views/projects/services/mattermost_slash_commands/_help.html.haml index 70f2ef52135..6494d3cd793 100644 --- a/app/views/projects/services/mattermost_slash_commands/_help.html.haml +++ b/app/views/projects/services/mattermost_slash_commands/_help.html.haml @@ -1,101 +1,103 @@ - pretty_path_with_namespace = "#{@project ? @project.namespace.name : 'namespace'} / #{@project ? @project.name : 'name'}" - run_actions_text = "Perform common operations on this project: #{pretty_path_with_namespace}" -- unless GitLab.config.mattermost.enabled - .well - This service allows GitLab users to perform common operations on this - project by entering slash commands in Mattermost. - %br - See list of available commands in Mattermost after setting up this service, - by entering - %code /<command_trigger_word> help - %br - %br - To setup this service: - %ul.list-unstyled - %li - 1. - = link_to 'Enable custom slash commands', 'https://docs.mattermost.com/developer/slash-commands.html#enabling-custom-commands' - on your Mattermost installation - %li - 2. - = link_to 'Add a slash command', 'https://docs.mattermost.com/developer/slash-commands.html#set-up-a-custom-command' - in Mattermost with these options: - - %hr - - .help-form - .form-group - = label_tag :display_name, 'Display name', class: 'col-sm-2 col-xs-12 control-label' - .col-sm-10.col-xs-12.input-group - = text_field_tag :display_name, "GitLab / #{pretty_path_with_namespace}", class: 'form-control input-sm', readonly: 'readonly' - .input-group-btn - = clipboard_button(clipboard_target: '#display_name') - - .form-group - = label_tag :description, 'Description', class: 'col-sm-2 col-xs-12 control-label' - .col-sm-10.col-xs-12.input-group - = text_field_tag :description, run_actions_text, class: 'form-control input-sm', readonly: 'readonly' - .input-group-btn - = clipboard_button(clipboard_target: '#description') - - .form-group - = label_tag nil, 'Command trigger word', class: 'col-sm-2 col-xs-12 control-label' - .col-sm-10.col-xs-12.text-block - %p Fill in the word that works best for your team. - %p - Suggestions: - %code= 'gitlab' - %code= @project.path # Path contains no spaces, but dashes - %code= @project.path_with_namespace - - .form-group - = label_tag :request_url, 'Request URL', class: 'col-sm-2 col-xs-12 control-label' - .col-sm-10.col-xs-12.input-group - = text_field_tag :request_url, service_trigger_url(subject), class: 'form-control input-sm', readonly: 'readonly' - .input-group-btn - = clipboard_button(clipboard_target: '#request_url') - - .form-group - = label_tag nil, 'Request method', class: 'col-sm-2 col-xs-12 control-label' - .col-sm-10.col-xs-12.text-block POST - - .form-group - = label_tag :response_username, 'Response username', class: 'col-sm-2 col-xs-12 control-label' - .col-sm-10.col-xs-12.input-group - = text_field_tag :response_username, 'GitLab', class: 'form-control input-sm', readonly: 'readonly' - .input-group-btn - = clipboard_button(clipboard_target: '#response_username') - - .form-group - = label_tag :response_icon, 'Response icon', class: 'col-sm-2 col-xs-12 control-label' - .col-sm-10.col-xs-12.input-group - = text_field_tag :response_icon, asset_url('gitlab_logo.png'), class: 'form-control input-sm', readonly: 'readonly' - .input-group-btn - = clipboard_button(clipboard_target: '#response_icon') - - .form-group - = label_tag nil, 'Autocomplete', class: 'col-sm-2 col-xs-12 control-label' - .col-sm-10.col-xs-12.text-block Yes - - .form-group - = label_tag :autocomplete_hint, 'Autocomplete hint', class: 'col-sm-2 col-xs-12 control-label' - .col-sm-10.col-xs-12.input-group - = text_field_tag :autocomplete_hint, '[help]', class: 'form-control input-sm', readonly: 'readonly' - .input-group-btn - = clipboard_button(clipboard_target: '#autocomplete_hint') - - .form-group - = label_tag :autocomplete_description, 'Autocomplete description', class: 'col-sm-2 col-xs-12 control-label' - .col-sm-10.col-xs-12.input-group - = text_field_tag :autocomplete_description, run_actions_text, class: 'form-control input-sm', readonly: 'readonly' - .input-group-btn - = clipboard_button(clipboard_target: '#autocomplete_description') - - %hr - - %ul.list-unstyled - %li - 3. After adding the slash command, paste the - %strong token - into the field below +.well + This service allows GitLab users to perform common operations on this + project by entering slash commands in Mattermost. + %br + See list of available commands in Mattermost after setting up this service, + by entering + %code /<command_trigger_word> help + %br + %br + To setup this service: + %ul.list-unstyled + %li + 1. + = link_to 'Enable custom slash commands', 'https://docs.mattermost.com/developer/slash-commands.html#enabling-custom-commands' + on your Mattermost installation + %li + 2. + = link_to 'Add a slash command', 'https://docs.mattermost.com/developer/slash-commands.html#set-up-a-custom-command' + in Mattermost with these options: + + %hr + + .help-form + .form-group + = label_tag :display_name, 'Display name', class: 'col-sm-2 col-xs-12 control-label' + .col-sm-10.col-xs-12.input-group + = text_field_tag :display_name, "GitLab / #{pretty_path_with_namespace}", class: 'form-control input-sm', readonly: 'readonly' + .input-group-btn + = clipboard_button(clipboard_target: '#display_name') + + .form-group + = label_tag :description, 'Description', class: 'col-sm-2 col-xs-12 control-label' + .col-sm-10.col-xs-12.input-group + = text_field_tag :description, run_actions_text, class: 'form-control input-sm', readonly: 'readonly' + .input-group-btn + = clipboard_button(clipboard_target: '#description') + + .form-group + = label_tag nil, 'Command trigger word', class: 'col-sm-2 col-xs-12 control-label' + .col-sm-10.col-xs-12.text-block + %p Fill in the word that works best for your team. + %p + Suggestions: + %code= 'gitlab' + %code= @project.path # Path contains no spaces, but dashes + %code= @project.path_with_namespace + + .form-group + = label_tag :request_url, 'Request URL', class: 'col-sm-2 col-xs-12 control-label' + .col-sm-10.col-xs-12.input-group + = text_field_tag :request_url, service_trigger_url(subject), class: 'form-control input-sm', readonly: 'readonly' + .input-group-btn + = clipboard_button(clipboard_target: '#request_url') + + .form-group + = label_tag nil, 'Request method', class: 'col-sm-2 col-xs-12 control-label' + .col-sm-10.col-xs-12.text-block POST + + .form-group + = label_tag :response_username, 'Response username', class: 'col-sm-2 col-xs-12 control-label' + .col-sm-10.col-xs-12.input-group + = text_field_tag :response_username, 'GitLab', class: 'form-control input-sm', readonly: 'readonly' + .input-group-btn + = clipboard_button(clipboard_target: '#response_username') + + .form-group + = label_tag :response_icon, 'Response icon', class: 'col-sm-2 col-xs-12 control-label' + .col-sm-10.col-xs-12.input-group + = text_field_tag :response_icon, asset_url('gitlab_logo.png'), class: 'form-control input-sm', readonly: 'readonly' + .input-group-btn + = clipboard_button(clipboard_target: '#response_icon') + + .form-group + = label_tag nil, 'Autocomplete', class: 'col-sm-2 col-xs-12 control-label' + .col-sm-10.col-xs-12.text-block Yes + + .form-group + = label_tag :autocomplete_hint, 'Autocomplete hint', class: 'col-sm-2 col-xs-12 control-label' + .col-sm-10.col-xs-12.input-group + = text_field_tag :autocomplete_hint, '[help]', class: 'form-control input-sm', readonly: 'readonly' + .input-group-btn + = clipboard_button(clipboard_target: '#autocomplete_hint') + + .form-group + = label_tag :autocomplete_description, 'Autocomplete description', class: 'col-sm-2 col-xs-12 control-label' + .col-sm-10.col-xs-12.input-group + = text_field_tag :autocomplete_description, run_actions_text, class: 'form-control input-sm', readonly: 'readonly' + .input-group-btn + = clipboard_button(clipboard_target: '#autocomplete_description') + + %hr + + %ul.list-unstyled + %li + 3. After adding the slash command, paste the + %strong token + into the field below + +- if Gitlab.config.mattermost.enabled + = link_to "Auto config", new_namespace_project_mattermost_path(@project.namespace, @project) -- cgit v1.2.1 From 0045996728308bcb7643618ab48efb7e04e7d4bf Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Thu, 15 Dec 2016 20:19:42 +0100 Subject: Add auto configure of commands --- app/controllers/projects/mattermost_controller.rb | 19 ++++++++----------- .../mattermost_slash_commands_service.rb | 4 ---- app/models/service.rb | 4 ---- 3 files changed, 8 insertions(+), 19 deletions(-) (limited to 'app') diff --git a/app/controllers/projects/mattermost_controller.rb b/app/controllers/projects/mattermost_controller.rb index f50f921c7cf..f04189c8775 100644 --- a/app/controllers/projects/mattermost_controller.rb +++ b/app/controllers/projects/mattermost_controller.rb @@ -32,16 +32,13 @@ class Projects::MattermostController < Projects::ApplicationController end def teams - # Mocking for frontend development - @teams = [{"id"=>"qz8gdr1fopncueb8n9on8ohk3h", "create_at"=>1479992105904, "update_at"=>1479992105904, "delete_at"=>0, "display_name"=>"chatops", "name"=>"chatops", "email"=>"admin@example.com", "type"=>"O", "company_name"=>"", "allowed_domains"=>"", "invite_id"=>"gthxi47gj7rxtcx6zama63zd1w", "allow_open_invite"=>false}] - - # @teams = - # begin - # Mattermost::Mattermost.new(Gitlab.config.mattermost.host, current_user).with_session do - # Mattermost::Team.all - # end - # rescue Mattermost::NoSessionError - # @teams = [] - # end + @teams = + begin + Mattermost::Mattermost.new(Gitlab.config.mattermost.host, current_user).with_session do + Mattermost::Team.team_admin + end + rescue Mattermost::NoSessionError + [] + end end end diff --git a/app/models/project_services/mattermost_slash_commands_service.rb b/app/models/project_services/mattermost_slash_commands_service.rb index c0e8e1a9324..e07cc0e4077 100644 --- a/app/models/project_services/mattermost_slash_commands_service.rb +++ b/app/models/project_services/mattermost_slash_commands_service.rb @@ -25,10 +25,6 @@ class MattermostSlashCommandsService < ChatService ] end - def auto_config? - Gitlab.config.mattermost.enabled - end - def configure(host, current_user, params) token = Mattermost::Mattermost.new(host, current_user).with_session do Mattermost::Commands.create(params[:team_id], diff --git a/app/models/service.rb b/app/models/service.rb index 9004d9caa19..e49a8fa2904 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -54,10 +54,6 @@ class Service < ActiveRecord::Base template end - def auto_config? - false - end - def category read_attribute(:category).to_sym end -- cgit v1.2.1 From 9046b583ff61d74c8e481053d150da924d129ad8 Mon Sep 17 00:00:00 2001 From: Dimitrie Hoekstra Date: Fri, 16 Dec 2016 12:51:12 +0100 Subject: fixed variable, plus added light text color for light badges --- app/assets/stylesheets/framework/badges.scss | 1 + app/assets/stylesheets/framework/variables.scss | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/badges.scss b/app/assets/stylesheets/framework/badges.scss index 89e1c7890d8..e9d7cda0647 100644 --- a/app/assets/stylesheets/framework/badges.scss +++ b/app/assets/stylesheets/framework/badges.scss @@ -7,4 +7,5 @@ .badge-dark { background-color: $badge-bg-dark; + color: $badge-color-dark; } diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index cdc54fdc254..288bb67c4bf 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -281,7 +281,8 @@ $btn-active-gray-light: e4e7ed; */ $badge-bg: #f3f3f3; $badge-bg-dark: #eee; -$badge-color: $btn-transparent-color; +$badge-color: #929292; +$badge-color-dark: #8f8f8f; /* * Award emoji -- cgit v1.2.1 From 595da33d738041cf0b2c28a87989aa271f5019cc Mon Sep 17 00:00:00 2001 From: Dimitrie Hoekstra Date: Fri, 16 Dec 2016 13:05:44 +0100 Subject: fixed scss linting issue --- app/assets/stylesheets/pages/labels.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/labels.scss b/app/assets/stylesheets/pages/labels.scss index 703a429d63c..d129eb12a45 100644 --- a/app/assets/stylesheets/pages/labels.scss +++ b/app/assets/stylesheets/pages/labels.scss @@ -98,7 +98,7 @@ } .label { - padding: 8px 9px 9px 9px; + padding: 8px 9px 9px; font-size: 14px; } } -- cgit v1.2.1 From c945a0a7141ddf80e58e821178195cc48b8143f0 Mon Sep 17 00:00:00 2001 From: Adam Niedzielski Date: Fri, 16 Dec 2016 13:24:03 +0100 Subject: Pass variables from deployment project services to CI runner This commit introduces the concept of deployment variables - variables that are collected from deployment services and passed to CI runner during a deployment build. Deployment services specify the variables by overriding "predefined_variables" method. This commit also configures variables for KubernetesService --- app/models/ci/build.rb | 3 ++- app/models/project.rb | 6 ++++++ app/models/project_services/deployment_service.rb | 4 ++++ app/models/project_services/kubernetes_service.rb | 10 ++++++++++ 4 files changed, 22 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index fdbf28a1d68..591aba6bdc9 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -155,7 +155,7 @@ module Ci end def has_environment? - self.environment.present? + environment.present? end def starts_environment? @@ -221,6 +221,7 @@ module Ci variables += pipeline.predefined_variables variables += runner.predefined_variables if runner variables += project.container_registry_variables + variables += project.deployment_variables if has_environment? variables += yaml_variables variables += user_variables variables += project.secret_variables diff --git a/app/models/project.rb b/app/models/project.rb index 2c726cfc5df..5f8058dac60 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1229,6 +1229,12 @@ class Project < ActiveRecord::Base end end + def deployment_variables + return [] unless deployment_service + + deployment_service.predefined_variables + end + def append_or_update_attribute(name, value) old_values = public_send(name.to_s) diff --git a/app/models/project_services/deployment_service.rb b/app/models/project_services/deployment_service.rb index 55e98c31251..da6be9dd7b7 100644 --- a/app/models/project_services/deployment_service.rb +++ b/app/models/project_services/deployment_service.rb @@ -8,4 +8,8 @@ class DeploymentService < Service def supported_events [] end + + def predefined_variables + [] + end end diff --git a/app/models/project_services/kubernetes_service.rb b/app/models/project_services/kubernetes_service.rb index 80ae1191108..f5fbf8b353b 100644 --- a/app/models/project_services/kubernetes_service.rb +++ b/app/models/project_services/kubernetes_service.rb @@ -83,6 +83,16 @@ class KubernetesService < DeploymentService { success: false, result: err } end + def predefined_variables + variables = [ + { key: 'KUBE_URL', value: api_url, public: true }, + { key: 'KUBE_TOKEN', value: token, public: false }, + { key: 'KUBE_NAMESPACE', value: namespace, public: true } + ] + variables << { key: 'KUBE_CA_PEM', value: ca_pem, public: true } if ca_pem.present? + variables + end + private def build_kubeclient(api_path = '/api', api_version = 'v1') -- cgit v1.2.1 From df6c1b84a842d6dc54b27e396b60ffd4d7723c4a Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Fri, 16 Dec 2016 12:29:58 +0000 Subject: Prevent enviroment table to overflow when name has underscores Fix error in linter Add changelog entry --- .../environments/components/environment_item.js.es6 | 2 +- app/assets/stylesheets/pages/environments.scss | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/environments/components/environment_item.js.es6 b/app/assets/javascripts/environments/components/environment_item.js.es6 index 2e046a60146..4674d5202e6 100644 --- a/app/assets/javascripts/environments/components/environment_item.js.es6 +++ b/app/assets/javascripts/environments/components/environment_item.js.es6 @@ -449,7 +449,7 @@ - + diff --git a/app/assets/stylesheets/pages/environments.scss b/app/assets/stylesheets/pages/environments.scss index 92dd9885ab8..3d60426de01 100644 --- a/app/assets/stylesheets/pages/environments.scss +++ b/app/assets/stylesheets/pages/environments.scss @@ -30,19 +30,25 @@ display: table-cell; } + .environments-name, .environments-commit, .environments-actions { width: 20%; } - .environments-deploy, - .environments-build, .environments-date { width: 10%; } - .environments-name { - width: 30%; + .environments-deploy, + .environments-build { + width: 15%; + } + + .environment-name, + .environments-build-cell, + .deployment-column { + word-break: break-all; } .deployment-column { -- cgit v1.2.1 From 55f224e4e785d0e1515ac4a840e689cb6d9c7d24 Mon Sep 17 00:00:00 2001 From: Drew Blessing Date: Mon, 17 Oct 2016 09:39:14 -0500 Subject: Add GitLab host to 2FA QR and manual info The two factor authentication account string only had the user's email address. This led to ambiguous entries in two factor code generating apps. This adds the GitLab host to the account string in the standard format (according to Google). No matter the code generator this change disambiguates the entry. --- app/controllers/profiles/two_factor_auths_controller.rb | 8 ++++++-- app/views/profiles/two_factor_auths/show.html.haml | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/controllers/profiles/two_factor_auths_controller.rb b/app/controllers/profiles/two_factor_auths_controller.rb index 9eb75bb3891..18044ca78e2 100644 --- a/app/controllers/profiles/two_factor_auths_controller.rb +++ b/app/controllers/profiles/two_factor_auths_controller.rb @@ -22,6 +22,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController end @qr_code = build_qr_code + @account_string = account_string setup_u2f_registration end @@ -78,11 +79,14 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController private def build_qr_code - issuer = "#{issuer_host} | #{current_user.email}" - uri = current_user.otp_provisioning_uri(current_user.email, issuer: issuer) + uri = current_user.otp_provisioning_uri(account_string, issuer: issuer_host) RQRCode::render_qrcode(uri, :svg, level: :m, unit: 3) end + def account_string + "#{issuer_host}:#{current_user.email}" + end + def issuer_host Gitlab.config.gitlab.host end diff --git a/app/views/profiles/two_factor_auths/show.html.haml b/app/views/profiles/two_factor_auths/show.html.haml index 03ac739ade5..558a1d56151 100644 --- a/app/views/profiles/two_factor_auths/show.html.haml +++ b/app/views/profiles/two_factor_auths/show.html.haml @@ -30,7 +30,7 @@ To add the entry manually, provide the following details to the application on your phone. %p.prepend-top-0.append-bottom-0 Account: - = current_user.email + = @account_string %p.prepend-top-0.append-bottom-0 Key: = current_user.otp_secret.scan(/.{4}/).join(' ') -- cgit v1.2.1 From 7363a7d3b5804493f86531bebb1610afb91b5293 Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Fri, 16 Dec 2016 15:45:56 +0100 Subject: Add tests for auto configure slash commands --- app/controllers/projects/services_controller.rb | 26 -------- app/helpers/mattermost_helper.rb | 13 ---- app/views/projects/services/_form.html.haml | 20 +++--- .../mattermost_slash_commands/_form.html.haml | 3 - app/views/shared/_service_settings.html.haml | 73 +++++++++++----------- 5 files changed, 47 insertions(+), 88 deletions(-) delete mode 100644 app/helpers/mattermost_helper.rb delete mode 100644 app/views/projects/services/mattermost_slash_commands/_form.html.haml (limited to 'app') diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb index 94ea36bbdd9..b4f5750b0a4 100644 --- a/app/controllers/projects/services_controller.rb +++ b/app/controllers/projects/services_controller.rb @@ -44,35 +44,9 @@ class Projects::ServicesController < Projects::ApplicationController redirect_back_or_default(options: message) end - def configure - host = Gitlab.config.mattermost.host - if @service.auto_config? && host - @service.configure(host, current_user, params) - - redirect_to( - edit_namespace_project_service_path(@project.namespace, @project, @service.to_param), - notice: 'This service is now configured.' - ) - else - redirect_to( - edit_namespace_project_service_path(@project.namespace, @project, @service.to_param), - alert: 'This service can not be automatticly configured.' - ) - end - rescue Mattermost::NoSessionError - redirect_to( - edit_namespace_project_service_path(@project.namespace, @project, @service.to_param), - alert: 'An error occurred, is Mattermost configured with Single Sign on?' - ) - end - private def service @service ||= @project.find_or_initialize_service(params[:id]) end - - def configure_params - params.require(:auto_configure).permit(:trigger, :team_id) - end end diff --git a/app/helpers/mattermost_helper.rb b/app/helpers/mattermost_helper.rb deleted file mode 100644 index 83434c20c2b..00000000000 --- a/app/helpers/mattermost_helper.rb +++ /dev/null @@ -1,13 +0,0 @@ -module MattermostHelper - def mattermost_teams_for(current_user) - return unless Gitlab.config.mattermost.enabled - # Hack to make frontend work better - return [{"id"=>"qz8gdr1fopncueb8n9on8ohk3h", "create_at"=>1479992105904, "update_at"=>1479992105904, "delete_at"=>0, "display_name"=>"chatops", "name"=>"chatops", "email"=>"admin@example.com", "type"=>"O", "company_name"=>"", "allowed_domains"=>"", "invite_id"=>"gthxi47gj7rxtcx6zama63zd1w", "allow_open_invite"=>false}] - - - host = Gitlab.config.mattermost.host - Mattermost::Mattermost.new(host, current_user).with_session do - Mattermost::Team.all - end - end -end diff --git a/app/views/projects/services/_form.html.haml b/app/views/projects/services/_form.html.haml index 0160a366aaa..db51c4f8a4e 100644 --- a/app/views/projects/services/_form.html.haml +++ b/app/views/projects/services/_form.html.haml @@ -6,12 +6,16 @@ %p= @service.description .col-lg-9 - - # This returns an array of hashes, could you make a fancy dropdown :D - - # Also, this is mocked for now, checkout the MattermostHelper to edit the data - = mattermost_teams_for(current_user) - = form_for(:auto_configure, method: :post, url: configure_namespace_project_service_path(@project.namespace, @project, @service.to_param)) do |f| - = "Team ID" - = f.text_field(:team_id) - = "Team ID" - = f.submit 'Save changes', class: 'btn btn-save' + = form_for(@service, as: :service, url: namespace_project_service_path(@project.namespace, @project, @service.to_param), method: :put, html: { class: 'form-horizontal' }) do |form| + = render 'shared/service_settings', form: form, subject: @service + .footer-block.row-content-block + = form.submit 'Save changes', class: 'btn btn-save' +   + - if @service.valid? && @service.activated? + - unless @service.can_test? + - disabled_class = 'disabled' + - disabled_title = @service.disabled_title + + = link_to 'Test settings', test_namespace_project_service_path(@project.namespace, @project, @service), class: "btn #{disabled_class}", title: disabled_title + = link_to "Cancel", namespace_project_services_path(@project.namespace, @project), class: "btn btn-cancel" diff --git a/app/views/projects/services/mattermost_slash_commands/_form.html.haml b/app/views/projects/services/mattermost_slash_commands/_form.html.haml deleted file mode 100644 index 9d9c877e791..00000000000 --- a/app/views/projects/services/mattermost_slash_commands/_form.html.haml +++ /dev/null @@ -1,3 +0,0 @@ -- teams = Mattermost::Mattermost.new(Gitlab.config.mattermost.host, current_user).with_session do - Mattermost::Mattermost::Team.all - end diff --git a/app/views/shared/_service_settings.html.haml b/app/views/shared/_service_settings.html.haml index e8ab1b2ed46..9c5053dace5 100644 --- a/app/views/shared/_service_settings.html.haml +++ b/app/views/shared/_service_settings.html.haml @@ -13,41 +13,38 @@ .col-sm-10 = form.check_box :active - - if @service.auto_config? - - - else - - if @service.supported_events.present? - .form-group - = form.label :url, "Trigger", class: 'control-label' - - .col-sm-10 - - @service.supported_events.each do |event| - %div - = form.check_box service_event_field_name(event), class: 'pull-left' - .prepend-left-20 - = form.label service_event_field_name(event), class: 'list-label' do - %strong - = event.humanize - - - field = @service.event_field(event) - - - if field - %p - = form.text_field field[:name], class: "form-control", placeholder: field[:placeholder] - - %p.light - = service_event_description(event) - - - @service.global_fields.each do |field| - - type = field[:type] - - - if type == 'fieldset' - - fields = field[:fields] - - legend = field[:legend] - - %fieldset - %legend= legend - - fields.each do |subfield| - = render 'shared/field', form: form, field: subfield - - else - = render 'shared/field', form: form, field: field + - if @service.supported_events.present? + .form-group + = form.label :url, "Trigger", class: 'control-label' + + .col-sm-10 + - @service.supported_events.each do |event| + %div + = form.check_box service_event_field_name(event), class: 'pull-left' + .prepend-left-20 + = form.label service_event_field_name(event), class: 'list-label' do + %strong + = event.humanize + + - field = @service.event_field(event) + + - if field + %p + = form.text_field field[:name], class: "form-control", placeholder: field[:placeholder] + + %p.light + = service_event_description(event) + + - @service.global_fields.each do |field| + - type = field[:type] + + - if type == 'fieldset' + - fields = field[:fields] + - legend = field[:legend] + + %fieldset + %legend= legend + - fields.each do |subfield| + = render 'shared/field', form: form, field: subfield + - else + = render 'shared/field', form: form, field: field -- cgit v1.2.1 From 1b4a244dbc8d1e5b79feb4f111ec6183afa1b413 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 16 Dec 2016 23:04:01 +0800 Subject: Rename to Gitlab::Serialize::Ci::Variables Feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8088#note_20133176 --- app/models/ci/build.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 99f3f4711aa..0e30755b870 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -10,7 +10,7 @@ module Ci has_many :deployments, as: :deployable serialize :options - serialize :yaml_variables, Gitlab::Serialize::YamlVariables + serialize :yaml_variables, Gitlab::Serialize::Ci::Variables validates :coverage, numericality: true, allow_blank: true validates_presence_of :ref -- cgit v1.2.1 From 0d3e24358b88ce41848c97f3ac37bc813074f260 Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Wed, 30 Nov 2016 15:51:48 +0100 Subject: Create Slack Slash command service --- app/models/project.rb | 1 + .../slack_slash_commands_service.rb | 49 ++++++++++++++++++++++ app/models/service.rb | 3 +- .../mattermost_slash_commands/_help.html.haml | 2 +- 4 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 app/models/project_services/slack_slash_commands_service.rb (limited to 'app') diff --git a/app/models/project.rb b/app/models/project.rb index 5d092ca42c2..7f3a4debfc6 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -96,6 +96,7 @@ class Project < ActiveRecord::Base has_one :gemnasium_service, dependent: :destroy has_one :mattermost_slash_commands_service, dependent: :destroy has_one :mattermost_notification_service, dependent: :destroy + has_one :slack_slash_commands_service, dependent: :destroy has_one :slack_notification_service, dependent: :destroy has_one :buildkite_service, dependent: :destroy has_one :bamboo_service, dependent: :destroy diff --git a/app/models/project_services/slack_slash_commands_service.rb b/app/models/project_services/slack_slash_commands_service.rb new file mode 100644 index 00000000000..9c66f95eef9 --- /dev/null +++ b/app/models/project_services/slack_slash_commands_service.rb @@ -0,0 +1,49 @@ +class SlackSlashCommandsService < ChatService + include TriggersHelper + + prop_accessor :token + + def can_test? + false + end + + def title + 'Slack Slash Command' + end + + def description + "Perform common operations on GitLab in Slack" + end + + def to_param + 'slack_slash_commands' + end + + def fields + [ + { type: 'text', name: 'token', placeholder: '' } + ] + end + + def trigger(params) + return nil unless valid_token?(params[:token]) + + user = find_chat_user(params) + unless user + url = authorize_chat_name_url(params) + return Gitlab::ChatCommands::Presenters::Access.new(url).authorize + end + + Gitlab::ChatCommands::Command.new(project, user, params).execute + end + + private + + def find_chat_user(params) + ChatNames::FindUserService.new(self, params).execute + end + + def authorize_chat_name_url(params) + ChatNames::AuthorizeUserService.new(self, params).execute + end +end diff --git a/app/models/service.rb b/app/models/service.rb index 0bbab078cf6..8abd8e73e43 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -216,11 +216,12 @@ class Service < ActiveRecord::Base jira kubernetes mattermost_slash_commands + mattermost_notification pipelines_email pivotaltracker pushover redmine - mattermost_notification + slack_slash_commands slack_notification teamcity ] diff --git a/app/views/projects/services/mattermost_slash_commands/_help.html.haml b/app/views/projects/services/mattermost_slash_commands/_help.html.haml index a676c0290a0..2bdd4cd148c 100644 --- a/app/views/projects/services/mattermost_slash_commands/_help.html.haml +++ b/app/views/projects/services/mattermost_slash_commands/_help.html.haml @@ -1,4 +1,4 @@ -- pretty_path_with_namespace = "#{@project ? @project.namespace.name : 'namespace'} / #{@project ? @project.name : 'name'}" +- pretty_path_with_namespace = "#{@project.namespace ? @project.namespace.name : 'namespace'} / #{@project ? @project.name : 'name'}" - run_actions_text = "Perform common operations on this project: #{pretty_path_with_namespace}" .well -- cgit v1.2.1 From ed880e4954803f9753cfafe0dd8106852245d10d Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 15 Dec 2016 23:45:10 +0100 Subject: Rename ChatService into ChatSlashCommandsService --- app/models/project.rb | 1 - app/models/project_services/chat_service.rb | 21 --------- .../chat_slash_commands_service.rb | 55 ++++++++++++++++++++++ .../mattermost_slash_commands_service.rb | 28 +---------- .../slack_slash_commands_service.rb | 36 ++------------ 5 files changed, 60 insertions(+), 81 deletions(-) delete mode 100644 app/models/project_services/chat_service.rb create mode 100644 app/models/project_services/chat_slash_commands_service.rb (limited to 'app') diff --git a/app/models/project.rb b/app/models/project.rb index 7f3a4debfc6..9d8351399f9 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -79,7 +79,6 @@ class Project < ActiveRecord::Base has_one :last_event, -> {order 'events.created_at DESC'}, class_name: 'Event' has_many :boards, before_add: :validate_board_limit, dependent: :destroy - has_many :chat_services # Project services has_one :campfire_service, dependent: :destroy diff --git a/app/models/project_services/chat_service.rb b/app/models/project_services/chat_service.rb deleted file mode 100644 index 574788462de..00000000000 --- a/app/models/project_services/chat_service.rb +++ /dev/null @@ -1,21 +0,0 @@ -# Base class for Chat services -# This class is not meant to be used directly, but only to inherit from. -class ChatService < Service - default_value_for :category, 'chat' - - has_many :chat_names, foreign_key: :service_id - - def valid_token?(token) - self.respond_to?(:token) && - self.token.present? && - ActiveSupport::SecurityUtils.variable_size_secure_compare(token, self.token) - end - - def supported_events - [] - end - - def trigger(params) - raise NotImplementedError - end -end diff --git a/app/models/project_services/chat_slash_commands_service.rb b/app/models/project_services/chat_slash_commands_service.rb new file mode 100644 index 00000000000..b21a1730285 --- /dev/null +++ b/app/models/project_services/chat_slash_commands_service.rb @@ -0,0 +1,55 @@ +# Base class for Chat services +# This class is not meant to be used directly, but only to inherrit from. +class ChatSlashCommandsService < Service + default_value_for :category, 'chat' + + prop_accessor :token + + has_many :chat_names, foreign_key: :service_id + + def valid_token?(token) + self.respond_to?(:token) && + self.token.present? && + ActiveSupport::SecurityUtils.variable_size_secure_compare(token, self.token) + end + + def supported_events + [] + end + + def can_test? + false + end + + def fields + [ + { type: 'text', name: 'token', placeholder: '' } + ] + end + + def trigger(params) + return nil unless valid_token?(params[:token]) + + user = find_chat_user(params) + unless user + url = authorize_chat_name_url(params) + return presenter.authorize_chat_name(url) + end + + Gitlab::ChatCommands::Command.new(presenter, project, user, params).execute + end + + private + + def find_chat_user(params) + ChatNames::FindUserService.new(self, params).execute + end + + def authorize_chat_name_url(params) + ChatNames::AuthorizeUserService.new(self, params).execute + end + + def presenter + throw NotImplementedError + end +end diff --git a/app/models/project_services/mattermost_slash_commands_service.rb b/app/models/project_services/mattermost_slash_commands_service.rb index 33431f41dc2..4c1e27cafbb 100644 --- a/app/models/project_services/mattermost_slash_commands_service.rb +++ b/app/models/project_services/mattermost_slash_commands_service.rb @@ -19,31 +19,7 @@ class MattermostSlashCommandsService < ChatService 'mattermost_slash_commands' end - def fields - [ - { type: 'text', name: 'token', placeholder: '' } - ] - end - - def trigger(params) - return nil unless valid_token?(params[:token]) - - user = find_chat_user(params) - unless user - url = authorize_chat_name_url(params) - return Mattermost::Presenter.authorize_chat_name(url) - end - - Gitlab::ChatCommands::Command.new(project, user, params).execute - end - - private - - def find_chat_user(params) - ChatNames::FindUserService.new(self, params).execute - end - - def authorize_chat_name_url(params) - ChatNames::AuthorizeUserService.new(self, params).execute + def presenter + Gitlab::ChatCommands::Presenters::Mattermost.new end end diff --git a/app/models/project_services/slack_slash_commands_service.rb b/app/models/project_services/slack_slash_commands_service.rb index 9c66f95eef9..978d48e8c18 100644 --- a/app/models/project_services/slack_slash_commands_service.rb +++ b/app/models/project_services/slack_slash_commands_service.rb @@ -1,12 +1,6 @@ -class SlackSlashCommandsService < ChatService +class SlackSlashCommandsService < ChatSlashCommandsService include TriggersHelper - prop_accessor :token - - def can_test? - false - end - def title 'Slack Slash Command' end @@ -19,31 +13,7 @@ class SlackSlashCommandsService < ChatService 'slack_slash_commands' end - def fields - [ - { type: 'text', name: 'token', placeholder: '' } - ] - end - - def trigger(params) - return nil unless valid_token?(params[:token]) - - user = find_chat_user(params) - unless user - url = authorize_chat_name_url(params) - return Gitlab::ChatCommands::Presenters::Access.new(url).authorize - end - - Gitlab::ChatCommands::Command.new(project, user, params).execute - end - - private - - def find_chat_user(params) - ChatNames::FindUserService.new(self, params).execute - end - - def authorize_chat_name_url(params) - ChatNames::AuthorizeUserService.new(self, params).execute + def presenter + Gitlab::ChatCommands::Presenters::Mattermost.new end end -- cgit v1.2.1 From 8ca5fef9d472e11b4a9ff5d5ab47bbba3e7e670d Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 15 Dec 2016 23:48:30 +0100 Subject: Use single presenter for everything --- app/models/project_services/chat_slash_commands_service.rb | 8 ++------ app/models/project_services/mattermost_slash_commands_service.rb | 4 ---- app/models/project_services/slack_slash_commands_service.rb | 4 ---- 3 files changed, 2 insertions(+), 14 deletions(-) (limited to 'app') diff --git a/app/models/project_services/chat_slash_commands_service.rb b/app/models/project_services/chat_slash_commands_service.rb index b21a1730285..7ff80447a1c 100644 --- a/app/models/project_services/chat_slash_commands_service.rb +++ b/app/models/project_services/chat_slash_commands_service.rb @@ -33,10 +33,10 @@ class ChatSlashCommandsService < Service user = find_chat_user(params) unless user url = authorize_chat_name_url(params) - return presenter.authorize_chat_name(url) + return Gitlab::ChatCommands::Presenter.authorize_chat_name(url) end - Gitlab::ChatCommands::Command.new(presenter, project, user, params).execute + Gitlab::ChatCommands::Command.new(project, user, params).execute end private @@ -48,8 +48,4 @@ class ChatSlashCommandsService < Service def authorize_chat_name_url(params) ChatNames::AuthorizeUserService.new(self, params).execute end - - def presenter - throw NotImplementedError - end end diff --git a/app/models/project_services/mattermost_slash_commands_service.rb b/app/models/project_services/mattermost_slash_commands_service.rb index 4c1e27cafbb..6aac7c2788b 100644 --- a/app/models/project_services/mattermost_slash_commands_service.rb +++ b/app/models/project_services/mattermost_slash_commands_service.rb @@ -18,8 +18,4 @@ class MattermostSlashCommandsService < ChatService def to_param 'mattermost_slash_commands' end - - def presenter - Gitlab::ChatCommands::Presenters::Mattermost.new - end end diff --git a/app/models/project_services/slack_slash_commands_service.rb b/app/models/project_services/slack_slash_commands_service.rb index 978d48e8c18..197d8eb7bca 100644 --- a/app/models/project_services/slack_slash_commands_service.rb +++ b/app/models/project_services/slack_slash_commands_service.rb @@ -12,8 +12,4 @@ class SlackSlashCommandsService < ChatSlashCommandsService def to_param 'slack_slash_commands' end - - def presenter - Gitlab::ChatCommands::Presenters::Mattermost.new - end end -- cgit v1.2.1 From cc83aded33471a3e2f943bd9a760f689d30f901e Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 16 Dec 2016 00:00:54 +0100 Subject: Render format dependent links --- app/models/project_services/chat_slash_commands_service.rb | 13 +++++++++++-- .../project_services/mattermost_slash_commands_service.rb | 4 ++++ app/models/project_services/slack_slash_commands_service.rb | 4 ++++ 3 files changed, 19 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/models/project_services/chat_slash_commands_service.rb b/app/models/project_services/chat_slash_commands_service.rb index 7ff80447a1c..f11d257e6c1 100644 --- a/app/models/project_services/chat_slash_commands_service.rb +++ b/app/models/project_services/chat_slash_commands_service.rb @@ -33,10 +33,11 @@ class ChatSlashCommandsService < Service user = find_chat_user(params) unless user url = authorize_chat_name_url(params) - return Gitlab::ChatCommands::Presenter.authorize_chat_name(url) + return presenter.authorize_chat_name(url) end - Gitlab::ChatCommands::Command.new(project, user, params).execute + Gitlab::ChatCommands::Command.new(project, user, + params.merge(presenter_format: presenter_format)).execute end private @@ -48,4 +49,12 @@ class ChatSlashCommandsService < Service def authorize_chat_name_url(params) ChatNames::AuthorizeUserService.new(self, params).execute end + + def presenter + Gitlab::ChatCommands::Presenter.new(presenter_format) + end + + def presenter_format + throw NotImplementedError + end end diff --git a/app/models/project_services/mattermost_slash_commands_service.rb b/app/models/project_services/mattermost_slash_commands_service.rb index 6aac7c2788b..f9d4b29f4ea 100644 --- a/app/models/project_services/mattermost_slash_commands_service.rb +++ b/app/models/project_services/mattermost_slash_commands_service.rb @@ -18,4 +18,8 @@ class MattermostSlashCommandsService < ChatService def to_param 'mattermost_slash_commands' end + + def presenter_format + 'mattermost' + end end diff --git a/app/models/project_services/slack_slash_commands_service.rb b/app/models/project_services/slack_slash_commands_service.rb index 197d8eb7bca..6bf10ff6572 100644 --- a/app/models/project_services/slack_slash_commands_service.rb +++ b/app/models/project_services/slack_slash_commands_service.rb @@ -12,4 +12,8 @@ class SlackSlashCommandsService < ChatSlashCommandsService def to_param 'slack_slash_commands' end + + def presenter_format + 'slack' + end end -- cgit v1.2.1 From ebc3f62be52e386b4550e01ce589744e880ad443 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 16 Dec 2016 13:32:05 +0100 Subject: Fix specs --- .../projects/services/mattermost_slash_commands/_help.html.haml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/views/projects/services/mattermost_slash_commands/_help.html.haml b/app/views/projects/services/mattermost_slash_commands/_help.html.haml index 2bdd4cd148c..01a77a952d1 100644 --- a/app/views/projects/services/mattermost_slash_commands/_help.html.haml +++ b/app/views/projects/services/mattermost_slash_commands/_help.html.haml @@ -1,5 +1,4 @@ -- pretty_path_with_namespace = "#{@project.namespace ? @project.namespace.name : 'namespace'} / #{@project ? @project.name : 'name'}" -- run_actions_text = "Perform common operations on this project: #{pretty_path_with_namespace}" +- run_actions_text = "Perform common operations on this project: #{@project.name_with_namespace}" .well This service allows GitLab users to perform common operations on this @@ -27,7 +26,7 @@ .form-group = label_tag :display_name, 'Display name', class: 'col-sm-2 col-xs-12 control-label' .col-sm-10.col-xs-12.input-group - = text_field_tag :display_name, "GitLab / #{pretty_path_with_namespace}", class: 'form-control input-sm', readonly: 'readonly' + = text_field_tag :display_name, "GitLab / #{@project.name_with_namespace}", class: 'form-control input-sm', readonly: 'readonly' .input-group-btn = clipboard_button(clipboard_target: '#display_name') -- cgit v1.2.1 From f9f1a508c6a4bdb2fcee98d18394e28e1cc663c3 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 16 Dec 2016 14:21:06 +0100 Subject: Fix SlackSlashCommands tests --- app/models/project_services/chat_slash_commands_service.rb | 2 +- app/models/project_services/mattermost_slash_commands_service.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/models/project_services/chat_slash_commands_service.rb b/app/models/project_services/chat_slash_commands_service.rb index f11d257e6c1..e58c96f5094 100644 --- a/app/models/project_services/chat_slash_commands_service.rb +++ b/app/models/project_services/chat_slash_commands_service.rb @@ -5,7 +5,7 @@ class ChatSlashCommandsService < Service prop_accessor :token - has_many :chat_names, foreign_key: :service_id + has_many :chat_names, foreign_key: :service_id, dependent: :destroy def valid_token?(token) self.respond_to?(:token) && diff --git a/app/models/project_services/mattermost_slash_commands_service.rb b/app/models/project_services/mattermost_slash_commands_service.rb index f9d4b29f4ea..72a7b9c8f3a 100644 --- a/app/models/project_services/mattermost_slash_commands_service.rb +++ b/app/models/project_services/mattermost_slash_commands_service.rb @@ -1,4 +1,4 @@ -class MattermostSlashCommandsService < ChatService +class MattermostSlashCommandsService < ChatSlashCommandsService include TriggersHelper prop_accessor :token -- cgit v1.2.1 From 0f2776287a7d9b0fde9ff54ef8d9f74e2f844a09 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 16 Dec 2016 15:08:10 +0100 Subject: Use Slack::Notifier::LinkFormatter to convert markdown links to slack compat --- app/models/project_services/chat_slash_commands_service.rb | 8 ++------ .../project_services/mattermost_slash_commands_service.rb | 4 ---- app/models/project_services/slack_slash_commands_service.rb | 11 +++++++++-- 3 files changed, 11 insertions(+), 12 deletions(-) (limited to 'app') diff --git a/app/models/project_services/chat_slash_commands_service.rb b/app/models/project_services/chat_slash_commands_service.rb index e58c96f5094..12261e9821e 100644 --- a/app/models/project_services/chat_slash_commands_service.rb +++ b/app/models/project_services/chat_slash_commands_service.rb @@ -37,7 +37,7 @@ class ChatSlashCommandsService < Service end Gitlab::ChatCommands::Command.new(project, user, - params.merge(presenter_format: presenter_format)).execute + params).execute end private @@ -51,10 +51,6 @@ class ChatSlashCommandsService < Service end def presenter - Gitlab::ChatCommands::Presenter.new(presenter_format) - end - - def presenter_format - throw NotImplementedError + Gitlab::ChatCommands::Presenter.new end end diff --git a/app/models/project_services/mattermost_slash_commands_service.rb b/app/models/project_services/mattermost_slash_commands_service.rb index 72a7b9c8f3a..10740275669 100644 --- a/app/models/project_services/mattermost_slash_commands_service.rb +++ b/app/models/project_services/mattermost_slash_commands_service.rb @@ -18,8 +18,4 @@ class MattermostSlashCommandsService < ChatSlashCommandsService def to_param 'mattermost_slash_commands' end - - def presenter_format - 'mattermost' - end end diff --git a/app/models/project_services/slack_slash_commands_service.rb b/app/models/project_services/slack_slash_commands_service.rb index 6bf10ff6572..8413c657099 100644 --- a/app/models/project_services/slack_slash_commands_service.rb +++ b/app/models/project_services/slack_slash_commands_service.rb @@ -13,7 +13,14 @@ class SlackSlashCommandsService < ChatSlashCommandsService 'slack_slash_commands' end - def presenter_format - 'slack' + def trigger(params) + result = super + + # Format messages to be Slack-compatible + if result && result[:text] + result[:text] = Slack::Notifier::LinkFormatter.format(result[:text]) + end + + result end end -- cgit v1.2.1 From c46b758b48400efff5241efafad94c2ddbb8224c Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Fri, 16 Dec 2016 17:56:27 +0000 Subject: Remove unused style for dropdown. Improves animation --- app/assets/stylesheets/pages/pipelines.scss | 48 ++++++++++++++--------------- 1 file changed, 23 insertions(+), 25 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index a0719b415e5..b3deac3ab75 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -466,6 +466,28 @@ margin-bottom: 10px; white-space: normal; + + .dropdown-menu-toggle { + background-color: transparent; + border: none; + padding: 0; + color: $gl-text-color-light; + flex-grow: 1; + + + &:focus { + outline: none; + } + + &:hover { + color: $gl-text-color; + + .dropdown-counter-badge { + color: $gl-text-color; + } + } + } + &:hover { background-color: $stage-hover-bg; border: 1px solid $stage-hover-border; @@ -635,28 +657,6 @@ font-weight: 100; } - -.dropdown-menu-toggle { - background-color: transparent; - border: none; - padding: 0; - color: $gl-text-color-light; - flex-grow: 1; - - - &:focus { - outline: none; - } - - &:hover { - color: $gl-text-color; - - .dropdown-counter-badge { - color: $gl-text-color; - } - } -} - // Action Icons .ci-action-icon-container .ci-action-icon-wrapper { float: right; @@ -816,7 +816,7 @@ .ci-status-icon { width: 28px; padding: 0 8px 0 0; - transition: all 0.2s cubic-bezier(0.25, 0, 1, 1); + transition: width 0.2s cubic-bezier(0.25, 0, 1, 1); + .dropdown-caret { display: inline-block; @@ -853,7 +853,6 @@ .ci-status-icon-skipped { background-color: rgba($gray-darkest, .1); } - } .mini-pipeline-graph-icon-container { @@ -861,7 +860,6 @@ .ci-status-icon:focus { width: 28px; padding: 0 8px 0 0; - transition: all 0.2s cubic-bezier(0.25, 0, 1, 1); + .dropdown-caret { display: inline-block; -- cgit v1.2.1 From 170efaaba273792ddffc2806ef1501f33d87a5a2 Mon Sep 17 00:00:00 2001 From: Rydkin Maxim Date: Fri, 16 Dec 2016 01:14:20 +0300 Subject: Enable Style/MultilineOperationIndentation in Rubocop, fixes #25741 --- app/controllers/jwt_controller.rb | 2 +- app/controllers/sessions_controller.rb | 2 +- app/helpers/form_helper.rb | 12 ++++++------ app/helpers/nav_helper.rb | 18 +++++++++--------- app/helpers/tab_helper.rb | 6 +++--- app/models/member.rb | 4 ++-- app/models/network/graph.rb | 4 ++-- app/models/project_services/issue_tracker_service.rb | 4 ++-- app/models/user.rb | 2 +- app/policies/note_policy.rb | 2 +- app/policies/project_policy.rb | 12 ++++++------ app/services/groups/update_service.rb | 2 +- app/services/issues/update_service.rb | 2 +- app/services/merge_requests/build_service.rb | 2 +- app/services/merge_requests/update_service.rb | 2 +- app/services/projects/update_service.rb | 2 +- 16 files changed, 39 insertions(+), 39 deletions(-) (limited to 'app') diff --git a/app/controllers/jwt_controller.rb b/app/controllers/jwt_controller.rb index c736200a104..c2e4d62b50b 100644 --- a/app/controllers/jwt_controller.rb +++ b/app/controllers/jwt_controller.rb @@ -26,7 +26,7 @@ class JwtController < ApplicationController @authentication_result = Gitlab::Auth.find_for_git_client(login, password, project: nil, ip: request.ip) render_unauthorized unless @authentication_result.success? && - (@authentication_result.actor.nil? || @authentication_result.actor.is_a?(User)) + (@authentication_result.actor.nil? || @authentication_result.actor.is_a?(User)) end rescue Gitlab::Auth::MissingPersonalTokenError render_missing_personal_token diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 8c698695202..93a180b9036 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -114,7 +114,7 @@ class SessionsController < Devise::SessionsController def valid_otp_attempt?(user) user.validate_and_consume_otp!(user_params[:otp_attempt]) || - user.invalidate_otp_backup_code!(user_params[:otp_attempt]) + user.invalidate_otp_backup_code!(user_params[:otp_attempt]) end def log_audit_event(user, options = {}) diff --git a/app/helpers/form_helper.rb b/app/helpers/form_helper.rb index 6a43be2cf3e..1182939f656 100644 --- a/app/helpers/form_helper.rb +++ b/app/helpers/form_helper.rb @@ -7,12 +7,12 @@ module FormHelper content_tag(:div, class: 'alert alert-danger', id: 'error_explanation') do content_tag(:h4, headline) << - content_tag(:ul) do - model.errors.full_messages. - map { |msg| content_tag(:li, msg) }. - join. - html_safe - end + content_tag(:ul) do + model.errors.full_messages. + map { |msg| content_tag(:li, msg) }. + join. + html_safe + end end end end diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb index a3331dc80cb..e21178c7377 100644 --- a/app/helpers/nav_helper.rb +++ b/app/helpers/nav_helper.rb @@ -7,12 +7,12 @@ module NavHelper def page_gutter_class if current_path?('merge_requests#show') || - current_path?('merge_requests#diffs') || - current_path?('merge_requests#commits') || - current_path?('merge_requests#builds') || - current_path?('merge_requests#conflicts') || - current_path?('merge_requests#pipelines') || - current_path?('issues#show') + current_path?('merge_requests#diffs') || + current_path?('merge_requests#commits') || + current_path?('merge_requests#builds') || + current_path?('merge_requests#conflicts') || + current_path?('merge_requests#pipelines') || + current_path?('issues#show') if cookies[:collapsed_gutter] == 'true' "page-gutter right-sidebar-collapsed" else @@ -21,9 +21,9 @@ module NavHelper elsif current_path?('builds#show') "page-gutter build-sidebar right-sidebar-expanded" elsif current_path?('wikis#show') || - current_path?('wikis#edit') || - current_path?('wikis#history') || - current_path?('wikis#git_access') + current_path?('wikis#edit') || + current_path?('wikis#history') || + current_path?('wikis#git_access') "page-gutter wiki-sidebar right-sidebar-expanded" end end diff --git a/app/helpers/tab_helper.rb b/app/helpers/tab_helper.rb index 563ddd2a511..547f6258909 100644 --- a/app/helpers/tab_helper.rb +++ b/app/helpers/tab_helper.rb @@ -106,9 +106,9 @@ module TabHelper def branches_tab_class if current_controller?(:protected_branches) || - current_controller?(:branches) || - current_page?(namespace_project_repository_path(@project.namespace, - @project)) + current_controller?(:branches) || + current_page?(namespace_project_repository_path(@project.namespace, + @project)) 'active' end end diff --git a/app/models/member.rb b/app/models/member.rb index 3b65587c66b..d29b3c68cf6 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -89,8 +89,8 @@ class Member < ActiveRecord::Base member = if user.is_a?(User) source.members.find_by(user_id: user.id) || - source.requesters.find_by(user_id: user.id) || - source.members.build(user_id: user.id) + source.requesters.find_by(user_id: user.id) || + source.members.build(user_id: user.id) else source.members.build(invite_email: user) end diff --git a/app/models/network/graph.rb b/app/models/network/graph.rb index 345041a6ad1..b524ca50ee8 100644 --- a/app/models/network/graph.rb +++ b/app/models/network/graph.rb @@ -161,8 +161,8 @@ module Network def is_overlap?(range, overlap_space) range.each do |i| if i != range.first && - i != range.last && - @commits[i].spaces.include?(overlap_space) + i != range.last && + @commits[i].spaces.include?(overlap_space) return true end diff --git a/app/models/project_services/issue_tracker_service.rb b/app/models/project_services/issue_tracker_service.rb index 207bb816ad1..bce2cdd5516 100644 --- a/app/models/project_services/issue_tracker_service.rb +++ b/app/models/project_services/issue_tracker_service.rb @@ -85,8 +85,8 @@ class IssueTrackerService < Service def enabled_in_gitlab_config Gitlab.config.issues_tracker && - Gitlab.config.issues_tracker.values.any? && - issues_tracker + Gitlab.config.issues_tracker.values.any? && + issues_tracker end def issues_tracker diff --git a/app/models/user.rb b/app/models/user.rb index 1bd28203523..3f8bbbc425d 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -390,7 +390,7 @@ class User < ActiveRecord::Base def namespace_uniq # Return early if username already failed the first uniqueness validation return if errors.key?(:username) && - errors[:username].include?('has already been taken') + errors[:username].include?('has already been taken') existing_namespace = Namespace.by_path(username) if existing_namespace && existing_namespace != namespace diff --git a/app/policies/note_policy.rb b/app/policies/note_policy.rb index 83847466ee2..5326061bd07 100644 --- a/app/policies/note_policy.rb +++ b/app/policies/note_policy.rb @@ -12,7 +12,7 @@ class NotePolicy < BasePolicy end if @subject.for_merge_request? && - @subject.noteable.author == @user + @subject.noteable.author == @user can! :resolve_note end end diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb index d5aadfce76a..b5db9c12622 100644 --- a/app/policies/project_policy.rb +++ b/app/policies/project_policy.rb @@ -3,7 +3,7 @@ class ProjectPolicy < BasePolicy team_access!(user) owner = project.owner == user || - (project.group && project.group.has_owner?(user)) + (project.group && project.group.has_owner?(user)) owner_access! if user.admin? || owner team_member_owner_access! if owner @@ -13,7 +13,7 @@ class ProjectPolicy < BasePolicy public_access! if project.request_access_enabled && - !(owner || user.admin? || project.team.member?(user) || project_group_member?(user)) + !(owner || user.admin? || project.team.member?(user) || project_group_member?(user)) can! :request_access end end @@ -244,10 +244,10 @@ class ProjectPolicy < BasePolicy def project_group_member?(user) project.group && - ( - project.group.members.exists?(user_id: user.id) || - project.group.requesters.exists?(user_id: user.id) - ) + ( + project.group.members.exists?(user_id: user.id) || + project.group.requesters.exists?(user_id: user.id) + ) end def named_abilities(name) diff --git a/app/services/groups/update_service.rb b/app/services/groups/update_service.rb index 99ad12b1003..fff2273f402 100644 --- a/app/services/groups/update_service.rb +++ b/app/services/groups/update_service.rb @@ -5,7 +5,7 @@ module Groups new_visibility = params[:visibility_level] if new_visibility && new_visibility.to_i != group.visibility_level unless can?(current_user, :change_visibility_level, group) && - Gitlab::VisibilityLevel.allowed_for?(current_user, new_visibility) + Gitlab::VisibilityLevel.allowed_for?(current_user, new_visibility) deny_visibility_level(group, new_visibility) return group diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb index a2111b3806b..78cbf94ec69 100644 --- a/app/services/issues/update_service.rb +++ b/app/services/issues/update_service.rb @@ -10,7 +10,7 @@ module Issues end if issue.previous_changes.include?('title') || - issue.previous_changes.include?('description') + issue.previous_changes.include?('description') todo_service.update_issue(issue, current_user) end diff --git a/app/services/merge_requests/build_service.rb b/app/services/merge_requests/build_service.rb index bebfca7537b..6a7393a9921 100644 --- a/app/services/merge_requests/build_service.rb +++ b/app/services/merge_requests/build_service.rb @@ -42,7 +42,7 @@ module MergeRequests end if merge_request.source_project == merge_request.target_project && - merge_request.target_branch == merge_request.source_branch + merge_request.target_branch == merge_request.source_branch messages << 'You must select different branches' end diff --git a/app/services/merge_requests/update_service.rb b/app/services/merge_requests/update_service.rb index fda0da19d87..ad16ef8c70f 100644 --- a/app/services/merge_requests/update_service.rb +++ b/app/services/merge_requests/update_service.rb @@ -25,7 +25,7 @@ module MergeRequests end if merge_request.previous_changes.include?('title') || - merge_request.previous_changes.include?('description') + merge_request.previous_changes.include?('description') todo_service.update_merge_request(merge_request, current_user) end diff --git a/app/services/projects/update_service.rb b/app/services/projects/update_service.rb index 921ca6748d3..8a6af8d8ada 100644 --- a/app/services/projects/update_service.rb +++ b/app/services/projects/update_service.rb @@ -6,7 +6,7 @@ module Projects if new_visibility && new_visibility.to_i != project.visibility_level unless can?(current_user, :change_visibility_level, project) && - Gitlab::VisibilityLevel.allowed_for?(current_user, new_visibility) + Gitlab::VisibilityLevel.allowed_for?(current_user, new_visibility) deny_visibility_level(project, new_visibility) return project -- cgit v1.2.1 From 88e364f0f6f8d21b73f9eea786c7f8326dff61fe Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Fri, 16 Dec 2016 12:56:38 -0600 Subject: Put back bootstrap wells --- app/assets/stylesheets/framework/tw_bootstrap.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/tw_bootstrap.scss b/app/assets/stylesheets/framework/tw_bootstrap.scss index d998d654aa4..718dbbfea27 100644 --- a/app/assets/stylesheets/framework/tw_bootstrap.scss +++ b/app/assets/stylesheets/framework/tw_bootstrap.scss @@ -35,7 +35,7 @@ @import "bootstrap/alerts"; // @import "bootstrap/progress-bars"; @import "bootstrap/list-group"; -// @import "bootstrap/wells"; +@import "bootstrap/wells"; @import "bootstrap/close"; @import "bootstrap/panels"; -- cgit v1.2.1 From 1b313e8db8513f41808923d9d429305a68bcee3a Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 15 Dec 2016 12:55:20 +0100 Subject: Make CI/CD detailed status group concept explicit --- app/views/ci/status/_badge.html.haml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/views/ci/status/_badge.html.haml b/app/views/ci/status/_badge.html.haml index f2135af2686..601fb7f0f3f 100644 --- a/app/views/ci/status/_badge.html.haml +++ b/app/views/ci/status/_badge.html.haml @@ -1,10 +1,11 @@ - status = local_assigns.fetch(:status) +- css_classes = "ci-status ci-#{status.group}" - if status.has_details? - = link_to status.details_path, class: "ci-status ci-#{status}" do + = link_to status.details_path, class: css_classes do = custom_icon(status.icon) = status.text - else - %span{ class: "ci-status ci-#{status}" } + %span{ class: css_classes } = custom_icon(status.icon) = status.text -- cgit v1.2.1 From cce41cb2a6574de609211e4e2284f684e2d236d8 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Thu, 15 Dec 2016 18:08:11 +0000 Subject: Adds CSS --- app/assets/stylesheets/framework/icons.scss | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'app') diff --git a/app/assets/stylesheets/framework/icons.scss b/app/assets/stylesheets/framework/icons.scss index 226bd2ead31..b37847e3d96 100644 --- a/app/assets/stylesheets/framework/icons.scss +++ b/app/assets/stylesheets/framework/icons.scss @@ -49,3 +49,11 @@ fill: $gray-darkest; } } + +.ci-status-icon-manual { + color: $gl-text-color; + + svg { + fill: $gray-darkest; + } +} -- cgit v1.2.1 From f0889bdfa3e0d1433b3cd293859b13ee9d186ab6 Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Fri, 16 Dec 2016 20:29:17 +0100 Subject: Incorporate review --- app/controllers/projects/services_controller.rb | 2 +- .../mattermost_slash_commands_service.rb | 26 +++++++++++++++++----- app/views/projects/mattermost/new.html.haml | 2 -- 3 files changed, 21 insertions(+), 9 deletions(-) (limited to 'app') diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb index b4f5750b0a4..30c2a5d9982 100644 --- a/app/controllers/projects/services_controller.rb +++ b/app/controllers/projects/services_controller.rb @@ -3,7 +3,7 @@ class Projects::ServicesController < Projects::ApplicationController # Authorize before_action :authorize_admin_project! - before_action :service, only: [:edit, :update, :test, :configure] + before_action :service, only: [:edit, :update, :test] respond_to :html diff --git a/app/models/project_services/mattermost_slash_commands_service.rb b/app/models/project_services/mattermost_slash_commands_service.rb index 5af85d9a598..5dfc4cc2744 100644 --- a/app/models/project_services/mattermost_slash_commands_service.rb +++ b/app/models/project_services/mattermost_slash_commands_service.rb @@ -25,15 +25,12 @@ class MattermostSlashCommandsService < ChatService ] end - def configure(host, current_user, team_id:, trigger:, url:, icon_url:) + def configure(host, current_user, params) new_token = Mattermost::Session.new(host, current_user).with_session do - Mattermost::Command.create(team_id, - trigger: trigger || @service.project.path, - url: url, - icon_url: icon_url) + Mattermost::Command.create(params[:team_id], command) end - update!(token: new_token) + update!(token: new_token, active: true) end def trigger(params) @@ -50,6 +47,23 @@ class MattermostSlashCommandsService < ChatService private + def command(trigger:, url:, icon_url:) + pretty_project_name = project.name_with_namespace + + { + auto_complete: true, + auto_complete_desc: "Perform common operations on: #{pretty_project_name}", + auto_complete_hint: '[help]', + description: "Perform common operations on: #{pretty_project_name}", + display_name: "GitLab / #{pretty_project_name}", + method: 'P', + user_name: 'GitLab', + trigger: trigger, + url: url, + icon_url: icon_url + } + end + def find_chat_user(params) ChatNames::FindUserService.new(self, params).execute end diff --git a/app/views/projects/mattermost/new.html.haml b/app/views/projects/mattermost/new.html.haml index b4a1476be13..88270985e7b 100644 --- a/app/views/projects/mattermost/new.html.haml +++ b/app/views/projects/mattermost/new.html.haml @@ -1,5 +1,3 @@ -= "hello world" -= @teams = form_for(:create, method: :post, url: configure_namespace_project_mattermost_path(@project.namespace, @project, )) do |f| = "Team ID" = f.text_field(:team_id) -- cgit v1.2.1 From d58fffb27766f49b82866c5460fe218854f9596e Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Fri, 16 Dec 2016 14:30:28 -0600 Subject: fix margin on alert stripes within ":flash_message" block --- app/assets/stylesheets/framework/layout.scss | 8 ++++++++ app/views/layouts/_page.html.haml | 7 ++++--- 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/layout.scss b/app/assets/stylesheets/framework/layout.scss index 66711aa1804..bef24162924 100644 --- a/app/assets/stylesheets/framework/layout.scss +++ b/app/assets/stylesheets/framework/layout.scss @@ -32,6 +32,14 @@ body { } } +.alert-wrapper { + margin-bottom: $gl-padding; + + .alert { + margin-bottom: 0; + } +} + /* The following prevents side effects related to iOS Safari's implementation of -webkit-overflow-scrolling: touch, which is applied to the body by jquery.nicescroling plugin to force hardware acceleration for momentum scrolling. Side diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml index a9a0b149049..54d02ee8e4b 100644 --- a/app/views/layouts/_page.html.haml +++ b/app/views/layouts/_page.html.haml @@ -22,9 +22,10 @@ = render "layouts/nav/#{nav}" .content-wrapper{ class: "#{layout_nav_class}" } = yield :sub_nav - = render "layouts/broadcast" - = render "layouts/flash" - = yield :flash_message + .alert-wrapper + = render "layouts/broadcast" + = render "layouts/flash" + = yield :flash_message %div{ class: "#{(container_class unless @no_container)} #{@content_class}" } .content{ id: "content-body" } = yield -- cgit v1.2.1 From dc9b0913670dc8de5e01a40fd28fa44f48defc9e Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Fri, 16 Dec 2016 14:38:01 -0600 Subject: stripe colors for successive alert-warning blocks --- app/assets/stylesheets/framework/layout.scss | 27 +++++++++++++++++++++++++ app/assets/stylesheets/framework/variables.scss | 1 - app/assets/stylesheets/pages/projects.scss | 6 ------ 3 files changed, 27 insertions(+), 7 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/layout.scss b/app/assets/stylesheets/framework/layout.scss index bef24162924..59fae61a44f 100644 --- a/app/assets/stylesheets/framework/layout.scss +++ b/app/assets/stylesheets/framework/layout.scss @@ -38,6 +38,33 @@ body { .alert { margin-bottom: 0; } + + /* Stripe the background colors so that adjacent alert-warnings are distinct from one another */ + .alert-warning { + transition: background-color 0.15s, border-color 0.15s; + background-color: lighten($gl-warning, 4%); + border-color: lighten($gl-warning, 4%); + } + + .alert-warning + .alert-warning { + background-color: $gl-warning; + border-color: $gl-warning; + } + + .alert-warning + .alert-warning + .alert-warning { + background-color: darken($gl-warning, 4%); + border-color: darken($gl-warning, 4%); + } + + .alert-warning + .alert-warning + .alert-warning + .alert-warning { + background-color: darken($gl-warning, 8%); + border-color: darken($gl-warning, 8%); + } + + .alert-warning:only-of-type { + background-color: $gl-warning; + border-color: $gl-warning; + } } diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 267fcd77b38..0b156d61a23 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -474,7 +474,6 @@ $project-option-descr-color: #54565b; $project-breadcrumb-color: #999; $project-private-forks-notice-odd: #2aa056; $project-network-controls-color: #888; -$project-limit-message-bg: #f28d35; /* * Runners diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 9c3dbc58ae0..3b1b375133d 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -6,12 +6,6 @@ } } -.no-ssh-key-message, -.project-limit-message { - background-color: $project-limit-message-bg; - margin-bottom: 0; -} - .new_project, .edit-project { -- cgit v1.2.1 From 178f9ebb67bddbd2719cbd140967103b57f2c0c7 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Thu, 15 Dec 2016 19:32:03 -0500 Subject: Respect newlines in commit messages on network graph --- app/assets/javascripts/network/branch_graph.js | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/network/branch_graph.js b/app/assets/javascripts/network/branch_graph.js index 64b19a54893..20a68780cd5 100644 --- a/app/assets/javascripts/network/branch_graph.js +++ b/app/assets/javascripts/network/branch_graph.js @@ -356,7 +356,7 @@ icon = this.image(gon.relative_url_root + commit.author.icon, x, y, 20, 20); nameText = this.text(x + 25, y + 10, commit.author.name); idText = this.text(x, y + 35, commit.id); - messageText = this.text(x, y + 50, commit.message); + messageText = this.text(x, y + 50, commit.message.replace(/\r?\n/g, " \n ")); textSet = this.set(icon, nameText, idText, messageText).attr({ "text-anchor": "start", font: "12px Monaco, monospace" @@ -368,6 +368,7 @@ idText.attr({ fill: "#AAA" }); + messageText.node.style["white-space"] = "pre"; this.textWrap(messageText, boxWidth - 50); rect = this.rect(x - 10, y - 10, boxWidth, 100, 4).attr({ fill: "#FFF", @@ -404,16 +405,21 @@ s.push("\n"); x = 0; } - x += word.length * letterWidth; - s.push(word + " "); + if (word === "\n") { + s.push("\n"); + x = 0; + } else { + s.push(word + " "); + x += word.length * letterWidth; + } } t.attr({ - text: s.join("") + text: s.join("").trim() }); b = t.getBBox(); - h = Math.abs(b.y2) - Math.abs(b.y) + 1; + h = Math.abs(b.y2) + 1; return t.attr({ - y: b.y + h + y: h }); }; -- cgit v1.2.1 From 34ed74fab90904eb77c8b07779401650684af5b1 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Fri, 16 Dec 2016 19:59:53 -0200 Subject: Avoid use of Hash#dig to keep compatibility with Ruby 2.1 --- app/controllers/concerns/oauth_applications.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/controllers/concerns/oauth_applications.rb b/app/controllers/concerns/oauth_applications.rb index 7210ed3eb32..9849aa93fa6 100644 --- a/app/controllers/concerns/oauth_applications.rb +++ b/app/controllers/concerns/oauth_applications.rb @@ -6,7 +6,7 @@ module OauthApplications end def prepare_scopes - scopes = params.dig(:doorkeeper_application, :scopes) + scopes = params.fetch(:doorkeeper_application, {}).fetch(:scopes, nil) if scopes params[:doorkeeper_application][:scopes] = scopes.join(' ') -- cgit v1.2.1 From 09388b2021034173156ba8958fa290b01e3a447d Mon Sep 17 00:00:00 2001 From: Nur Rony Date: Tue, 18 Oct 2016 18:22:18 +0600 Subject: Adds sort dropdown for group members --- app/assets/stylesheets/pages/members.scss | 54 +++++++++++++++++----- app/controllers/groups/group_members_controller.rb | 10 ++-- .../projects/project_members_controller.rb | 5 +- app/helpers/members_helper.rb | 30 ++++++++---- app/helpers/sorting_helper.rb | 41 +++++++++++++++- app/views/groups/group_members/index.html.haml | 1 + app/views/projects/project_members/index.html.haml | 1 + app/views/shared/members/_sort_dropdown.html.haml | 11 +++++ 8 files changed, 127 insertions(+), 26 deletions(-) create mode 100644 app/views/shared/members/_sort_dropdown.html.haml (limited to 'app') diff --git a/app/assets/stylesheets/pages/members.scss b/app/assets/stylesheets/pages/members.scss index 5f3bbb40ba0..b7521133ce5 100644 --- a/app/assets/stylesheets/pages/members.scss +++ b/app/assets/stylesheets/pages/members.scss @@ -78,6 +78,20 @@ float: right; } + .dropdown { + width: 100%; + margin-top: 5px; + + .dropdown-menu-toggle { + width: 100%; + } + + @media (min-width: $screen-sm-min) { + top: 2.4px; + width: 155px; + } + } + .form-control { width: 100%; padding-right: 35px; @@ -85,18 +99,34 @@ @media (min-width: $screen-sm-min) { width: 350px; } + + &.input-short { + @media (min-width: $screen-md-min) { + width: 170px; + } + + @media (min-width: $screen-lg-min) { + width: 210px; + } + } + } + + .member-search-btn { + position: absolute; + right: 4px; + top: 0; + height: 35px; + padding-left: 10px; + padding-right: 10px; + color: $gray-darkest; + background: transparent; + border: 0; + outline: 0; + + @media (min-width: $screen-sm-min) { + right: 160px; + top: 8px; + } } -} -.member-search-btn { - position: absolute; - right: 0; - top: 0; - height: 35px; - padding-left: 10px; - padding-right: 10px; - color: $gray-darkest; - background: transparent; - border: 0; - outline: 0; } diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb index 940a3ad20ba..af8abb96d4a 100644 --- a/app/controllers/groups/group_members_controller.rb +++ b/app/controllers/groups/group_members_controller.rb @@ -10,11 +10,15 @@ class Groups::GroupMembersController < Groups::ApplicationController @members = @members.non_invite unless can?(current_user, :admin_group, @group) if params[:search].present? - users = @group.users.search(params[:search]).to_a - @members = @members.where(user_id: users) + @members = @members.joins(:user).merge(User.search(params[:search])) end - @members = @members.order('access_level DESC').page(params[:page]).per(50) + if params[:sort].present? + @members = @members.joins(:user).merge(User.sort(@sort = params[:sort])) + end + + + @members = @members.page(params[:page]).per(50) @requesters = AccessRequestsFinder.new(@group).execute(current_user) @group_member = @group.group_members.new diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index 53308948f62..e4aba4b700e 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -1,10 +1,12 @@ class Projects::ProjectMembersController < Projects::ApplicationController include MembershipActions + include SortingHelper # Authorize before_action :authorize_admin_project_member!, except: [:index, :leave, :request_access] def index + @sort = params[:sort].presence || sort_value_name @group_links = @project.project_group_links @project_members = @project.project_members @@ -40,7 +42,8 @@ class Projects::ProjectMembersController < Projects::ApplicationController @project_members = Member. where(wheres.join(' OR ')). - order(access_level: :desc).page(params[:page]) + sort(@sort). + page(params[:page]) @requesters = AccessRequestsFinder.new(@project).execute(current_user) diff --git a/app/helpers/members_helper.rb b/app/helpers/members_helper.rb index 877c77050be..f1b8962eb36 100644 --- a/app/helpers/members_helper.rb +++ b/app/helpers/members_helper.rb @@ -11,17 +11,17 @@ module MembersHelper text = 'Are you sure you want to ' action = - if member.request? - if member.user == user - 'withdraw your access request for' + if member.request? + if member.user == user + 'withdraw your access request for' + else + "deny #{member.user.name}'s request to join" + end + elsif member.invite? + "revoke the invitation for #{member.invite_email} to join" else - "deny #{member.user.name}'s request to join" + "remove #{member.user.name} from" end - elsif member.invite? - "revoke the invitation for #{member.invite_email} to join" - else - "remove #{member.user.name} from" - end text << action << " the #{member.source.human_name} #{member.real_source_type.humanize(capitalize: false)}?" end @@ -36,4 +36,16 @@ module MembersHelper "Are you sure you want to leave the " \ "\"#{member_source.human_name}\" #{member_source.class.to_s.humanize(capitalize: false)}?" end + + def filter_group_project_member_path(options = {}) + exist_opts = { + search: params[:search], + sort: params[:sort] + } + + options = exist_opts.merge(options) + path = request.path + path << "?#{options.to_param}" + path + end end diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb index 8b138a8e69f..9c6f9f741ed 100644 --- a/app/helpers/sorting_helper.rb +++ b/app/helpers/sorting_helper.rb @@ -25,7 +25,7 @@ module SortingHelper sort_value_recently_updated => sort_title_recently_updated, sort_value_oldest_updated => sort_title_oldest_updated, sort_value_recently_created => sort_title_recently_created, - sort_value_oldest_created => sort_title_oldest_created, + sort_value_oldest_created => sort_title_oldest_created } if current_controller?('admin/projects') @@ -35,6 +35,17 @@ module SortingHelper options end + def member_sort_options_hash + { + sort_value_last_joined => sort_title_last_joined, + sort_value_oldest_joined => sort_title_oldest_joined, + sort_value_name => sort_title_name_asc, + sort_value_name_desc => sort_title_name_desc, + sort_value_recently_signin => sort_title_recently_signin, + sort_value_oldest_signin => sort_title_oldest_signin + } + end + def sort_title_priority 'Priority' end @@ -95,6 +106,34 @@ module SortingHelper 'Most popular' end + def sort_title_last_joined + 'Last joined' + end + + def sort_title_oldest_joined + 'Oldest joined' + end + + def sort_title_name_asc + 'Name, ascending' + end + + def sort_title_name_desc + 'Name, descending' + end + + def sort_value_last_joined + 'last_joined' + end + + def sort_value_oldest_joined + 'oldest_joined' + end + + def sort_value_name_desc + 'name_desc' + end + def sort_value_priority 'priority' end diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml index ebf9aca7700..bc5d3c797ac 100644 --- a/app/views/groups/group_members/index.html.haml +++ b/app/views/groups/group_members/index.html.haml @@ -21,6 +21,7 @@ = search_field_tag :search, params[:search], { placeholder: 'Find existing members by name', class: 'form-control', spellcheck: false } %button.member-search-btn{ type: "submit", "aria-label" => "Submit search" } = icon("search") + = render 'shared/members/sort_dropdown' .panel.panel-default .panel-heading Users with access to diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml index bdeb704b6da..4f1cec20f85 100644 --- a/app/views/projects/project_members/index.html.haml +++ b/app/views/projects/project_members/index.html.haml @@ -21,6 +21,7 @@ = search_field_tag :search, params[:search], { placeholder: 'Find existing members by name', class: 'form-control', spellcheck: false } %button.member-search-btn{ type: "submit", "aria-label" => "Submit search" } = icon("search") + = render 'shared/members/sort_dropdown' - if @group_links.any? = render 'groups', group_links: @group_links diff --git a/app/views/shared/members/_sort_dropdown.html.haml b/app/views/shared/members/_sort_dropdown.html.haml new file mode 100644 index 00000000000..42c09636ba3 --- /dev/null +++ b/app/views/shared/members/_sort_dropdown.html.haml @@ -0,0 +1,11 @@ +- @sort ||= sort_value_last_joined + +.dropdown.inline + = dropdown_toggle(member_sort_options_hash[@sort], { toggle: 'dropdown' }, { id: 'sort-members-dropdown' }) + %ul.dropdown-menu.dropdown-menu-align-right.dropdown-menu-selectable + %li.dropdown-header + Sort by + - member_sort_options_hash.each do |value, title| + %li + = link_to filter_group_project_member_path(sort: value), class: ("is-active" if @sort == value) do + = title -- cgit v1.2.1 From f54ddbf1ecb91ea96b52e18f87ff5ed10ad45747 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 16 Nov 2016 19:35:33 -0200 Subject: Fix MembersHelper --- app/helpers/members_helper.rb | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'app') diff --git a/app/helpers/members_helper.rb b/app/helpers/members_helper.rb index f1b8962eb36..cf8fdfca1bd 100644 --- a/app/helpers/members_helper.rb +++ b/app/helpers/members_helper.rb @@ -11,17 +11,17 @@ module MembersHelper text = 'Are you sure you want to ' action = - if member.request? - if member.user == user - 'withdraw your access request for' - else - "deny #{member.user.name}'s request to join" - end - elsif member.invite? - "revoke the invitation for #{member.invite_email} to join" + if member.request? + if member.user == user + 'withdraw your access request for' else - "remove #{member.user.name} from" + "deny #{member.user.name}'s request to join" end + elsif member.invite? + "revoke the invitation for #{member.invite_email} to join" + else + "remove #{member.user.name} from" + end text << action << " the #{member.source.human_name} #{member.real_source_type.humanize(capitalize: false)}?" end @@ -39,8 +39,8 @@ module MembersHelper def filter_group_project_member_path(options = {}) exist_opts = { - search: params[:search], - sort: params[:sort] + search: params[:search], + sort: params[:sort] } options = exist_opts.merge(options) -- cgit v1.2.1 From 59d43bea80b56faff54630934694b317cda9f899 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 16 Nov 2016 19:37:51 -0200 Subject: Fix sort functionality for group/project members --- app/controllers/groups/group_members_controller.rb | 14 ++++---------- app/models/member.rb | 20 ++++++++++++++++++++ app/models/user.rb | 6 ++++-- 3 files changed, 28 insertions(+), 12 deletions(-) (limited to 'app') diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb index af8abb96d4a..812aaa4c191 100644 --- a/app/controllers/groups/group_members_controller.rb +++ b/app/controllers/groups/group_members_controller.rb @@ -6,19 +6,13 @@ class Groups::GroupMembersController < Groups::ApplicationController def index @project = @group.projects.find(params[:project_id]) if params[:project_id] + @members = @group.group_members @members = @members.non_invite unless can?(current_user, :admin_group, @group) - - if params[:search].present? - @members = @members.joins(:user).merge(User.search(params[:search])) - end - - if params[:sort].present? - @members = @members.joins(:user).merge(User.sort(@sort = params[:sort])) - end - - + @members = @members.search(params[:search]) if params[:search].present? + @members = @members.sort(@sort = params[:sort]) if params[:sort].present? @members = @members.page(params[:page]).per(50) + @requesters = AccessRequestsFinder.new(@group).execute(current_user) @group_member = @group.group_members.new diff --git a/app/models/member.rb b/app/models/member.rb index 3b65587c66b..b82b16e6f33 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -57,6 +57,11 @@ class Member < ActiveRecord::Base scope :owners, -> { active.where(access_level: OWNER) } scope :owners_and_masters, -> { active.where(access_level: [OWNER, MASTER]) } + scope :order_name_asc, -> { joins(:user).merge(User.order_name_asc) } + scope :order_name_desc, -> { joins(:user).merge(User.order_name_desc) } + scope :order_recent_sign_in, -> { joins(:user).merge(User.order_recent_sign_in) } + scope :order_oldest_sign_in, -> { joins(:user).merge(User.order_oldest_sign_in) } + before_validation :generate_invite_token, on: :create, if: -> (member) { member.invite_email.present? } after_create :send_invite, if: :invite?, unless: :importing? @@ -72,6 +77,21 @@ class Member < ActiveRecord::Base default_value_for :notification_level, NotificationSetting.levels[:global] class << self + def search(query) + joins(:user).merge(User.search(query)) + end + + def sort(method) + case method.to_s + when 'recent_sign_in' then order_recent_sign_in + when 'oldest_sign_in' then order_oldest_sign_in + when 'last_joined' then order_created_desc + when 'oldest_joined' then order_created_asc + else + order_by(method) + end + end + def access_for_user_ids(user_ids) where(user_id: user_ids).has_access.pluck(:user_id, :access_level).to_h end diff --git a/app/models/user.rb b/app/models/user.rb index 1bd28203523..a2812d68384 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -178,6 +178,8 @@ class User < ActiveRecord::Base scope :not_in_project, ->(project) { project.users.present? ? where("id not in (:ids)", ids: project.users.map(&:id) ) : all } scope :without_projects, -> { where('id NOT IN (SELECT DISTINCT(user_id) FROM members WHERE user_id IS NOT NULL AND requested_at IS NULL)') } scope :todo_authors, ->(user_id, state) { where(id: Todo.where(user_id: user_id, state: state).select(:author_id)) } + scope :order_recent_sign_in, -> { reorder(last_sign_in_at: :desc) } + scope :order_oldest_sign_in, -> { reorder(last_sign_in_at: :asc) } def self.with_two_factor joins("LEFT OUTER JOIN u2f_registrations AS u2f ON u2f.user_id = users.id"). @@ -205,8 +207,8 @@ class User < ActiveRecord::Base def sort(method) case method.to_s - when 'recent_sign_in' then reorder(last_sign_in_at: :desc) - when 'oldest_sign_in' then reorder(last_sign_in_at: :asc) + when 'recent_sign_in' then order_recent_sign_in + when 'oldest_sign_in' then order_oldest_sign_in else order_by(method) end -- cgit v1.2.1 From 7783267d6cc41b6a5ced907316aefbc71f2a8e7e Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 16 Nov 2016 19:45:35 -0200 Subject: Add option to sort group/project members by access level --- app/helpers/sorting_helper.rb | 18 ++++++++++++++++++ app/models/member.rb | 2 ++ 2 files changed, 20 insertions(+) (limited to 'app') diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb index 9c6f9f741ed..f03c4627050 100644 --- a/app/helpers/sorting_helper.rb +++ b/app/helpers/sorting_helper.rb @@ -37,6 +37,8 @@ module SortingHelper def member_sort_options_hash { + sort_value_access_level_asc => sort_title_access_level_asc, + sort_value_access_level_desc => sort_title_access_level_desc, sort_value_last_joined => sort_title_last_joined, sort_value_oldest_joined => sort_title_oldest_joined, sort_value_name => sort_title_name_asc, @@ -114,6 +116,14 @@ module SortingHelper 'Oldest joined' end + def sort_title_access_level_asc + 'Access level, ascending' + end + + def sort_title_access_level_desc + 'Access level, descending' + end + def sort_title_name_asc 'Name, ascending' end @@ -130,6 +140,14 @@ module SortingHelper 'oldest_joined' end + def sort_value_access_level_asc + 'access_level_asc' + end + + def sort_value_access_level_desc + 'access_level_desc' + end + def sort_value_name_desc 'name_desc' end diff --git a/app/models/member.rb b/app/models/member.rb index b82b16e6f33..8c36a631ac4 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -83,6 +83,8 @@ class Member < ActiveRecord::Base def sort(method) case method.to_s + when 'access_level_asc' then reorder(access_level: :asc) + when 'access_level_desc' then reorder(access_level: :desc) when 'recent_sign_in' then order_recent_sign_in when 'oldest_sign_in' then order_oldest_sign_in when 'last_joined' then order_created_desc -- cgit v1.2.1 From 3a2905f5072f451b4b1f284c4383b4054a8892af Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 16 Nov 2016 20:37:50 -0200 Subject: Sort group/project members alphabetically by default --- app/controllers/groups/group_members_controller.rb | 4 +++- app/views/shared/members/_sort_dropdown.html.haml | 2 -- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb index 812aaa4c191..4f273a8d4f0 100644 --- a/app/controllers/groups/group_members_controller.rb +++ b/app/controllers/groups/group_members_controller.rb @@ -1,16 +1,18 @@ class Groups::GroupMembersController < Groups::ApplicationController include MembershipActions + include SortingHelper # Authorize before_action :authorize_admin_group_member!, except: [:index, :leave, :request_access] def index + @sort = params[:sort].presence || sort_value_name @project = @group.projects.find(params[:project_id]) if params[:project_id] @members = @group.group_members @members = @members.non_invite unless can?(current_user, :admin_group, @group) @members = @members.search(params[:search]) if params[:search].present? - @members = @members.sort(@sort = params[:sort]) if params[:sort].present? + @members = @members.sort(@sort) @members = @members.page(params[:page]).per(50) @requesters = AccessRequestsFinder.new(@group).execute(current_user) diff --git a/app/views/shared/members/_sort_dropdown.html.haml b/app/views/shared/members/_sort_dropdown.html.haml index 42c09636ba3..a2b47b605b7 100644 --- a/app/views/shared/members/_sort_dropdown.html.haml +++ b/app/views/shared/members/_sort_dropdown.html.haml @@ -1,5 +1,3 @@ -- @sort ||= sort_value_last_joined - .dropdown.inline = dropdown_toggle(member_sort_options_hash[@sort], { toggle: 'dropdown' }, { id: 'sort-members-dropdown' }) %ul.dropdown-menu.dropdown-menu-align-right.dropdown-menu-selectable -- cgit v1.2.1 From c3af880aeea12565bc33a29284a9836e3b800019 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Thu, 17 Nov 2016 15:51:34 -0200 Subject: Remove unnecessary curly braces from sort dropdown partial --- app/views/shared/members/_sort_dropdown.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/shared/members/_sort_dropdown.html.haml b/app/views/shared/members/_sort_dropdown.html.haml index a2b47b605b7..8f28324c5f6 100644 --- a/app/views/shared/members/_sort_dropdown.html.haml +++ b/app/views/shared/members/_sort_dropdown.html.haml @@ -1,5 +1,5 @@ .dropdown.inline - = dropdown_toggle(member_sort_options_hash[@sort], { toggle: 'dropdown' }, { id: 'sort-members-dropdown' }) + = dropdown_toggle(member_sort_options_hash[@sort], { toggle: 'dropdown' }, id: 'sort-members-dropdown') %ul.dropdown-menu.dropdown-menu-align-right.dropdown-menu-selectable %li.dropdown-header Sort by -- cgit v1.2.1 From 06f696dd0a6326ca521d81203901618afa0f9a9a Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Thu, 17 Nov 2016 15:52:15 -0200 Subject: Refactor MembersHelper#filter_group_project_member_path --- app/helpers/members_helper.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'app') diff --git a/app/helpers/members_helper.rb b/app/helpers/members_helper.rb index cf8fdfca1bd..41d471cc92f 100644 --- a/app/helpers/members_helper.rb +++ b/app/helpers/members_helper.rb @@ -38,12 +38,8 @@ module MembersHelper end def filter_group_project_member_path(options = {}) - exist_opts = { - search: params[:search], - sort: params[:sort] - } + options = params.slice(:search, :sort).merge(options) - options = exist_opts.merge(options) path = request.path path << "?#{options.to_param}" path -- cgit v1.2.1 From 621b08d8b5cd5ffe22f5bc7fddecc16821c9bd56 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Fri, 18 Nov 2016 15:50:29 -0200 Subject: Fix sort functionality on project/group members to return invited users --- app/models/member.rb | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/models/member.rb b/app/models/member.rb index 8c36a631ac4..0312aef32fa 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -57,10 +57,10 @@ class Member < ActiveRecord::Base scope :owners, -> { active.where(access_level: OWNER) } scope :owners_and_masters, -> { active.where(access_level: [OWNER, MASTER]) } - scope :order_name_asc, -> { joins(:user).merge(User.order_name_asc) } - scope :order_name_desc, -> { joins(:user).merge(User.order_name_desc) } - scope :order_recent_sign_in, -> { joins(:user).merge(User.order_recent_sign_in) } - scope :order_oldest_sign_in, -> { joins(:user).merge(User.order_oldest_sign_in) } + scope :order_name_asc, -> { left_join_users.reorder(Gitlab::Database.nulls_last_order('users.name', 'ASC')) } + scope :order_name_desc, -> { left_join_users.reorder(Gitlab::Database.nulls_last_order('users.name', 'DESC')) } + scope :order_recent_sign_in, -> { left_join_users.reorder(Gitlab::Database.nulls_last_order('users.last_sign_in_at', 'DESC')) } + scope :order_oldest_sign_in, -> { left_join_users.reorder(Gitlab::Database.nulls_last_order('users.last_sign_in_at', 'ASC')) } before_validation :generate_invite_token, on: :create, if: -> (member) { member.invite_email.present? } @@ -94,6 +94,17 @@ class Member < ActiveRecord::Base end end + def left_join_users + users = User.arel_table + members = Member.arel_table + + member_users = members.join(users, Arel::Nodes::OuterJoin). + on(members[:user_id].eq(users[:id])). + join_sources + + joins(member_users) + end + def access_for_user_ids(user_ids) where(user_id: user_ids).has_access.pluck(:user_id, :access_level).to_h end -- cgit v1.2.1 From b667d834bc77d29b982c3858d6f788b2a4a34c0d Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 21 Nov 2016 16:05:11 -0200 Subject: Remove unused id from shared members sort dropdown --- app/views/shared/members/_sort_dropdown.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/shared/members/_sort_dropdown.html.haml b/app/views/shared/members/_sort_dropdown.html.haml index 8f28324c5f6..3fad8406374 100644 --- a/app/views/shared/members/_sort_dropdown.html.haml +++ b/app/views/shared/members/_sort_dropdown.html.haml @@ -1,5 +1,5 @@ .dropdown.inline - = dropdown_toggle(member_sort_options_hash[@sort], { toggle: 'dropdown' }, id: 'sort-members-dropdown') + = dropdown_toggle(member_sort_options_hash[@sort], { toggle: 'dropdown' }) %ul.dropdown-menu.dropdown-menu-align-right.dropdown-menu-selectable %li.dropdown-header Sort by -- cgit v1.2.1 From 5479fc9107507fd441de0661dd2c4c0826fb40f0 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Thu, 24 Nov 2016 11:17:51 -0200 Subject: Undo changes on members search button stylesheet --- app/assets/stylesheets/pages/members.scss | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/members.scss b/app/assets/stylesheets/pages/members.scss index b7521133ce5..f2417efeebb 100644 --- a/app/assets/stylesheets/pages/members.scss +++ b/app/assets/stylesheets/pages/members.scss @@ -110,23 +110,22 @@ } } } +} - .member-search-btn { - position: absolute; - right: 4px; - top: 0; - height: 35px; - padding-left: 10px; - padding-right: 10px; - color: $gray-darkest; - background: transparent; - border: 0; - outline: 0; +.member-search-btn { + position: absolute; + right: 4px; + top: 0; + height: 35px; + padding-left: 10px; + padding-right: 10px; + color: $gray-darkest; + background: transparent; + border: 0; + outline: 0; - @media (min-width: $screen-sm-min) { - right: 160px; - top: 8px; - } + @media (min-width: $screen-sm-min) { + right: 160px; + top: 8px; } - } -- cgit v1.2.1 From eac34fd9a3347b873fc963856b2f0e2104fe7a9b Mon Sep 17 00:00:00 2001 From: Nur Rony Date: Fri, 2 Dec 2016 16:24:28 +0600 Subject: Fix sort dropdown alignment --- app/assets/stylesheets/pages/members.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/members.scss b/app/assets/stylesheets/pages/members.scss index f2417efeebb..36ee5d17211 100644 --- a/app/assets/stylesheets/pages/members.scss +++ b/app/assets/stylesheets/pages/members.scss @@ -83,11 +83,12 @@ margin-top: 5px; .dropdown-menu-toggle { + vertical-align: middle; width: 100%; } @media (min-width: $screen-sm-min) { - top: 2.4px; + margin-top: 0; width: 155px; } } @@ -126,6 +127,5 @@ @media (min-width: $screen-sm-min) { right: 160px; - top: 8px; } } -- cgit v1.2.1 From ecea127cd1e2ac382a71e03ebc16de44f762b2dd Mon Sep 17 00:00:00 2001 From: Nur Rony Date: Fri, 2 Dec 2016 17:52:10 +0600 Subject: Improve test for sort dropdown on members page --- app/views/shared/members/_sort_dropdown.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/shared/members/_sort_dropdown.html.haml b/app/views/shared/members/_sort_dropdown.html.haml index 3fad8406374..bad0891f9f2 100644 --- a/app/views/shared/members/_sort_dropdown.html.haml +++ b/app/views/shared/members/_sort_dropdown.html.haml @@ -1,4 +1,4 @@ -.dropdown.inline +.dropdown.inline.member-sort-dropdown = dropdown_toggle(member_sort_options_hash[@sort], { toggle: 'dropdown' }) %ul.dropdown-menu.dropdown-menu-align-right.dropdown-menu-selectable %li.dropdown-header -- cgit v1.2.1 From e644b8d683d7b9fa2c411fe65e1c828ba9908b57 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Fri, 9 Dec 2016 17:19:47 -0200 Subject: Fix query in Projects::ProjectMembersController to fetch members --- app/controllers/projects/project_members_controller.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index e4aba4b700e..3aec6f18e27 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -37,8 +37,8 @@ class Projects::ProjectMembersController < Projects::ApplicationController @group_links = @project.project_group_links.where(group_id: @project.invited_groups.search(params[:search]).select(:id)) end - wheres = ["id IN (#{@project_members.select(:id).to_sql})"] - wheres << "id IN (#{group_members.select(:id).to_sql})" if group_members + wheres = ["members.id IN (#{@project_members.select(:id).to_sql})"] + wheres << "members.id IN (#{group_members.select(:id).to_sql})" if group_members @project_members = Member. where(wheres.join(' OR ')). -- cgit v1.2.1 From db43813aa0118852d7529b9ec856d6cca19540ad Mon Sep 17 00:00:00 2001 From: Regis Date: Fri, 16 Dec 2016 15:37:18 -0700 Subject: add CONST and one line a tag in pagination - add request to false in store handler --- app/assets/javascripts/vue_pagination/index.js.es6 | 9 +++------ app/assets/javascripts/vue_pipelines_index/index.js.es6 | 14 ++++++-------- app/assets/javascripts/vue_pipelines_index/store.js.es6 | 7 ++++--- 3 files changed, 13 insertions(+), 17 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pagination/index.js.es6 b/app/assets/javascripts/vue_pagination/index.js.es6 index 3889e6d6d28..6aeb6d3b37b 100644 --- a/app/assets/javascripts/vue_pagination/index.js.es6 +++ b/app/assets/javascripts/vue_pagination/index.js.es6 @@ -5,6 +5,7 @@ ((gl) => { const PAGINATION_UI_BUTTON_LIMIT = 4; + const UI_LIMIT = 6; const SPREAD = '...'; const PREV = 'Prev'; const NEXT = 'Next'; @@ -104,7 +105,7 @@ items.push({ title: PREV, disabled: true }); } - if (page > 6) items.push({ title: SPREAD, separator: true }); + if (page > UI_LIMIT) items.push({ title: SPREAD, separator: true }); const start = Math.max(page - PAGINATION_UI_BUTTON_LIMIT, 1); const end = Math.min(page + PAGINATION_UI_BUTTON_LIMIT, total); @@ -139,11 +140,7 @@ disabled: item.disabled }' > - - {{item.title}} - + {{item.title}}
    diff --git a/app/assets/javascripts/vue_pipelines_index/index.js.es6 b/app/assets/javascripts/vue_pipelines_index/index.js.es6 index 8f3e211aac8..bad24ce41d0 100644 --- a/app/assets/javascripts/vue_pipelines_index/index.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/index.js.es6 @@ -36,14 +36,12 @@ 'vue-pipelines': gl.VuePipelines, }, template: ` -
    - - -
    + + `, }); } diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index 619fd094996..46c27b1c38a 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -34,9 +34,10 @@ updatePipelineNums(this.count); this.pageRequest = false; - }, () => new Flash( - 'Something went wrong on our end.', - )); + }, () => { + this.pageRequest = false; + return new Flash('Something went wrong on our end.'); + }); goFetch(); -- cgit v1.2.1 From b08f92928058b395d2d6666b13ccb113bd78efbf Mon Sep 17 00:00:00 2001 From: Regis Date: Fri, 16 Dec 2016 15:42:05 -0700 Subject: interval event handlers - keep page:fetch listener null --- app/assets/javascripts/vue_pipelines_index/store.js.es6 | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index 46c27b1c38a..3cd31dbffe7 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -60,10 +60,9 @@ }; const removeAll = () => { - removeTimeIntervals(); - window.removeEventListener('beforeunload', () => {}); - window.removeEventListener('focus', () => {}); - window.removeEventListener('blur', () => {}); + window.removeEventListener('beforeunload', removeTimeIntervals); + window.removeEventListener('focus', startIntervalLoops); + window.removeEventListener('blur', removeTimeIntervals); // turbolinks event handler document.removeEventListener('page:fetch', () => {}); -- cgit v1.2.1 From 1e237c9f906460ee13155ee63f91f42bb8f93d3a Mon Sep 17 00:00:00 2001 From: Regis Date: Fri, 16 Dec 2016 15:46:15 -0700 Subject: computed for actions and artifacts --- .../javascripts/vue_pipelines_index/pipeline_actions.js.es6 | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 index 24640ba5fb8..491403c8b59 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 @@ -6,6 +6,14 @@ props: [ 'pipeline', ], + computed: { + actions() { + return this.pipeline.details.manual_actions.length > 0; + }, + artifacts() { + return this.pipeline.details.artifacts.length > 0; + }, + }, methods: { download(name) { return `Download ${name} artifacts`; @@ -17,7 +25,7 @@
    Date: Fri, 16 Dec 2016 15:48:24 -0700 Subject: fix v-ifs in pipeline_url --- app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 index bf24392b82f..87e516d2f14 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 @@ -37,7 +37,7 @@ API stuck -- cgit v1.2.1 From 0b207930e0196d025e893ab2228682c38f364903 Mon Sep 17 00:00:00 2001 From: Regis Date: Fri, 16 Dec 2016 15:50:28 -0700 Subject: refactor pageValues --- .../javascripts/vue_pipelines_index/store.js.es6 | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js.es6 index 3cd31dbffe7..04fde27af58 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js.es6 @@ -2,16 +2,14 @@ /* eslint-disable no-param-reassign, no-underscore-dangle */ ((gl) => { - const pageValues = (headers) => { - const values = {}; - values.perPage = +headers['X-Per-Page']; - values.page = +headers['X-Page']; - values.total = +headers['X-Total']; - values.totalPages = +headers['X-Total-Pages']; - values.nextPage = +headers['X-Next-Page']; - values.previousPage = +headers['X-Prev-Page']; - return values; - }; + const pageValues = headers => ({ + perPage: +headers['X-Per-Page'], + page: +headers['X-Page'], + total: +headers['X-Total'], + totalPages: +headers['X-Total-Pages'], + nextPage: +headers['X-Next-Page'], + previousPage: +headers['X-Prev-Page'], + }); gl.PipelineStore = class { fetchDataLoop(Vue, pageNum, url, apiScope) { -- cgit v1.2.1 From 4c620d6b136d3b294e0935a8d13ba102761393e1 Mon Sep 17 00:00:00 2001 From: Regis Date: Fri, 16 Dec 2016 15:50:56 -0700 Subject: change example function in pagination component --- app/assets/javascripts/vue_pagination/index.js.es6 | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pagination/index.js.es6 b/app/assets/javascripts/vue_pagination/index.js.es6 index 6aeb6d3b37b..7df15f9d4af 100644 --- a/app/assets/javascripts/vue_pagination/index.js.es6 +++ b/app/assets/javascripts/vue_pagination/index.js.es6 @@ -41,16 +41,14 @@ This is an example: - const pageInfo = (headers) => { - const values = {}; - values.perPage = +headers['X-Per-Page']; - values.page = +headers['X-Page']; - values.total = +headers['X-Total']; - values.totalPages = +headers['X-Total-Pages']; - values.nextPage = +headers['X-Next-Page']; - values.previousPage = +headers['X-Prev-Page']; - return values; - }; + const pageInfo = headers => ({ + perPage: +headers['X-Per-Page'], + page: +headers['X-Page'], + total: +headers['X-Total'], + totalPages: +headers['X-Total-Pages'], + nextPage: +headers['X-Next-Page'], + previousPage: +headers['X-Prev-Page'], + }); */ pageInfo: { -- cgit v1.2.1 From 715461a9bc74ad732872577e506ff00703fd108c Mon Sep 17 00:00:00 2001 From: Regis Date: Fri, 16 Dec 2016 15:59:13 -0700 Subject: pipline user for pipeline_url refactor --- app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 index 87e516d2f14..96baef32a9f 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 @@ -8,8 +8,7 @@ ], computed: { user() { - if (this.pipeline.user) return true; - return false; + return !!this.pipeline.user; }, }, template: ` -- cgit v1.2.1 From e8b55c51d87e06825f2ea27e2ce32f810ff2fb20 Mon Sep 17 00:00:00 2001 From: Regis Date: Fri, 16 Dec 2016 16:03:01 -0700 Subject: refactor commitSha - commitUrl - commitTitle in pipelines.js.es6 --- app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index a2b12554494..4a907eec681 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -55,16 +55,13 @@ return ({ name: ref.name, tag: ref['tag?'], ref_url: ref.url }); }, commitTitle(pipeline) { - if (pipeline.commit) return pipeline.commit.title; - return ''; + return pipeline.commit ? pipeline.commit.title : ''; }, commitSha(pipeline) { - if (pipeline.commit) return pipeline.commit.short_id; - return ''; + return pipeline.commit ? pipeline.commit.short_id : ''; }, commitUrl(pipeline) { - if (pipeline.commit) return pipeline.commit.commit_url; - return ''; + return pipeline.commit ? pipeline.commit.commit_url : ''; }, match(string) { return string.replace(/_([a-z])/g, (m, w) => w.toUpperCase()); -- cgit v1.2.1 From e98cdf4b2070c27da76cfa4ba3d5e2022ff08b19 Mon Sep 17 00:00:00 2001 From: Regis Date: Fri, 16 Dec 2016 16:12:52 -0700 Subject: all svgs from index haml --- .../vue_pipelines_index/pipeline_actions.js.es6 | 20 +++----------------- .../javascripts/vue_pipelines_index/pipelines.js.es6 | 4 ++-- .../javascripts/vue_pipelines_index/time_ago.js.es6 | 15 ++------------- app/views/projects/pipelines/index.html.haml | 2 ++ 4 files changed, 9 insertions(+), 32 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 index 491403c8b59..b568d3a75a2 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 @@ -3,9 +3,7 @@ ((gl) => { gl.VuePipelineActions = Vue.extend({ - props: [ - 'pipeline', - ], + props: ['pipeline', 'svgs'], computed: { actions() { return this.pipeline.details.manual_actions.length > 0; @@ -31,13 +29,7 @@ title="Manual build" alt="Manual Build" > - - - - +
    +
    + + +
    +
    { + window.gl = window.gl || {}; + window.gl.environmentsList = window.gl.environmentsList || {}; + + window.gl.environmentsList.TerminalButtonComponent = Vue.component('terminal-button-component', { + props: { + terminalPath: { + type: String, + default: '', + }, + terminalIconSvg: { + type: String, + default: '', + }, + }, + + template: ` + + + + `, + }); +})(); diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss index 59ff17ad2c1..a11f1cd7735 100644 --- a/app/assets/stylesheets/framework/buttons.scss +++ b/app/assets/stylesheets/framework/buttons.scss @@ -230,6 +230,13 @@ } } +.btn-terminal { + svg { + height: 14px; + width: 18px; + } +} + .btn-lg { padding: 12px 20px; } diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index be22e7bdc79..7905d2f2e7c 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -734,3 +734,23 @@ padding: 5px 5px 5px 7px; } } + +.terminal-icon { + margin-left: 3px; +} + +.terminal-container { + .content-block { + border-bottom: none; + } + + #terminal { + margin-top: 10px; + min-height: 450px; + box-sizing: border-box; + + > div { + min-height: 450px; + } + } +} diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb index a1b39c6a78a..87cc36253f1 100644 --- a/app/controllers/projects/environments_controller.rb +++ b/app/controllers/projects/environments_controller.rb @@ -4,7 +4,9 @@ class Projects::EnvironmentsController < Projects::ApplicationController before_action :authorize_create_environment!, only: [:new, :create] before_action :authorize_create_deployment!, only: [:stop] before_action :authorize_update_environment!, only: [:edit, :update] - before_action :environment, only: [:show, :edit, :update, :stop] + before_action :authorize_admin_environment!, only: [:terminal, :terminal_websocket_authorize] + before_action :environment, only: [:show, :edit, :update, :stop, :terminal, :terminal_websocket_authorize] + before_action :verify_api_request!, only: :terminal_websocket_authorize def index @scope = params[:scope] @@ -14,7 +16,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController format.html format.json do render json: EnvironmentSerializer - .new(project: @project) + .new(project: @project, user: current_user) .represent(@environments) end end @@ -65,11 +67,9 @@ class Projects::EnvironmentsController < Projects::ApplicationController # GET .../terminal.ws : implemented in gitlab-workhorse def terminal_websocket_authorize - Gitlab::Workhorse.verify_api_request!(request.headers) - # Just return the first terminal for now. If the list is in the process of # being looked up, this may result in a 404 response, so the frontend - # should retry + # should retry those errors terminal = environment.terminals.try(:first) if terminal set_workhorse_internal_api_content_type @@ -81,6 +81,10 @@ class Projects::EnvironmentsController < Projects::ApplicationController private + def verify_api_request! + Gitlab::Workhorse.verify_api_request!(request.headers) + end + def environment_params params.require(:environment).permit(:name, :external_url) end diff --git a/app/serializers/environment_entity.rb b/app/serializers/environment_entity.rb index e7ef01258ef..5d15eb8d3d3 100644 --- a/app/serializers/environment_entity.rb +++ b/app/serializers/environment_entity.rb @@ -8,7 +8,6 @@ class EnvironmentEntity < Grape::Entity expose :environment_type expose :last_deployment, using: DeploymentEntity expose :stoppable? - expose :has_terminals?, as: :has_terminals expose :environment_path do |environment| namespace_project_environment_path( @@ -25,10 +24,11 @@ class EnvironmentEntity < Grape::Entity end expose :terminal_path, if: ->(environment, _) { environment.has_terminals? } do |environment| - terminal_namespace_project_environment_path( - environment.project.namespace, - environment.project, - environment) + can?(request.user, :admin_environment, environment.project) && + terminal_namespace_project_environment_path( + environment.project.namespace, + environment.project, + environment) end expose :created_at, :updated_at diff --git a/app/serializers/request_aware_entity.rb b/app/serializers/request_aware_entity.rb index ff8c1142abc..e159d750cb7 100644 --- a/app/serializers/request_aware_entity.rb +++ b/app/serializers/request_aware_entity.rb @@ -8,4 +8,8 @@ module RequestAwareEntity def request @options.fetch(:request) end + + def can?(object, action, subject) + Ability.allowed?(object, action, subject) + end end diff --git a/app/views/projects/environments/_terminal_button.html.haml b/app/views/projects/environments/_terminal_button.html.haml new file mode 100644 index 00000000000..97de9c95de7 --- /dev/null +++ b/app/views/projects/environments/_terminal_button.html.haml @@ -0,0 +1,3 @@ +- if environment.has_terminals? && can?(current_user, :admin_environment, @project) + = link_to terminal_namespace_project_environment_path(@project.namespace, @project, environment), class: 'btn terminal-button' do + = icon('terminal') diff --git a/app/views/projects/environments/index.html.haml b/app/views/projects/environments/index.html.haml index 6aae035b3e0..0c6f696f5b9 100644 --- a/app/views/projects/environments/index.html.haml +++ b/app/views/projects/environments/index.html.haml @@ -15,4 +15,5 @@ "help-page-path" => help_page_path("ci/environments"), "css-class" => container_class, "commit-icon-svg" => custom_icon("icon_commit"), + "terminal-icon-svg" => custom_icon("icon_terminal"), "play-icon-svg" => custom_icon("icon_play")}} diff --git a/app/views/projects/environments/show.html.haml b/app/views/projects/environments/show.html.haml index bcac73d3698..6e0d9456900 100644 --- a/app/views/projects/environments/show.html.haml +++ b/app/views/projects/environments/show.html.haml @@ -8,6 +8,7 @@ %h3.page-title= @environment.name.capitalize .col-md-3 .nav-controls + = render 'projects/environments/terminal_button', environment: @environment = render 'projects/environments/external_url', environment: @environment - if can?(current_user, :update_environment, @environment) = link_to 'Edit', edit_namespace_project_environment_path(@project.namespace, @project, @environment), class: 'btn' diff --git a/app/views/projects/environments/terminal.html.haml b/app/views/projects/environments/terminal.html.haml new file mode 100644 index 00000000000..a6726e509e0 --- /dev/null +++ b/app/views/projects/environments/terminal.html.haml @@ -0,0 +1,22 @@ +- @no_container = true +- page_title "Terminal for environment", @environment.name += render "projects/pipelines/head" + +- content_for :page_specific_javascripts do + = stylesheet_link_tag "xterm/xterm" + = page_specific_javascript_tag("terminal/terminal_bundle.js") + +%div{class: container_class} + .top-area + .row + .col-sm-6 + %h3.page-title + Terminal for environment + = @environment.name + + .col-sm-6 + .nav-controls + = render 'projects/deployments/actions', deployment: @environment.last_deployment + +.terminal-container{class: container_class} + #terminal{data:{project_path: "#{terminal_namespace_project_environment_path(@project.namespace, @project, @environment)}.ws"}} diff --git a/app/views/shared/icons/_icon_terminal.svg b/app/views/shared/icons/_icon_terminal.svg new file mode 100644 index 00000000000..c80f44c3edf --- /dev/null +++ b/app/views/shared/icons/_icon_terminal.svg @@ -0,0 +1 @@ + -- cgit v1.2.1 From 34e317d21ce49c122beb73d2eb695311b75d0b89 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Mon, 19 Dec 2016 17:58:46 +0000 Subject: Adds loading to improve UX --- .../mini_pipeline_graph_dropdown.js.es6 | 42 ++++++++++++++++------ app/assets/stylesheets/pages/pipelines.scss | 12 +++++-- .../projects/ci/pipelines/_pipeline.html.haml | 10 ++++-- app/views/projects/pipelines/_stage.html.haml | 10 +++--- 4 files changed, 53 insertions(+), 21 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/mini_pipeline_graph_dropdown.js.es6 b/app/assets/javascripts/mini_pipeline_graph_dropdown.js.es6 index ce24cbdb705..1db1ad6f017 100644 --- a/app/assets/javascripts/mini_pipeline_graph_dropdown.js.es6 +++ b/app/assets/javascripts/mini_pipeline_graph_dropdown.js.es6 @@ -18,31 +18,34 @@ class MiniPipelineGraph { constructor({ container }) { this.container = container; + this.dropdownListSelector = '.js-builds-dropdown-container'; this.getBuildsList = this.getBuildsList.bind(this); this.bindEvents(); } /** - * Adds an removes the event listener. - * TODO: Remove jQuery when we have a way to handle events properly. + * Adds and removes the event listener. */ bindEvents() { - $(this.container).off('click', 'button.js-builds-dropdown-button', this.getBuildsList); - $(this.container).on('click', 'button.js-builds-dropdown-button', this.getBuildsList); + const dropdownButtonSelector = 'button.js-builds-dropdown-button'; + + $(this.container).off('click', dropdownButtonSelector, this.getBuildsList); + $(this.container).on('click', dropdownButtonSelector, this.getBuildsList); } /** - * For the clicked stage, renders the received html in the sibiling - * element with the `js-builds-dropdown-container` clas + * For the clicked stage, renders the given data in the dropdown list. * - * @param {Element} stageContainer + * @param {HTMLElement} stageContainer * @param {Object} data */ renderBuildsList(stageContainer, data) { - const dropdownContainer = stageContainer.parentElement.querySelector('.js-builds-dropdown-container'); + const dropdownContainer = stageContainer.parentElement.querySelector( + `${this.dropdownListSelector} .js-builds-dropdown-list`, + ); - dropdownContainer.innerHTML = data.html; + dropdownContainer.innerHTML = data; } /** @@ -58,10 +61,29 @@ dataType: 'json', type: 'GET', url: endpoint, - success: data => this.renderBuildsList(e.currentTarget, data), + beforeSend: () => { + this.renderBuildsList(e.currentTarget, ''); + this.toggleLoading(e.currentTarget); + }, + success: (data) => { + this.toggleLoading(e.currentTarget); + this.renderBuildsList(e.currentTarget, data.html); + }, error: () => new Flash('An error occurred while fetching the builds.', 'alert'), }); } + + /** + * Toggles the visibility of the loading icon. + * + * @param {HTMLElement} stageContainer + * @return {type} + */ + toggleLoading(stageContainer) { + stageContainer.parentElement.querySelector( + `${this.dropdownListSelector} .js-builds-dropdown-loading`, + ).classList.toggle('hidden'); + } } window.gl = window.gl || {}; diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index b3deac3ab75..ae7b40a9416 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -753,13 +753,19 @@ margin: 0; } + .builds-dropdown-loading { + margin: 10px auto; + width: 18px; + } + .grouped-pipeline-dropdown { right: -172px; top: 23px; - } + min-height: 191px; - .grouped-pipeline-dropdown a { - color: $gl-text-color-light; + a { + color: $gl-text-color-light; + } } .arrow-up { diff --git a/app/views/projects/ci/pipelines/_pipeline.html.haml b/app/views/projects/ci/pipelines/_pipeline.html.haml index d488eeda2fe..6dfc55aa23c 100644 --- a/app/views/projects/ci/pipelines/_pipeline.html.haml +++ b/app/views/projects/ci/pipelines/_pipeline.html.haml @@ -53,13 +53,19 @@ .stage-container.mini-pipeline-graph - if hasMultipleBuilds .dropdown.inline.build-content - %button.has-tooltip.builds-dropdown.js-builds-dropdown-button{ type: 'button', data: { toggle: 'dropdown', title: tooltip, "stage-endpoint" => stage_namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline, stage: stage.name)}} + %button.has-tooltip.builds-dropdown.js-builds-dropdown-button{ type: 'button', data: { toggle: 'dropdown', title: tooltip, placement: 'top', "stage-endpoint" => stage_namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline, stage: stage.name)}} %span{ class: klass } %span.mini-pipeline-graph-icon-container %span{ class: icon_status_klass }= custom_icon(icon_status) = icon('caret-down', class: 'dropdown-caret') - %div.js-builds-dropdown-container + .js-builds-dropdown-container + .dropdown-menu.grouped-pipeline-dropdown + .arrow-up + .js-builds-dropdown-list + + .js-builds-dropdown-loading.builds-dropdown-loading.hidden + %span.fa.fa-spinner.fa-spin - else - if detailed_status.has_details? = link_to detailed_status.details_path, class: klass, title: tooltip do diff --git a/app/views/projects/pipelines/_stage.html.haml b/app/views/projects/pipelines/_stage.html.haml index 83fd518726d..20456e792e7 100644 --- a/app/views/projects/pipelines/_stage.html.haml +++ b/app/views/projects/pipelines/_stage.html.haml @@ -1,6 +1,4 @@ -.dropdown-menu.grouped-pipeline-dropdown - .arrow-up - %ul - - @stage.statuses.each do |status| - %li.dropdown-build - = render 'ci/status/graph_badge', subject: status +%ul + - @stage.statuses.each do |status| + %li.dropdown-build + = render 'ci/status/graph_badge', subject: status -- cgit v1.2.1 From 921f411a41d92ff6b3fdea2560adbd861d97be57 Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Mon, 19 Dec 2016 23:50:42 +0100 Subject: Last fixes --- app/models/project_services/mattermost_slash_commands_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/models/project_services/mattermost_slash_commands_service.rb b/app/models/project_services/mattermost_slash_commands_service.rb index 5000f96e350..92e2ae637fb 100644 --- a/app/models/project_services/mattermost_slash_commands_service.rb +++ b/app/models/project_services/mattermost_slash_commands_service.rb @@ -37,7 +37,7 @@ class MattermostSlashCommandsService < ChatService end end - def list_teams + def list_teams(current_user) begin response = Mattermost::Session.new(current_user).with_session do |session| Mattermost::Team.all(session) -- cgit v1.2.1 From 34295036e2a9ecf18ca5440a5dd6dbb0c7f05643 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 19 Dec 2016 23:53:19 +0100 Subject: Improve sources - Add proper error handling, - Use flash[:alert] and flash[:notice], - Use `resource` instead of `resources`, --- app/controllers/projects/mattermost_controller.rb | 39 -------------------- app/controllers/projects/mattermosts_controller.rb | 41 ++++++++++++++++++++++ app/helpers/projects_helper.rb | 9 +++-- .../mattermost_slash_commands_service.rb | 35 ++++++------------ app/views/projects/mattermost/_no_teams.html.haml | 12 ------- .../projects/mattermost/_team_selection.html.haml | 41 ---------------------- app/views/projects/mattermost/new.html.haml | 8 ----- app/views/projects/mattermosts/_no_teams.html.haml | 12 +++++++ .../projects/mattermosts/_team_selection.html.haml | 41 ++++++++++++++++++++++ app/views/projects/mattermosts/new.html.haml | 8 +++++ .../_installation_info.html.haml | 27 +++++++------- 11 files changed, 128 insertions(+), 145 deletions(-) delete mode 100644 app/controllers/projects/mattermost_controller.rb create mode 100644 app/controllers/projects/mattermosts_controller.rb delete mode 100644 app/views/projects/mattermost/_no_teams.html.haml delete mode 100644 app/views/projects/mattermost/_team_selection.html.haml delete mode 100644 app/views/projects/mattermost/new.html.haml create mode 100644 app/views/projects/mattermosts/_no_teams.html.haml create mode 100644 app/views/projects/mattermosts/_team_selection.html.haml create mode 100644 app/views/projects/mattermosts/new.html.haml (limited to 'app') diff --git a/app/controllers/projects/mattermost_controller.rb b/app/controllers/projects/mattermost_controller.rb deleted file mode 100644 index a0eaec262ee..00000000000 --- a/app/controllers/projects/mattermost_controller.rb +++ /dev/null @@ -1,39 +0,0 @@ -class Projects::MattermostController < Projects::ApplicationController - layout 'project_settings' - before_action :authorize_admin_project! - before_action :service - before_action :teams, only: [:new] - - def new - end - - def create - message = @service.configure(current_user, configure_params) - notice = message.is_a?(String) ? message : 'This service is now configured' - - redirect_to( - new_namespace_project_mattermost_path(@project.namespace, @project), - notice: notice - ) - rescue NoSessionError - redirect_to( - new_namespace_project_mattermost_path(@project.namespace, @project), - alert: 'No session could be set up, is Mattermost configured with Single Sign on?' - ) - end - - private - - def configure_params - params.permit(:trigger, :team_id). - merge(url: service_trigger_url(@service), icon_url: asset_url('gitlab_logo.png')) - end - - def service - @service ||= @project.find_or_initialize_service('mattermost_slash_commands') - end - - def teams - @teams = @service.list_teams(current_user) - end -end diff --git a/app/controllers/projects/mattermosts_controller.rb b/app/controllers/projects/mattermosts_controller.rb new file mode 100644 index 00000000000..c6b39add7ad --- /dev/null +++ b/app/controllers/projects/mattermosts_controller.rb @@ -0,0 +1,41 @@ +class Projects::MattermostsController < Projects::ApplicationController + include TriggersHelper + include ActionView::Helpers::AssetUrlHelper + + layout 'project_settings' + + before_action :authorize_admin_project! + before_action :service + before_action :teams, only: [:new] + + def new + end + + def create + @service.configure!(current_user, configure_params) + + flash[:notice] = 'This service is now configured' + redirect_to edit_namespace_project_service_path(@project.namespace, @project, service) + rescue => e + flash[:alert] = e.message + redirect_to new_namespace_project_mattermost_path(@project.namespace, @project) + end + + private + + def configure_params + params.require(:mattermost).permit(:trigger, :team_id).merge( + url: service_trigger_url(@service), + icon_url: asset_url('gitlab_logo.png')) + end + + def teams + @teams ||= @service.list_teams(current_user) + rescue => e + flash[:alert] = e.message + end + + def service + @service ||= @project.find_or_initialize_service('mattermost_slash_commands') + end +end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 963e72ce96e..b7731ab4be2 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -149,12 +149,11 @@ module ProjectsHelper end def mattermost_teams_options(teams) - teams_options = teams.map do |team| - return nil unless team['display_name'] && team['id'] - [team['display_name'], team['id']] + teams_options = teams.map do |id, options| + return nil unless id && options['display_name'] + [options['display_name'], id] end.compact - teams_options.unshift(['Select team...', '0']) unless teams_options.one? - teams_options + teams_options.unshift(['Select team...', '0']) end private diff --git a/app/models/project_services/mattermost_slash_commands_service.rb b/app/models/project_services/mattermost_slash_commands_service.rb index 92e2ae637fb..51de80f38de 100644 --- a/app/models/project_services/mattermost_slash_commands_service.rb +++ b/app/models/project_services/mattermost_slash_commands_service.rb @@ -25,28 +25,17 @@ class MattermostSlashCommandsService < ChatService ] end - def configure(current_user, params) - result = Mattermost::Session.new(current_user).with_session do |session| - Mattermost::Command.create(session, params[:team_id], command) + def configure!(current_user, params) + token = Mattermost::Session.new(current_user).with_session do |session| + Mattermost::Command.create(session, command(params)) end - if result.has_key?('message') - result['message'] - else - update!(token: result['token'], active: true) - end + update!(active: true, token: token) end - def list_teams(current_user) - begin - response = Mattermost::Session.new(current_user).with_session do |session| - Mattermost::Team.all(session) - end - - # We ignore the error message as we can't display it - response.has_key?('message') ? [] : response - rescue Mattermost::NoSessionError - [] + def list_teams(user) + Mattermost::Session.new(user).with_session do |session| + Mattermost::Team.all(session) end end @@ -64,21 +53,17 @@ class MattermostSlashCommandsService < ChatService private - def command(trigger:, url:, icon_url:) + def command(params) pretty_project_name = project.name_with_namespace - { + params.merge( auto_complete: true, auto_complete_desc: "Perform common operations on: #{pretty_project_name}", auto_complete_hint: '[help]', description: "Perform common operations on: #{pretty_project_name}", display_name: "GitLab / #{pretty_project_name}", method: 'P', - user_name: 'GitLab', - trigger: trigger, - url: url, - icon_url: icon_url - } + user_name: 'GitLab') end def find_chat_user(params) diff --git a/app/views/projects/mattermost/_no_teams.html.haml b/app/views/projects/mattermost/_no_teams.html.haml deleted file mode 100644 index 605c7f61dee..00000000000 --- a/app/views/projects/mattermost/_no_teams.html.haml +++ /dev/null @@ -1,12 +0,0 @@ -%p - You aren’t a member of any team on the Mattermost instance at - %strong= Gitlab.config.mattermost.host -%p - To install this service, - = link_to "#{Gitlab.config.mattermost.host}/select_team", target: '__blank' do - join a team - = icon('external-link') - and try again. -%hr -.clearfix - = link_to 'Go back', edit_namespace_project_service_path(@project.namespace, @project, @service), class: 'btn btn-lg pull-right' diff --git a/app/views/projects/mattermost/_team_selection.html.haml b/app/views/projects/mattermost/_team_selection.html.haml deleted file mode 100644 index e0ab63dbc5d..00000000000 --- a/app/views/projects/mattermost/_team_selection.html.haml +++ /dev/null @@ -1,41 +0,0 @@ -%p - This service will be installed on the Mattermost instance at - %strong= Gitlab.config.mattermost.host -%hr -= form_for(:create, method: :post, url: configure_namespace_project_mattermost_index_path(@project.namespace, @project)) do |f| - %h4 Team - %p Select or create the team where the slash commands will be used in - - options = mattermost_teams_options(@teams) - = f.select(:team_id, options, {}, { class: 'form-control', selected: "#{options.first[1] if options.count.one?}", disabled: options.count.one? }) - .help-block - - if options.count.one? - This is the only team where you are an administrator. - - else - The list shows teams where you are administrator - To create a team, ask your Mattermost system administrator. - To create a team, - = link_to "#{Gitlab.config.mattermost.host}/create_team" do - use Mattermost's interface - = icon('external-link') - %hr - %h4 Command trigger word - %p Choose the word that will trigger commands - = f.text_field(:trigger, value: @project.path, class: 'form-control') - .help-block - %p Trigger word must be unique, and cannot begin with a slash or contain any spaces. Use the word that works best for your team. - %p Fill in the word that works best for your team. - %p - Suggestions: - %code= 'gitlab' - %code= @project.path # Path contains no spaces, but dashes - %code= @project.path_with_namespace - %p - Reserved: - = link_to 'https://docs.mattermost.com/help/messaging/executing-commands.html#built-in-commands', target: '__blank' do - see list of built-in slash commands - = icon('external-link') - %hr - .clearfix - .pull-right - = link_to 'Cancel', edit_namespace_project_service_path(@project.namespace, @project, @service), class: 'btn btn-lg' - = f.submit 'Install', class: 'btn btn-save btn-lg' diff --git a/app/views/projects/mattermost/new.html.haml b/app/views/projects/mattermost/new.html.haml deleted file mode 100644 index 96b1d2aee61..00000000000 --- a/app/views/projects/mattermost/new.html.haml +++ /dev/null @@ -1,8 +0,0 @@ -.service-installation - .inline.pull-right - = custom_icon('mattermost_logo', size: 48) - %h3 Install Mattermost Command - - if @teams.empty? - = render 'no_teams' - - else - = render 'team_selection' diff --git a/app/views/projects/mattermosts/_no_teams.html.haml b/app/views/projects/mattermosts/_no_teams.html.haml new file mode 100644 index 00000000000..605c7f61dee --- /dev/null +++ b/app/views/projects/mattermosts/_no_teams.html.haml @@ -0,0 +1,12 @@ +%p + You aren’t a member of any team on the Mattermost instance at + %strong= Gitlab.config.mattermost.host +%p + To install this service, + = link_to "#{Gitlab.config.mattermost.host}/select_team", target: '__blank' do + join a team + = icon('external-link') + and try again. +%hr +.clearfix + = link_to 'Go back', edit_namespace_project_service_path(@project.namespace, @project, @service), class: 'btn btn-lg pull-right' diff --git a/app/views/projects/mattermosts/_team_selection.html.haml b/app/views/projects/mattermosts/_team_selection.html.haml new file mode 100644 index 00000000000..376592e66c9 --- /dev/null +++ b/app/views/projects/mattermosts/_team_selection.html.haml @@ -0,0 +1,41 @@ +%p + This service will be installed on the Mattermost instance at + %strong= link_to Gitlab.config.mattermost.host, Gitlab.config.mattermost.host +%hr += form_for(:mattermost, method: :post, url: namespace_project_mattermost_path(@project.namespace, @project)) do |f| + %h4 Team + %p Select or create the team where the slash commands will be used in + - selected_id = @teams.keys.first if @teams.one? + = f.select(:team_id, mattermost_teams_options(@teams), {}, { class: 'form-control', selected: "#{selected_id}", disabled: @teams.one? }) + .help-block + - if @teams.one? + This is the only team where you are an administrator. + - else + The list shows teams where you are administrator + To create a team, ask your Mattermost system administrator. + To create a team, + = link_to "#{Gitlab.config.mattermost.host}/create_team" do + use Mattermost's interface + = icon('external-link') + %hr + %h4 Command trigger word + %p Choose the word that will trigger commands + = f.text_field(:trigger, value: @project.path, class: 'form-control') + .help-block + %p Trigger word must be unique, and cannot begin with a slash or contain any spaces. Use the word that works best for your team. + %p Fill in the word that works best for your team. + %p + Suggestions: + %code= 'gitlab' + %code= @project.path # Path contains no spaces, but dashes + %code= @project.path_with_namespace + %p + Reserved: + = link_to 'https://docs.mattermost.com/help/messaging/executing-commands.html#built-in-commands', target: '__blank' do + see list of built-in slash commands + = icon('external-link') + %hr + .clearfix + .pull-right + = link_to 'Cancel', edit_namespace_project_service_path(@project.namespace, @project, @service), class: 'btn btn-lg' + = f.submit 'Install', class: 'btn btn-save btn-lg' diff --git a/app/views/projects/mattermosts/new.html.haml b/app/views/projects/mattermosts/new.html.haml new file mode 100644 index 00000000000..96b1d2aee61 --- /dev/null +++ b/app/views/projects/mattermosts/new.html.haml @@ -0,0 +1,8 @@ +.service-installation + .inline.pull-right + = custom_icon('mattermost_logo', size: 48) + %h3 Install Mattermost Command + - if @teams.empty? + = render 'no_teams' + - else + = render 'team_selection' diff --git a/app/views/projects/services/mattermost_slash_commands/_installation_info.html.haml b/app/views/projects/services/mattermost_slash_commands/_installation_info.html.haml index abc68e955e7..e6fcb09e054 100644 --- a/app/views/projects/services/mattermost_slash_commands/_installation_info.html.haml +++ b/app/views/projects/services/mattermost_slash_commands/_installation_info.html.haml @@ -5,18 +5,15 @@ .row %strong.col-sm-3.text-right Mattermost = link_to pretty_url(Gitlab.config.mattermost.host), Gitlab.config.mattermost.host, class: 'col-sm-9', target: '__blank' - .row - %strong.col-sm-3.text-right Installation - .col-sm-9 - - if @service.activated? - To edit or uninstall this service, press - %strong Edit in Mattermost - - else - To install this service, press - %strong Add to Mattermost - and follow the instructions - .row - .col-sm-9.col-sm-offset-3 - = link_to new_namespace_project_mattermost_path(@project.namespace, @project), class: 'btn btn-lg' do - = custom_icon('mattermost_logo', size: 15) - = @service.activated? ? 'Edit in Mattermost' : 'Add to Mattermost' + - unless @service.activated? + .row + %strong.col-sm-3.text-right Installation + .col-sm-9 + To install this service, press + %strong Add to Mattermost + and follow the instructions + .row + .col-sm-9.col-sm-offset-3 + = link_to new_namespace_project_mattermost_path(@project.namespace, @project), class: 'btn btn-lg' do + = custom_icon('mattermost_logo', size: 15) + = 'Add to Mattermost' -- cgit v1.2.1 From 841960f847f04da9c427bcdb19037e2112a90890 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Tue, 20 Dec 2016 00:22:10 +0100 Subject: Fix flow --- app/controllers/projects/mattermosts_controller.rb | 1 + .../project_services/mattermost_slash_commands_service.rb | 11 ++++------- 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'app') diff --git a/app/controllers/projects/mattermosts_controller.rb b/app/controllers/projects/mattermosts_controller.rb index c6b39add7ad..0f939838306 100644 --- a/app/controllers/projects/mattermosts_controller.rb +++ b/app/controllers/projects/mattermosts_controller.rb @@ -32,6 +32,7 @@ class Projects::MattermostsController < Projects::ApplicationController def teams @teams ||= @service.list_teams(current_user) rescue => e + @teams = [] flash[:alert] = e.message end diff --git a/app/models/project_services/mattermost_slash_commands_service.rb b/app/models/project_services/mattermost_slash_commands_service.rb index 51de80f38de..accf59bea18 100644 --- a/app/models/project_services/mattermost_slash_commands_service.rb +++ b/app/models/project_services/mattermost_slash_commands_service.rb @@ -25,18 +25,15 @@ class MattermostSlashCommandsService < ChatService ] end - def configure!(current_user, params) - token = Mattermost::Session.new(current_user).with_session do |session| - Mattermost::Command.create(session, command(params)) - end + def configure!(user, params) + token = Mattermost::Command.new(user). + create(command(params)) update!(active: true, token: token) end def list_teams(user) - Mattermost::Session.new(user).with_session do |session| - Mattermost::Team.all(session) - end + Mattermost::Team.new(user).all end def trigger(params) -- cgit v1.2.1 From f7b7e918fef6567d26e7fe17894e5df14c58f37c Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Tue, 20 Dec 2016 00:29:38 +0100 Subject: Remove rest of the form parameters as we can't really support them --- .../services/mattermost_slash_commands/_help.html.haml | 7 +++++-- .../mattermost_slash_commands/_installation_info.html.haml | 12 ------------ 2 files changed, 5 insertions(+), 14 deletions(-) (limited to 'app') diff --git a/app/views/projects/services/mattermost_slash_commands/_help.html.haml b/app/views/projects/services/mattermost_slash_commands/_help.html.haml index 7ed291e09db..63b797cd391 100644 --- a/app/views/projects/services/mattermost_slash_commands/_help.html.haml +++ b/app/views/projects/services/mattermost_slash_commands/_help.html.haml @@ -7,6 +7,9 @@ See list of available commands in Mattermost after setting up this service, by entering %code /<command_trigger_word> help - = render 'projects/services/mattermost_slash_commands/detailed_help', subject: @service unless enabled -= render 'projects/services/mattermost_slash_commands/installation_info' if enabled + - unless enabled + = render 'projects/services/mattermost_slash_commands/detailed_help', subject: @service + +- if enabled + = render 'projects/services/mattermost_slash_commands/installation_info', subject: @service diff --git a/app/views/projects/services/mattermost_slash_commands/_installation_info.html.haml b/app/views/projects/services/mattermost_slash_commands/_installation_info.html.haml index e6fcb09e054..c929eee3bb9 100644 --- a/app/views/projects/services/mattermost_slash_commands/_installation_info.html.haml +++ b/app/views/projects/services/mattermost_slash_commands/_installation_info.html.haml @@ -1,17 +1,5 @@ .services-installation-info - .row - %strong.col-sm-3.text-right Status - .col-sm-9= @service.activated? ? 'Installed' : 'Not installed' - .row - %strong.col-sm-3.text-right Mattermost - = link_to pretty_url(Gitlab.config.mattermost.host), Gitlab.config.mattermost.host, class: 'col-sm-9', target: '__blank' - unless @service.activated? - .row - %strong.col-sm-3.text-right Installation - .col-sm-9 - To install this service, press - %strong Add to Mattermost - and follow the instructions .row .col-sm-9.col-sm-offset-3 = link_to new_namespace_project_mattermost_path(@project.namespace, @project), class: 'btn btn-lg' do -- cgit v1.2.1 From 9edef45ae169e5882dab4950a8143acf7623a06d Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Mon, 19 Dec 2016 23:44:34 +0000 Subject: Resolve conflict Fix tooltips in dropdown --- app/assets/stylesheets/pages/pipelines.scss | 75 ++--------------------------- app/views/ci/status/_graph_badge.html.haml | 12 ++--- 2 files changed, 10 insertions(+), 77 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index bb320da619f..832d8443dc8 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -463,15 +463,11 @@ white-space: normal; color: $gl-text-color-light; -<<<<<<< HEAD - .dropdown-menu-toggle { background-color: transparent; border: none; padding: 0; color: $gl-text-color-light; - flex-grow: 1; - &:focus { outline: none; @@ -486,10 +482,6 @@ } } - &:hover { - background-color: $stage-hover-bg; - border: 1px solid $stage-hover-border; -======= > .build-content { display: inline-block; padding: 8px 10px 9px; @@ -497,8 +489,7 @@ border: 1px solid $border-color; border-radius: 30px; background-color: $white-light; ->>>>>>> master - + &:hover { background-color: $stage-hover-bg; border: 1px solid $stage-hover-border; @@ -603,22 +594,7 @@ } } } - - // Position in the pipeline graph - .grouped-pipeline-dropdown { -<<<<<<< HEAD - right: -206px; - top: -11px; - } } -======= - padding: 0; - width: 191px; - left: auto; - right: -195px; - top: -4px; - box-shadow: 0 1px 5px $black-transparent; ->>>>>>> master .dropdown-counter-badge { float: right; @@ -632,8 +608,8 @@ padding: 0; width: 191px; left: auto; - right: -206px; - top: -11px; + right: -195px; + top: -4px; box-shadow: 0 1px 5px $black-transparent; a { @@ -644,53 +620,10 @@ } } -<<<<<<< HEAD ul { max-height: 245px; overflow: auto; margin: 5px 0; -======= - .dropdown-build { - color: $gl-text-color-light; - - .build-content { - width: 100%; - } - - .ci-action-icon-container { - font-size: 11px; - position: absolute; - right: 4px; - - i { - width: 25px; - height: 25px; - font-size: 11px; - margin-top: 0; - - &::before { - top: 1px; - left: 1px; - } - } - } - - &:hover { - background-color: $stage-hover-bg; - border-radius: 3px; - color: $gl-text-color; - } - - .stage { - max-width: 100px; - width: 100px; - } - - .ci-status-icon svg { - height: 18px; - width: 18px; - } ->>>>>>> master li { padding-top: 2px; @@ -747,7 +680,7 @@ .dropdown-build { color: $gl-text-color-light; - a.ci-action-icon-container { + .ci-action-icon-container { padding: 0; font-size: 11px; float: right; diff --git a/app/views/ci/status/_graph_badge.html.haml b/app/views/ci/status/_graph_badge.html.haml index 52b4d77d074..dd2f649de9a 100644 --- a/app/views/ci/status/_graph_badge.html.haml +++ b/app/views/ci/status/_graph_badge.html.haml @@ -3,18 +3,18 @@ - subject = local_assigns.fetch(:subject) - status = subject.detailed_status(current_user) - klass = "ci-status-icon ci-status-icon-#{status.group}" +- tooltip = "#{subject.name} - #{status.label}" - if status.has_details? - = link_to status.details_path, class: 'build-content' do + = link_to status.details_path, class: 'build-content has-tooltip', data: { toggle: 'tooltip', title: tooltip } do %span{ class: klass }= custom_icon(status.icon) - .ci-status-text{ 'data-toggle' => 'tooltip', 'data-title' => "#{subject.name} - #{status.label}" }= subject.name + .ci-status-text= subject.name - else - .build-content + .build-content.has-tooltip{ data: { toggle: 'tooltip', title: tooltip } } %span{ class: klass }= custom_icon(status.icon) - .ci-status-text{ 'data-toggle' => 'tooltip', 'data-title' => "#{subject.name} - #{status.label}" }= subject.name + .ci-status-text= subject.name - if status.has_action? - = link_to status.action_path, method: status.action_method, - title: status.action_title, class: 'ci-action-icon-container' do + = link_to status.action_path, class: 'ci-action-icon-container has-tooltip', method: status.action_method, data: { toggle: 'tooltip', title: status.action_title } do %i.ci-action-icon-wrapper = icon(status.action_icon, class: status.action_class) -- cgit v1.2.1 From ac86c495a3fc54be6984c4df2b363e9b4e414b4d Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Mon, 19 Dec 2016 23:45:24 +0000 Subject: Pipeline graph node was one pixel off --- app/assets/stylesheets/pages/pipelines.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 832d8443dc8..3639db026cf 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -489,7 +489,7 @@ border: 1px solid $border-color; border-radius: 30px; background-color: $white-light; - + &:hover { background-color: $stage-hover-bg; border: 1px solid $stage-hover-border; @@ -547,7 +547,7 @@ content: ''; position: absolute; top: 48%; - right: -49px; + right: -48px; border-top: 2px solid $border-color; width: 48px; height: 1px; -- cgit v1.2.1 From 4e93cb9c2f89387c02bc59e8fdf0d5a93c516f7a Mon Sep 17 00:00:00 2001 From: Hiroyuki Sato Date: Thu, 15 Dec 2016 13:29:51 +0900 Subject: Cache last commit sha for path --- app/models/repository.rb | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/models/repository.rb b/app/models/repository.rb index 1ccabdb7c1f..bedb3be88c5 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -654,11 +654,22 @@ class Repository end def last_commit_for_path(sha, path) - args = %W(#{Gitlab.config.git.bin_path} rev-list --max-count=1 #{sha} -- #{path}) - sha = Gitlab::Popen.popen(args, path_to_repo).first.strip + sha = cache_last_commit_sha_for_path(sha, path) commit(sha) end + def last_commit_sha_for_path(sha, path) + args = %W(#{Gitlab.config.git.bin_path} rev-list --max-count=1 #{sha} -- #{path}) + Gitlab::Popen.popen(args, path_to_repo).first.strip + end + + def cache_last_commit_sha_for_path(sha, path) + key = path.blank? ? "last_commit_sha_for_path:#{sha}" : "last_commit_id_for_path:#{sha}:#{Digest::SHA1.hexdigest(path)}" + cache.fetch(key) do + last_commit_sha_for_path(sha, path) + end + end + def next_branch(name, opts = {}) branch_ids = self.branch_names.map do |n| next 1 if n == name -- cgit v1.2.1 From 1f1927571990ab44c7a45fbc436438756189d783 Mon Sep 17 00:00:00 2001 From: Hiroyuki Sato Date: Thu, 15 Dec 2016 14:40:15 +0900 Subject: Rename sha to id --- app/models/repository.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/models/repository.rb b/app/models/repository.rb index bedb3be88c5..58eab25b283 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -654,19 +654,19 @@ class Repository end def last_commit_for_path(sha, path) - sha = cache_last_commit_sha_for_path(sha, path) + sha = cache_last_commit_id_for_path(sha, path) commit(sha) end - def last_commit_sha_for_path(sha, path) + def last_commit_id_for_path(sha, path) args = %W(#{Gitlab.config.git.bin_path} rev-list --max-count=1 #{sha} -- #{path}) Gitlab::Popen.popen(args, path_to_repo).first.strip end - def cache_last_commit_sha_for_path(sha, path) - key = path.blank? ? "last_commit_sha_for_path:#{sha}" : "last_commit_id_for_path:#{sha}:#{Digest::SHA1.hexdigest(path)}" + def cache_last_commit_id_for_path(sha, path) + key = path.blank? ? "last_commit_id_for_path:#{sha}" : "last_commit_id_for_path:#{sha}:#{Digest::SHA1.hexdigest(path)}" cache.fetch(key) do - last_commit_sha_for_path(sha, path) + last_commit_id_for_path(sha, path) end end -- cgit v1.2.1 From 2b0b53cddd7d57ca5dd93437fdffefd7a07af91e Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Tue, 20 Dec 2016 11:00:56 +0100 Subject: Add tests for stage API endpoint --- app/controllers/projects/pipelines_controller.rb | 4 +--- app/models/ci/pipeline.rb | 5 +++++ app/models/ci/stage.rb | 4 ++++ 3 files changed, 10 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb index 0147072b0f1..cc347922c6a 100644 --- a/app/controllers/projects/pipelines_controller.rb +++ b/app/controllers/projects/pipelines_controller.rb @@ -42,9 +42,7 @@ class Projects::PipelinesController < Projects::ApplicationController end def stage - @stage = pipeline.stages.find do |stage| - stage.name == params[:stage] - end + @stage = pipeline.stage(params[:stage]) return not_found unless @stage respond_to do |format| diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 48354cdbefb..f2f6453b3b9 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -116,6 +116,11 @@ module Ci where.not(duration: nil).sum(:duration) end + def stage(name) + stage = Ci::Stage.new(self, name: name) + stage unless stage.statuses_count.zero? + end + def stages_count statuses.select(:stage).distinct.count end diff --git a/app/models/ci/stage.rb b/app/models/ci/stage.rb index 7ef59445d77..d035eda6df5 100644 --- a/app/models/ci/stage.rb +++ b/app/models/ci/stage.rb @@ -18,6 +18,10 @@ module Ci name end + def statuses_count + @statuses_count ||= statuses.count + end + def status @status ||= statuses.latest.status end -- cgit v1.2.1 From 51353a6bc7257612412c8712230c0d47667da021 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Tue, 20 Dec 2016 11:27:24 +0100 Subject: Always show dropdown --- .../projects/ci/pipelines/_pipeline.html.haml | 31 +++++++++------------- 1 file changed, 12 insertions(+), 19 deletions(-) (limited to 'app') diff --git a/app/views/projects/ci/pipelines/_pipeline.html.haml b/app/views/projects/ci/pipelines/_pipeline.html.haml index 6dfc55aa23c..ce8b9f9e8af 100644 --- a/app/views/projects/ci/pipelines/_pipeline.html.haml +++ b/app/views/projects/ci/pipelines/_pipeline.html.haml @@ -45,32 +45,25 @@ - if stage.status - detailed_status = stage.detailed_status(current_user) - klass = "has-tooltip ci-status-icon ci-status-icon-#{detailed_status.group}" - - hasMultipleBuilds = stage.statuses.count > 1 - icon_status = "#{detailed_status.icon}_borderless" - icon_status_klass = "ci-status-icon ci-status-icon-#{detailed_status.group}" - tooltip = "#{stage.name}: #{detailed_status.label || 'not found'}" .stage-container.mini-pipeline-graph - - if hasMultipleBuilds - .dropdown.inline.build-content - %button.has-tooltip.builds-dropdown.js-builds-dropdown-button{ type: 'button', data: { toggle: 'dropdown', title: tooltip, placement: 'top', "stage-endpoint" => stage_namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline, stage: stage.name)}} - %span{ class: klass } - %span.mini-pipeline-graph-icon-container - %span{ class: icon_status_klass }= custom_icon(icon_status) - = icon('caret-down', class: 'dropdown-caret') - - .js-builds-dropdown-container - .dropdown-menu.grouped-pipeline-dropdown - .arrow-up - .js-builds-dropdown-list - - .js-builds-dropdown-loading.builds-dropdown-loading.hidden - %span.fa.fa-spinner.fa-spin - - else - - if detailed_status.has_details? - = link_to detailed_status.details_path, class: klass, title: tooltip do + .dropdown.inline.build-content + %button.has-tooltip.builds-dropdown.js-builds-dropdown-button{ type: 'button', data: { toggle: 'dropdown', title: tooltip, placement: 'top', "stage-endpoint" => stage_namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline, stage: stage.name)}} + %span{ class: klass } %span.mini-pipeline-graph-icon-container %span{ class: icon_status_klass }= custom_icon(icon_status) + = icon('caret-down', class: 'dropdown-caret') + + .js-builds-dropdown-container + .dropdown-menu.grouped-pipeline-dropdown + .arrow-up + .js-builds-dropdown-list + + .js-builds-dropdown-loading.builds-dropdown-loading.hidden + %span.fa.fa-spinner.fa-spin %td - if pipeline.duration -- cgit v1.2.1 From 0cf23fde7c666b64e6c18a92d29e632f51b00059 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Tue, 20 Dec 2016 12:02:37 +0100 Subject: Work on tests for mattermost --- app/helpers/projects_helper.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index b7731ab4be2..bd2dcb08b3e 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -150,10 +150,10 @@ module ProjectsHelper def mattermost_teams_options(teams) teams_options = teams.map do |id, options| - return nil unless id && options['display_name'] - [options['display_name'], id] - end.compact - teams_options.unshift(['Select team...', '0']) + [options['display_name'] || options['name'], id] + end + + teams_options.compact.unshift(['Select team...', '0']) end private -- cgit v1.2.1 From 11040589c803410837d67fb481221e9d6ef1d969 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Tue, 20 Dec 2016 10:08:15 +0000 Subject: Adds tests for the MiniPipelineGraph class --- app/assets/javascripts/mini_pipeline_graph_dropdown.js.es6 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/mini_pipeline_graph_dropdown.js.es6 b/app/assets/javascripts/mini_pipeline_graph_dropdown.js.es6 index 1db1ad6f017..73d48074e41 100644 --- a/app/assets/javascripts/mini_pipeline_graph_dropdown.js.es6 +++ b/app/assets/javascripts/mini_pipeline_graph_dropdown.js.es6 @@ -16,8 +16,8 @@ */ (() => { class MiniPipelineGraph { - constructor({ container }) { - this.container = container; + constructor(opts = {}) { + this.container = opts.container || ''; this.dropdownListSelector = '.js-builds-dropdown-container'; this.getBuildsList = this.getBuildsList.bind(this); @@ -57,6 +57,8 @@ getBuildsList(e) { const endpoint = e.currentTarget.dataset.stageEndpoint; + console.log('ENDPOINT', endpoint); + return $.ajax({ dataType: 'json', type: 'GET', -- cgit v1.2.1 From dd5965a15ad3fcb0f411b25e2079ef20f311e446 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Tue, 20 Dec 2016 11:14:46 +0000 Subject: Remove console.log --- app/assets/javascripts/mini_pipeline_graph_dropdown.js.es6 | 2 -- 1 file changed, 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/mini_pipeline_graph_dropdown.js.es6 b/app/assets/javascripts/mini_pipeline_graph_dropdown.js.es6 index 73d48074e41..31b65a22723 100644 --- a/app/assets/javascripts/mini_pipeline_graph_dropdown.js.es6 +++ b/app/assets/javascripts/mini_pipeline_graph_dropdown.js.es6 @@ -57,8 +57,6 @@ getBuildsList(e) { const endpoint = e.currentTarget.dataset.stageEndpoint; - console.log('ENDPOINT', endpoint); - return $.ajax({ dataType: 'json', type: 'GET', -- cgit v1.2.1 From 27c936adf9728cd21114aa3f2f9b44deb0296eb4 Mon Sep 17 00:00:00 2001 From: James Edwards-Jones Date: Fri, 16 Dec 2016 15:52:27 +0000 Subject: Milestoneish SQL performance partially improved and memoized Memoize Milestoneish#issues_visible_to_user and counts to reduce lookups Milstoneish SQL optimised with project, but still slow on GlobalMilestone --- app/models/concerns/milestoneish.rb | 28 +++++++++++++++++++++++++--- app/models/global_milestone.rb | 10 +++++++--- app/models/milestone.rb | 4 ++++ 3 files changed, 36 insertions(+), 6 deletions(-) (limited to 'app') diff --git a/app/models/concerns/milestoneish.rb b/app/models/concerns/milestoneish.rb index 4359f1d7b06..8f02c226f0b 100644 --- a/app/models/concerns/milestoneish.rb +++ b/app/models/concerns/milestoneish.rb @@ -1,10 +1,15 @@ module Milestoneish def closed_items_count(user) - issues_visible_to_user(user).closed.size + merge_requests.closed_and_merged.size + memoize_per_user(user, :closed_items_count) do + (count_issues_by_state(user)['closed'] || 0) + merge_requests.closed_and_merged.size + end end def total_items_count(user) - issues_visible_to_user(user).size + merge_requests.size + memoize_per_user(user, :total_items_count) do + issues_count = count_issues_by_state(user).values.sum + issues_count + merge_requests.size + end end def complete?(user) @@ -30,7 +35,10 @@ module Milestoneish end def issues_visible_to_user(user) - IssuesFinder.new(user).execute.where(id: issues) + memoize_per_user(user, :issues_visible_to_user) do + params = try(:project_id) ? { project_id: project_id } : {} + IssuesFinder.new(user, params).execute.where(milestone_id: milestoneish_ids) + end end def upcoming? @@ -50,4 +58,18 @@ module Milestoneish def expired? due_date && due_date.past? end + + private + + def count_issues_by_state(user) + memoize_per_user(user, :count_issues_by_state) do + issues_visible_to_user(user).reorder(nil).group(:state).count + end + end + + def memoize_per_user(user, method_name) + @memoized ||= {} + @memoized[method_name] ||= {} + @memoized[method_name][user.try!(:id)] ||= yield + end end diff --git a/app/models/global_milestone.rb b/app/models/global_milestone.rb index b01607dcda9..a54e478f5f8 100644 --- a/app/models/global_milestone.rb +++ b/app/models/global_milestone.rb @@ -24,12 +24,16 @@ class GlobalMilestone @first_milestone = milestones.find {|m| m.description.present? } || milestones.first end + def milestoneish_ids + milestones.select(:id) + end + def safe_title @title.to_slug.normalize.to_s end def projects - @projects ||= Project.for_milestones(milestones.select(:id)) + @projects ||= Project.for_milestones(milestoneish_ids) end def state @@ -49,11 +53,11 @@ class GlobalMilestone end def issues - @issues ||= Issue.of_milestones(milestones.select(:id)).includes(:project, :assignee, :labels) + @issues ||= Issue.of_milestones(milestoneish_ids).includes(:project, :assignee, :labels) end def merge_requests - @merge_requests ||= MergeRequest.of_milestones(milestones.select(:id)).includes(:target_project, :assignee, :labels) + @merge_requests ||= MergeRequest.of_milestones(milestoneish_ids).includes(:target_project, :assignee, :labels) end def participants diff --git a/app/models/milestone.rb b/app/models/milestone.rb index 45ca97adad1..0dcfec89f14 100644 --- a/app/models/milestone.rb +++ b/app/models/milestone.rb @@ -129,6 +129,10 @@ class Milestone < ActiveRecord::Base self.title end + def milestoneish_ids + id + end + def can_be_closed? active? && issues.opened.count.zero? end -- cgit v1.2.1 From a2f57f23616bc1ab7547e5a7c517cdd49b172bd8 Mon Sep 17 00:00:00 2001 From: James Edwards-Jones Date: Mon, 19 Dec 2016 21:26:15 +0000 Subject: Fix N+1 queries on milestone show pages --- app/models/issue.rb | 2 ++ app/views/shared/milestones/_tabs.html.haml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/models/issue.rb b/app/models/issue.rb index 738c96e4db3..6825553512f 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -39,6 +39,8 @@ class Issue < ActiveRecord::Base scope :created_after, -> (datetime) { where("created_at >= ?", datetime) } + scope :include_associations, -> { includes(:assignee, :labels, project: :namespace) } + attr_spammable :title, spam_title: true attr_spammable :description, spam_description: true diff --git a/app/views/shared/milestones/_tabs.html.haml b/app/views/shared/milestones/_tabs.html.haml index 2b6ce2d7e7a..c8f2319d95a 100644 --- a/app/views/shared/milestones/_tabs.html.haml +++ b/app/views/shared/milestones/_tabs.html.haml @@ -21,7 +21,7 @@ .tab-content.milestone-content .tab-pane.active#tab-issues - = render 'shared/milestones/issues_tab', issues: milestone.issues_visible_to_user(current_user), show_project_name: show_project_name, show_full_project_name: show_full_project_name + = render 'shared/milestones/issues_tab', issues: milestone.issues_visible_to_user(current_user).include_associations, show_project_name: show_project_name, show_full_project_name: show_full_project_name .tab-pane#tab-merge-requests = render 'shared/milestones/merge_requests_tab', merge_requests: milestone.merge_requests, show_project_name: show_project_name, show_full_project_name: show_full_project_name .tab-pane#tab-participants -- cgit v1.2.1 From 4b9bd188433d77fbaec8ae445716de8084b6a145 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Tue, 20 Dec 2016 13:22:31 +0000 Subject: Adds tests for the mini pipeline graph --- app/assets/stylesheets/pages/pipelines.scss | 2 +- app/views/projects/ci/pipelines/_pipeline.html.haml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 3639db026cf..fb6ddc34f1f 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -748,7 +748,7 @@ .grouped-pipeline-dropdown { right: -172px; top: 23px; - min-height: 191px; + min-height: 50px; a { color: $gl-text-color-light; diff --git a/app/views/projects/ci/pipelines/_pipeline.html.haml b/app/views/projects/ci/pipelines/_pipeline.html.haml index ce8b9f9e8af..8541b351e2b 100644 --- a/app/views/projects/ci/pipelines/_pipeline.html.haml +++ b/app/views/projects/ci/pipelines/_pipeline.html.haml @@ -83,7 +83,7 @@ .btn-group.inline - if actions.any? .btn-group - %a.dropdown-toggle.btn.btn-default{type: 'button', 'data-toggle' => 'dropdown'} + %a.dropdown-toggle.btn.btn-default.js-pipeline-dropdown-manual-actions{type: 'button', 'data-toggle' => 'dropdown'} = custom_icon('icon_play') = icon('caret-down') %ul.dropdown-menu.dropdown-menu-align-right @@ -94,7 +94,7 @@ %span= build.name.humanize - if artifacts.present? .btn-group - %a.dropdown-toggle.btn.btn-default.build-artifacts{type: 'button', 'data-toggle' => 'dropdown'} + %a.dropdown-toggle.btn.btn-default.build-artifacts.js-pipeline-dropdown-download{type: 'button', 'data-toggle' => 'dropdown'} = icon("download") = icon('caret-down') %ul.dropdown-menu.dropdown-menu-align-right -- cgit v1.2.1 From 1a59766d0c7ed78a7167040af512842979d2414e Mon Sep 17 00:00:00 2001 From: Hiroyuki Sato Date: Tue, 20 Dec 2016 22:43:59 +0900 Subject: Merge two methods. --- app/models/repository.rb | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'app') diff --git a/app/models/repository.rb b/app/models/repository.rb index 58eab25b283..3266e9c75f0 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -654,19 +654,16 @@ class Repository end def last_commit_for_path(sha, path) - sha = cache_last_commit_id_for_path(sha, path) + sha = last_commit_id_for_path(sha, path) commit(sha) end def last_commit_id_for_path(sha, path) - args = %W(#{Gitlab.config.git.bin_path} rev-list --max-count=1 #{sha} -- #{path}) - Gitlab::Popen.popen(args, path_to_repo).first.strip - end - - def cache_last_commit_id_for_path(sha, path) key = path.blank? ? "last_commit_id_for_path:#{sha}" : "last_commit_id_for_path:#{sha}:#{Digest::SHA1.hexdigest(path)}" + cache.fetch(key) do - last_commit_id_for_path(sha, path) + args = %W(#{Gitlab.config.git.bin_path} rev-list --max-count=1 #{sha} -- #{path}) + Gitlab::Popen.popen(args, path_to_repo).first.strip end end -- cgit v1.2.1 From 3ef1e76659d0d583a2fd72d86309c2ba6816a316 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Tue, 20 Dec 2016 13:25:58 +0000 Subject: Fix broken test Changes after review --- .../javascripts/mini_pipeline_graph_dropdown.js.es6 | 21 +++++++++++++-------- app/views/projects/ci/pipelines/_pipeline.html.haml | 10 ++++------ 2 files changed, 17 insertions(+), 14 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/mini_pipeline_graph_dropdown.js.es6 b/app/assets/javascripts/mini_pipeline_graph_dropdown.js.es6 index 31b65a22723..90b3366f14b 100644 --- a/app/assets/javascripts/mini_pipeline_graph_dropdown.js.es6 +++ b/app/assets/javascripts/mini_pipeline_graph_dropdown.js.es6 @@ -1,3 +1,4 @@ +/* eslint-disable no-new */ /* global Flash */ /** @@ -30,8 +31,8 @@ bindEvents() { const dropdownButtonSelector = 'button.js-builds-dropdown-button'; - $(this.container).off('click', dropdownButtonSelector, this.getBuildsList); - $(this.container).on('click', dropdownButtonSelector, this.getBuildsList); + $(this.container).off('click', dropdownButtonSelector, this.getBuildsList) + .on('click', dropdownButtonSelector, this.getBuildsList); } /** @@ -55,21 +56,25 @@ * @return {Promise} */ getBuildsList(e) { - const endpoint = e.currentTarget.dataset.stageEndpoint; + const button = e.currentTarget; + const endpoint = button.dataset.stageEndpoint; return $.ajax({ dataType: 'json', type: 'GET', url: endpoint, beforeSend: () => { - this.renderBuildsList(e.currentTarget, ''); - this.toggleLoading(e.currentTarget); + this.renderBuildsList(button, ''); + this.toggleLoading(button); }, success: (data) => { - this.toggleLoading(e.currentTarget); - this.renderBuildsList(e.currentTarget, data.html); + this.toggleLoading(button); + this.renderBuildsList(button, data.html); + }, + error: () => { + this.toggleLoading(button); + new Flash('An error occurred while fetching the builds.', 'alert'); }, - error: () => new Flash('An error occurred while fetching the builds.', 'alert'), }); } diff --git a/app/views/projects/ci/pipelines/_pipeline.html.haml b/app/views/projects/ci/pipelines/_pipeline.html.haml index 8541b351e2b..2f8f153f9a9 100644 --- a/app/views/projects/ci/pipelines/_pipeline.html.haml +++ b/app/views/projects/ci/pipelines/_pipeline.html.haml @@ -44,17 +44,15 @@ - pipeline.stages.each do |stage| - if stage.status - detailed_status = stage.detailed_status(current_user) - - klass = "has-tooltip ci-status-icon ci-status-icon-#{detailed_status.group}" - icon_status = "#{detailed_status.icon}_borderless" - - icon_status_klass = "ci-status-icon ci-status-icon-#{detailed_status.group}" - - tooltip = "#{stage.name}: #{detailed_status.label || 'not found'}" + - status_klass = "ci-status-icon ci-status-icon-#{detailed_status.group}" .stage-container.mini-pipeline-graph .dropdown.inline.build-content - %button.has-tooltip.builds-dropdown.js-builds-dropdown-button{ type: 'button', data: { toggle: 'dropdown', title: tooltip, placement: 'top', "stage-endpoint" => stage_namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline, stage: stage.name)}} - %span{ class: klass } + %button.has-tooltip.builds-dropdown.js-builds-dropdown-button{ type: 'button', data: { toggle: 'dropdown', title: "#{stage.name}: #{detailed_status.label}", placement: 'top', "stage-endpoint" => stage_namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline, stage: stage.name)}} + %span.has-tooltip{ class: status_klass } %span.mini-pipeline-graph-icon-container - %span{ class: icon_status_klass }= custom_icon(icon_status) + %span{ class: status_klass }= custom_icon(icon_status) = icon('caret-down', class: 'dropdown-caret') .js-builds-dropdown-container -- cgit v1.2.1 From 8ad5d3171ac1c9079a8a828a1ee9eb16ec21fd38 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Tue, 20 Dec 2016 08:25:39 -0600 Subject: Fix sizing of avatar circles; add border --- app/assets/stylesheets/framework/avatar.scss | 2 +- app/assets/stylesheets/pages/projects.scss | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/avatar.scss b/app/assets/stylesheets/framework/avatar.scss index 000e591e09c..48827578d94 100644 --- a/app/assets/stylesheets/framework/avatar.scss +++ b/app/assets/stylesheets/framework/avatar.scss @@ -64,7 +64,7 @@ &.s32 { font-size: 20px; line-height: 30px; } &.s40 { font-size: 16px; line-height: 38px; } &.s60 { font-size: 32px; line-height: 58px; } - &.s70 { font-size: 34px; line-height: 68px; } + &.s70 { font-size: 34px; line-height: 70px; } &.s90 { font-size: 36px; line-height: 88px; } &.s110 { font-size: 40px; line-height: 108px; font-weight: 300; } &.s140 { font-size: 72px; line-height: 138px; } diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index a443b6a37b3..e16a553bcda 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -93,7 +93,6 @@ .group-avatar { float: none; margin: 0 auto; - border: none; &.identicon { border-radius: 50%; -- cgit v1.2.1 From 8d3ed21f2389a3a68dac56c077bc85591bed8b0b Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Tue, 20 Dec 2016 14:54:23 +0000 Subject: Pedro copy changes --- app/views/projects/mattermosts/_team_selection.html.haml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/views/projects/mattermosts/_team_selection.html.haml b/app/views/projects/mattermosts/_team_selection.html.haml index 376592e66c9..7980f7c9a72 100644 --- a/app/views/projects/mattermosts/_team_selection.html.haml +++ b/app/views/projects/mattermosts/_team_selection.html.haml @@ -4,7 +4,9 @@ %hr = form_for(:mattermost, method: :post, url: namespace_project_mattermost_path(@project.namespace, @project)) do |f| %h4 Team - %p Select or create the team where the slash commands will be used in + %p + = @teams.one? ? 'The team' : 'Select the team' + where the slash commands will be used in - selected_id = @teams.keys.first if @teams.one? = f.select(:team_id, mattermost_teams_options(@teams), {}, { class: 'form-control', selected: "#{selected_id}", disabled: @teams.one? }) .help-block @@ -22,8 +24,9 @@ %p Choose the word that will trigger commands = f.text_field(:trigger, value: @project.path, class: 'form-control') .help-block - %p Trigger word must be unique, and cannot begin with a slash or contain any spaces. Use the word that works best for your team. - %p Fill in the word that works best for your team. + %p + Trigger word must be unique, and can't begin with a slash or contain any spaces. + Use the word that works best for your team. %p Suggestions: %code= 'gitlab' -- cgit v1.2.1 From 33564b113386b3b9c1606dcc2ff7251c178667e5 Mon Sep 17 00:00:00 2001 From: jurre Date: Tue, 20 Dec 2016 15:23:20 +0100 Subject: Make 'unmarked as WIP' message more consistent --- app/services/system_note_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb index 8b48d90f60b..7613ecd5021 100644 --- a/app/services/system_note_service.rb +++ b/app/services/system_note_service.rb @@ -146,7 +146,7 @@ module SystemNoteService end def remove_merge_request_wip(noteable, project, author) - body = 'unmarked as a Work In Progress' + body = 'unmarked as a **Work In Progress**' create_note(noteable: noteable, project: project, author: author, note: body) end -- cgit v1.2.1 From b82fdf6257255b720526ccef716759892e88de09 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 20 Dec 2016 17:52:27 +0100 Subject: Fix error 500 renaming group. Also added specs and changelog. --- app/controllers/groups_controller.rb | 5 ++++- app/models/namespace.rb | 4 ++-- app/services/groups/update_service.rb | 8 +++++++- 3 files changed, 13 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index b83c3a872cf..5c7709ea013 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -82,7 +82,10 @@ class GroupsController < Groups::ApplicationController if Groups::UpdateService.new(@group, current_user, group_params).execute redirect_to edit_group_path(@group), notice: "Group '#{@group.name}' was successfully updated." else - render action: "edit" + error = group.errors.full_messages.first + alert_message = "Group '#{@group.name}' cannot be updated: " + error + + redirect_to edit_group_path(@group.reload), alert: alert_message end end diff --git a/app/models/namespace.rb b/app/models/namespace.rb index fd42f2328d8..b52f08c7081 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -98,7 +98,7 @@ class Namespace < ActiveRecord::Base def move_dir if any_project_has_container_registry_tags? - raise Exception.new('Namespace cannot be moved, because at least one project has tags in container registry') + raise Gitlab::UpdatePathError.new('Namespace cannot be moved, because at least one project has tags in container registry') end # Move the namespace directory in all storages paths used by member projects @@ -111,7 +111,7 @@ class Namespace < ActiveRecord::Base # if we cannot move namespace directory we should rollback # db changes in order to prevent out of sync between db and fs - raise Exception.new('namespace directory cannot be moved') + raise Gitlab::UpdatePathError.new('namespace directory cannot be moved') end end diff --git a/app/services/groups/update_service.rb b/app/services/groups/update_service.rb index fff2273f402..4e878ec556a 100644 --- a/app/services/groups/update_service.rb +++ b/app/services/groups/update_service.rb @@ -14,7 +14,13 @@ module Groups group.assign_attributes(params) - group.save + begin + group.save + rescue Gitlab::UpdatePathError => e + group.errors.add(:base, e.message) + + false + end end end end -- cgit v1.2.1 From 08bc8ad9874d646c0d7eb7dca1951b78f7e5df70 Mon Sep 17 00:00:00 2001 From: Pedro Moreira da Silva Date: Tue, 20 Dec 2016 17:20:41 +0000 Subject: Fix copy in Issue Tracker empty state. --- app/views/shared/empty_states/_issues.html.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/views/shared/empty_states/_issues.html.haml b/app/views/shared/empty_states/_issues.html.haml index e939278bc07..47379cfb4f8 100644 --- a/app/views/shared/empty_states/_issues.html.haml +++ b/app/views/shared/empty_states/_issues.html.haml @@ -10,9 +10,9 @@ .text-content - if has_button %h4 - The Issue Tracker is a good place to add things that need to be improved or solved in a project! + The Issue Tracker is the place to add things that need to be improved or solved in a project %p - An issue can be a bug, a todo or a feature request that needs to be discussed in a project. + Issues can be bugs, tasks or ideas to be discussed. Besides, issues are searchable and filterable. - if project_select_button = render 'shared/new_project_item_select', path: 'issues/new', label: 'New issue' -- cgit v1.2.1 From 61d09a7b15ef9ae2e23359f1afb87b0adbda4dd4 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Tue, 20 Dec 2016 19:11:53 +0100 Subject: WIP --- app/controllers/projects/mattermosts_controller.rb | 21 +++++++++++---------- app/helpers/application_helper.rb | 4 ---- app/helpers/projects_helper.rb | 8 -------- .../mattermost_slash_commands_service.rb | 8 ++++++-- 4 files changed, 17 insertions(+), 24 deletions(-) (limited to 'app') diff --git a/app/controllers/projects/mattermosts_controller.rb b/app/controllers/projects/mattermosts_controller.rb index 0f939838306..d87dff2a80e 100644 --- a/app/controllers/projects/mattermosts_controller.rb +++ b/app/controllers/projects/mattermosts_controller.rb @@ -12,13 +12,17 @@ class Projects::MattermostsController < Projects::ApplicationController end def create - @service.configure!(current_user, configure_params) - - flash[:notice] = 'This service is now configured' - redirect_to edit_namespace_project_service_path(@project.namespace, @project, service) - rescue => e - flash[:alert] = e.message - redirect_to new_namespace_project_mattermost_path(@project.namespace, @project) + result, message = @service.configure(current_user, configure_params) + + if result + flash[:notice] = 'This service is now configured' + redirect_to edit_namespace_project_service_path( + @project.namespace, @project, service) + else + flash[:alert] = message || 'Failed to configure service' + redirect_to new_namespace_project_mattermost_path( + @project.namespace, @project) + end end private @@ -31,9 +35,6 @@ class Projects::MattermostsController < Projects::ApplicationController def teams @teams ||= @service.list_teams(current_user) - rescue => e - @teams = [] - flash[:alert] = e.message end def service diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index adb5eeee3e4..c816b616631 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -294,8 +294,4 @@ module ApplicationHelper def page_class "issue-boards-page" if current_controller?(:boards) end - - def pretty_url(url) - url.gsub(/\A.*?:\/\//, '') - end end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index bd2dcb08b3e..d2177f683a1 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -148,14 +148,6 @@ module ProjectsHelper ).html_safe end - def mattermost_teams_options(teams) - teams_options = teams.map do |id, options| - [options['display_name'] || options['name'], id] - end - - teams_options.compact.unshift(['Select team...', '0']) - end - private def repo_children_classes(field) diff --git a/app/models/project_services/mattermost_slash_commands_service.rb b/app/models/project_services/mattermost_slash_commands_service.rb index 572a02b01d4..4c2b7d64f1f 100644 --- a/app/models/project_services/mattermost_slash_commands_service.rb +++ b/app/models/project_services/mattermost_slash_commands_service.rb @@ -19,15 +19,19 @@ class MattermostSlashCommandsService < ChatSlashCommandsService 'mattermost_slash_commands' end - def configure!(user, params) + def configure(user, params) token = Mattermost::Command.new(user). create(command(params)) - update!(active: true, token: token) + update(active: true, token: token) if token + rescue => Mattermost::Error => e + false, e.message end def list_teams(user) Mattermost::Team.new(user).all + rescue => Mattermost::Error => e + [] end private -- cgit v1.2.1 From 2393d30da232db04faa8da9e1a958cec22ffb6e8 Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Tue, 20 Dec 2016 20:11:02 +0100 Subject: Fix rubocop errors [ci skip] --- app/models/project_services/mattermost_slash_commands_service.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/models/project_services/mattermost_slash_commands_service.rb b/app/models/project_services/mattermost_slash_commands_service.rb index 4c2b7d64f1f..fc1e7d79d08 100644 --- a/app/models/project_services/mattermost_slash_commands_service.rb +++ b/app/models/project_services/mattermost_slash_commands_service.rb @@ -24,13 +24,13 @@ class MattermostSlashCommandsService < ChatSlashCommandsService create(command(params)) update(active: true, token: token) if token - rescue => Mattermost::Error => e - false, e.message + rescue Mattermost::Error => e + [false, e.message] end def list_teams(user) Mattermost::Team.new(user).all - rescue => Mattermost::Error => e + rescue Mattermost::Error [] end -- cgit v1.2.1 From 77deeb12f74b857f9356168ccdf92612fc85fe84 Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Wed, 14 Dec 2016 17:57:14 -0200 Subject: Fix issuable assignee update bug when previous assignee is null --- app/models/concerns/issuable.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index 0ea7b1b1098..ecbfb625c5e 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -92,9 +92,10 @@ module Issuable after_save :record_metrics def update_assignee_cache_counts - # make sure we flush the cache for both the old *and* new assignee - User.find(assignee_id_was).update_cache_counts if assignee_id_was - assignee.update_cache_counts if assignee + # make sure we flush the cache for both the old *and* new assignees(if they exist) + previous_assignee = User.find_by_id(assignee_id_was) + previous_assignee.try(:update_cache_counts) + assignee.try(:update_cache_counts) end # We want to use optimistic lock for cases when only title or description are involved -- cgit v1.2.1 From fed29117de6f30055d88daaa497ec18f85397ad6 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 20 Dec 2016 19:14:33 -0200 Subject: Rename SlackNotificationService back to SlackService --- app/models/project.rb | 2 +- .../project_services/slack_notification_service.rb | 40 ---------------------- app/models/project_services/slack_service.rb | 40 ++++++++++++++++++++++ app/models/service.rb | 2 +- 4 files changed, 42 insertions(+), 42 deletions(-) delete mode 100644 app/models/project_services/slack_notification_service.rb create mode 100644 app/models/project_services/slack_service.rb (limited to 'app') diff --git a/app/models/project.rb b/app/models/project.rb index 72d3da64f2d..5807ea5acdc 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -96,7 +96,7 @@ class Project < ActiveRecord::Base has_one :mattermost_slash_commands_service, dependent: :destroy has_one :mattermost_notification_service, dependent: :destroy has_one :slack_slash_commands_service, dependent: :destroy - has_one :slack_notification_service, dependent: :destroy + has_one :slack_service, dependent: :destroy has_one :buildkite_service, dependent: :destroy has_one :bamboo_service, dependent: :destroy has_one :teamcity_service, dependent: :destroy diff --git a/app/models/project_services/slack_notification_service.rb b/app/models/project_services/slack_notification_service.rb deleted file mode 100644 index 3cbf89efba4..00000000000 --- a/app/models/project_services/slack_notification_service.rb +++ /dev/null @@ -1,40 +0,0 @@ -class SlackNotificationService < ChatNotificationService - def title - 'Slack notifications' - end - - def description - 'Receive event notifications in Slack' - end - - def to_param - 'slack_notification' - end - - def help - 'This service sends notifications about projects events to Slack channels.
    - To setup this service: -
      -
    1. Add an incoming webhook in your Slack team. The default channel can be overridden for each event.
    2. -
    3. Paste the Webhook URL into the field below.
    4. -
    5. Select events below to enable notifications. The channel and username are optional.
    6. -
    ' - end - - def fields - default_fields + build_event_channels - end - - def default_fields - [ - { type: 'text', name: 'webhook', placeholder: 'https://hooks.slack.com/services/...' }, - { type: 'text', name: 'username', placeholder: 'username' }, - { type: 'checkbox', name: 'notify_only_broken_builds' }, - { type: 'checkbox', name: 'notify_only_broken_pipelines' }, - ] - end - - def default_channel - "#general" - end -end diff --git a/app/models/project_services/slack_service.rb b/app/models/project_services/slack_service.rb new file mode 100644 index 00000000000..0583470d3b5 --- /dev/null +++ b/app/models/project_services/slack_service.rb @@ -0,0 +1,40 @@ +class SlackService < ChatNotificationService + def title + 'Slack notifications' + end + + def description + 'Receive event notifications in Slack' + end + + def to_param + 'slack' + end + + def help + 'This service sends notifications about projects events to Slack channels.
    + To setup this service: +
      +
    1. Add an incoming webhook in your Slack team. The default channel can be overridden for each event.
    2. +
    3. Paste the Webhook URL into the field below.
    4. +
    5. Select events below to enable notifications. The channel and username are optional.
    6. +
    ' + end + + def fields + default_fields + build_event_channels + end + + def default_fields + [ + { type: 'text', name: 'webhook', placeholder: 'https://hooks.slack.com/services/...' }, + { type: 'text', name: 'username', placeholder: 'username' }, + { type: 'checkbox', name: 'notify_only_broken_builds' }, + { type: 'checkbox', name: 'notify_only_broken_pipelines' }, + ] + end + + def default_channel + "#general" + end +end diff --git a/app/models/service.rb b/app/models/service.rb index 8abd8e73e43..918ed8206e0 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -222,7 +222,7 @@ class Service < ActiveRecord::Base pushover redmine slack_slash_commands - slack_notification + slack teamcity ] end -- cgit v1.2.1 From d1bf557aacb5dd789ccc88786b47ec174ed1de2b Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 20 Dec 2016 19:29:39 -0200 Subject: Rename MattermostNotificationService back to MattermostService --- app/models/project.rb | 2 +- .../mattermost_notification_service.rb | 41 ---------------------- app/models/project_services/mattermost_service.rb | 41 ++++++++++++++++++++++ app/models/service.rb | 2 +- 4 files changed, 43 insertions(+), 43 deletions(-) delete mode 100644 app/models/project_services/mattermost_notification_service.rb create mode 100644 app/models/project_services/mattermost_service.rb (limited to 'app') diff --git a/app/models/project.rb b/app/models/project.rb index 5807ea5acdc..26fa20f856d 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -94,7 +94,7 @@ class Project < ActiveRecord::Base has_one :asana_service, dependent: :destroy has_one :gemnasium_service, dependent: :destroy has_one :mattermost_slash_commands_service, dependent: :destroy - has_one :mattermost_notification_service, dependent: :destroy + has_one :mattermost_service, dependent: :destroy has_one :slack_slash_commands_service, dependent: :destroy has_one :slack_service, dependent: :destroy has_one :buildkite_service, dependent: :destroy diff --git a/app/models/project_services/mattermost_notification_service.rb b/app/models/project_services/mattermost_notification_service.rb deleted file mode 100644 index de18c4b1f00..00000000000 --- a/app/models/project_services/mattermost_notification_service.rb +++ /dev/null @@ -1,41 +0,0 @@ -class MattermostNotificationService < ChatNotificationService - def title - 'Mattermost notifications' - end - - def description - 'Receive event notifications in Mattermost' - end - - def to_param - 'mattermost_notification' - end - - def help - 'This service sends notifications about projects events to Mattermost channels.
    - To set up this service: -
      -
    1. Enable incoming webhooks in your Mattermost installation.
    2. -
    3. Add an incoming webhook in your Mattermost team. The default channel can be overridden for each event.
    4. -
    5. Paste the webhook URL into the field bellow.
    6. -
    7. Select events below to enable notifications. The channel and username are optional.
    8. -
    ' - end - - def fields - default_fields + build_event_channels - end - - def default_fields - [ - { type: 'text', name: 'webhook', placeholder: 'http://mattermost_host/hooks/...' }, - { type: 'text', name: 'username', placeholder: 'username' }, - { type: 'checkbox', name: 'notify_only_broken_builds' }, - { type: 'checkbox', name: 'notify_only_broken_pipelines' }, - ] - end - - def default_channel - "#town-square" - end -end diff --git a/app/models/project_services/mattermost_service.rb b/app/models/project_services/mattermost_service.rb new file mode 100644 index 00000000000..0650f930402 --- /dev/null +++ b/app/models/project_services/mattermost_service.rb @@ -0,0 +1,41 @@ +class MattermostService < ChatNotificationService + def title + 'Mattermost notifications' + end + + def description + 'Receive event notifications in Mattermost' + end + + def to_param + 'mattermost' + end + + def help + 'This service sends notifications about projects events to Mattermost channels.
    + To set up this service: +
      +
    1. Enable incoming webhooks in your Mattermost installation.
    2. +
    3. Add an incoming webhook in your Mattermost team. The default channel can be overridden for each event.
    4. +
    5. Paste the webhook URL into the field bellow.
    6. +
    7. Select events below to enable notifications. The channel and username are optional.
    8. +
    ' + end + + def fields + default_fields + build_event_channels + end + + def default_fields + [ + { type: 'text', name: 'webhook', placeholder: 'http://mattermost_host/hooks/...' }, + { type: 'text', name: 'username', placeholder: 'username' }, + { type: 'checkbox', name: 'notify_only_broken_builds' }, + { type: 'checkbox', name: 'notify_only_broken_pipelines' }, + ] + end + + def default_channel + "#town-square" + end +end diff --git a/app/models/service.rb b/app/models/service.rb index 918ed8206e0..19ef3ba9c23 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -216,7 +216,7 @@ class Service < ActiveRecord::Base jira kubernetes mattermost_slash_commands - mattermost_notification + mattermost pipelines_email pivotaltracker pushover -- cgit v1.2.1 From 22a0567823e792bd760ced79539a0b2c4bfd8f5e Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Tue, 20 Dec 2016 23:17:32 +0100 Subject: Fix a few error messages --- app/helpers/mattermost_helper.rb | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 app/helpers/mattermost_helper.rb (limited to 'app') diff --git a/app/helpers/mattermost_helper.rb b/app/helpers/mattermost_helper.rb new file mode 100644 index 00000000000..49ac12db832 --- /dev/null +++ b/app/helpers/mattermost_helper.rb @@ -0,0 +1,9 @@ +module MattermostHelper + def mattermost_teams_options(teams) + teams_options = teams.map do |id, options| + [options['display_name'] || options['name'], id] + end + + teams_options.compact.unshift(['Select team...', '0']) + end +end -- cgit v1.2.1 From 85666b7077728aeb2015030d603bc9c9fe6686c6 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Tue, 20 Dec 2016 17:21:02 -0600 Subject: apply margin on alert banners only when there is one or more alerts --- app/assets/stylesheets/framework/layout.scss | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/layout.scss b/app/assets/stylesheets/framework/layout.scss index 59fae61a44f..5365b62e456 100644 --- a/app/assets/stylesheets/framework/layout.scss +++ b/app/assets/stylesheets/framework/layout.scss @@ -33,10 +33,12 @@ body { } .alert-wrapper { - margin-bottom: $gl-padding; - .alert { margin-bottom: 0; + + &:last-child { + margin-bottom: $gl-padding; + } } /* Stripe the background colors so that adjacent alert-warnings are distinct from one another */ -- cgit v1.2.1 From 35adeee5148eddebc003abcd690ad01a50219bde Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Mon, 12 Dec 2016 17:24:49 -0600 Subject: homogenize revert and cherry-pick button styles generated by commits_helper --- app/helpers/commits_helper.rb | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'app') diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index 66a720a9426..4d61833d624 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -131,9 +131,9 @@ module CommitsHelper return unless current_user tooltip = "Revert this #{commit.change_type_title(current_user)} in a new merge request" if has_tooltip + btn_class = "btn btn-warning btn-#{btn_class}" unless btn_class.nil? if can_collaborate_with_project? - btn_class = "btn btn-warning btn-#{btn_class}" unless btn_class.nil? link_to 'Revert', '#modal-revert-commit', 'data-toggle' => 'modal', 'data-container' => 'body', title: (tooltip if has_tooltip), class: "#{btn_class} #{'has-tooltip' if has_tooltip}" elsif can?(current_user, :fork_project, @project) continue_params = { @@ -145,8 +145,6 @@ module CommitsHelper namespace_key: current_user.namespace.id, continue: continue_params) - btn_class = "btn btn-grouped btn-warning" unless btn_class.nil? - link_to 'Revert', fork_path, class: btn_class, method: :post, 'data-toggle' => 'tooltip', 'data-container' => 'body', title: (tooltip if has_tooltip) end end @@ -154,10 +152,10 @@ module CommitsHelper def cherry_pick_commit_link(commit, continue_to_path, btn_class: nil, has_tooltip: true) return unless current_user - tooltip = "Cherry-pick this #{commit.change_type_title(current_user)} in a new merge request" + tooltip = "Cherry-pick this #{commit.change_type_title(current_user)} in a new merge request" if has_tooltip + btn_class = "btn btn-default btn-#{btn_class}" unless btn_class.nil? if can_collaborate_with_project? - btn_class = "btn btn-default btn-#{btn_class}" unless btn_class.nil? link_to 'Cherry-pick', '#modal-cherry-pick-commit', 'data-toggle' => 'modal', 'data-container' => 'body', title: (tooltip if has_tooltip), class: "#{btn_class} #{'has-tooltip' if has_tooltip}" elsif can?(current_user, :fork_project, @project) continue_params = { @@ -169,8 +167,7 @@ module CommitsHelper namespace_key: current_user.namespace.id, continue: continue_params) - btn_class = "btn btn-grouped btn-close" unless btn_class.nil? - link_to 'Cherry-pick', fork_path, class: "#{btn_class}", method: :post, 'data-toggle' => 'tooltip', 'data-container' => 'body', title: (tooltip if has_tooltip) + link_to 'Cherry-pick', fork_path, class: btn_class, method: :post, 'data-toggle' => 'tooltip', 'data-container' => 'body', title: (tooltip if has_tooltip) end end -- cgit v1.2.1 From 26a80149b0381e678ac6b4f13340e81055be3406 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Tue, 13 Dec 2016 09:49:05 -0600 Subject: factor out common code to satisfy rake flay --- app/helpers/commits_helper.rb | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) (limited to 'app') diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index 4d61833d624..e7d78cc422e 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -136,15 +136,7 @@ module CommitsHelper if can_collaborate_with_project? link_to 'Revert', '#modal-revert-commit', 'data-toggle' => 'modal', 'data-container' => 'body', title: (tooltip if has_tooltip), class: "#{btn_class} #{'has-tooltip' if has_tooltip}" elsif can?(current_user, :fork_project, @project) - continue_params = { - to: continue_to_path, - notice: edit_in_new_fork_notice + ' Try to revert this commit again.', - notice_now: edit_in_new_fork_notice_now - } - fork_path = namespace_project_forks_path(@project.namespace, @project, - namespace_key: current_user.namespace.id, - continue: continue_params) - + fork_path = fork_path_url(continue_to_path, message: 'Try to revert this commit again.') link_to 'Revert', fork_path, class: btn_class, method: :post, 'data-toggle' => 'tooltip', 'data-container' => 'body', title: (tooltip if has_tooltip) end end @@ -158,15 +150,7 @@ module CommitsHelper if can_collaborate_with_project? link_to 'Cherry-pick', '#modal-cherry-pick-commit', 'data-toggle' => 'modal', 'data-container' => 'body', title: (tooltip if has_tooltip), class: "#{btn_class} #{'has-tooltip' if has_tooltip}" elsif can?(current_user, :fork_project, @project) - continue_params = { - to: continue_to_path, - notice: edit_in_new_fork_notice + ' Try to cherry-pick this commit again.', - notice_now: edit_in_new_fork_notice_now - } - fork_path = namespace_project_forks_path(@project.namespace, @project, - namespace_key: current_user.namespace.id, - continue: continue_params) - + fork_path = fork_path_url(continue_to_path, message: 'Try to cherry-pick this commit again.') link_to 'Cherry-pick', fork_path, class: btn_class, method: :post, 'data-toggle' => 'tooltip', 'data-container' => 'body', title: (tooltip if has_tooltip) end end @@ -208,6 +192,20 @@ module CommitsHelper end end + def fork_path_url(continue_to_path, message: nil) + notice = edit_in_new_fork_notice + notice << " #{message}" unless message.nil? + + continue_params = { + to: continue_to_path, + notice: notice, + notice_now: edit_in_new_fork_notice_now + } + fork_path = namespace_project_forks_path(@project.namespace, @project, + namespace_key: current_user.namespace.id, + continue: continue_params) + end + def view_file_btn(commit_sha, diff_new_path, project) link_to( namespace_project_blob_path(project.namespace, project, -- cgit v1.2.1 From 4e3b9e03f8ef64a39f587c53e45b2f8d4cf571db Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Tue, 13 Dec 2016 09:57:01 -0600 Subject: remove button class size alteration from revert and cherry pick links --- app/helpers/commits_helper.rb | 4 ++-- app/views/projects/merge_requests/widget/_merged_buttons.haml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index e7d78cc422e..c7d1de0e3b7 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -131,7 +131,7 @@ module CommitsHelper return unless current_user tooltip = "Revert this #{commit.change_type_title(current_user)} in a new merge request" if has_tooltip - btn_class = "btn btn-warning btn-#{btn_class}" unless btn_class.nil? + btn_class = "btn btn-#{btn_class}" unless btn_class.nil? if can_collaborate_with_project? link_to 'Revert', '#modal-revert-commit', 'data-toggle' => 'modal', 'data-container' => 'body', title: (tooltip if has_tooltip), class: "#{btn_class} #{'has-tooltip' if has_tooltip}" @@ -145,7 +145,7 @@ module CommitsHelper return unless current_user tooltip = "Cherry-pick this #{commit.change_type_title(current_user)} in a new merge request" if has_tooltip - btn_class = "btn btn-default btn-#{btn_class}" unless btn_class.nil? + btn_class = "btn btn-#{btn_class}" unless btn_class.nil? if can_collaborate_with_project? link_to 'Cherry-pick', '#modal-cherry-pick-commit', 'data-toggle' => 'modal', 'data-container' => 'body', title: (tooltip if has_tooltip), class: "#{btn_class} #{'has-tooltip' if has_tooltip}" diff --git a/app/views/projects/merge_requests/widget/_merged_buttons.haml b/app/views/projects/merge_requests/widget/_merged_buttons.haml index d836a253507..81abb543d57 100644 --- a/app/views/projects/merge_requests/widget/_merged_buttons.haml +++ b/app/views/projects/merge_requests/widget/_merged_buttons.haml @@ -9,6 +9,6 @@ = icon('trash-o') Remove Source Branch - if mr_can_be_reverted - = revert_commit_link(@merge_request.merge_commit, namespace_project_merge_request_path(@project.namespace, @project, @merge_request), btn_class: 'sm') + = revert_commit_link(@merge_request.merge_commit, namespace_project_merge_request_path(@project.namespace, @project, @merge_request), btn_class: "warning") - if mr_can_be_cherry_picked - = cherry_pick_commit_link(@merge_request.merge_commit, namespace_project_merge_request_path(@project.namespace, @project, @merge_request), btn_class: 'sm') + = cherry_pick_commit_link(@merge_request.merge_commit, namespace_project_merge_request_path(@project.namespace, @project, @merge_request), btn_class: "default") -- cgit v1.2.1 From 759e37f3b192d791e32bda795f4731b29c17d552 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Wed, 14 Dec 2016 00:30:38 -0600 Subject: reduce common code even further to satisfy rake flay --- app/helpers/commits_helper.rb | 48 ++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 23 deletions(-) (limited to 'app') diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index c7d1de0e3b7..f1897119e20 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -128,31 +128,11 @@ module CommitsHelper end def revert_commit_link(commit, continue_to_path, btn_class: nil, has_tooltip: true) - return unless current_user - - tooltip = "Revert this #{commit.change_type_title(current_user)} in a new merge request" if has_tooltip - btn_class = "btn btn-#{btn_class}" unless btn_class.nil? - - if can_collaborate_with_project? - link_to 'Revert', '#modal-revert-commit', 'data-toggle' => 'modal', 'data-container' => 'body', title: (tooltip if has_tooltip), class: "#{btn_class} #{'has-tooltip' if has_tooltip}" - elsif can?(current_user, :fork_project, @project) - fork_path = fork_path_url(continue_to_path, message: 'Try to revert this commit again.') - link_to 'Revert', fork_path, class: btn_class, method: :post, 'data-toggle' => 'tooltip', 'data-container' => 'body', title: (tooltip if has_tooltip) - end + commit_action_link('revert', commit, continue_to_path, btn_class: btn_class, has_tooltip: has_tooltip) end def cherry_pick_commit_link(commit, continue_to_path, btn_class: nil, has_tooltip: true) - return unless current_user - - tooltip = "Cherry-pick this #{commit.change_type_title(current_user)} in a new merge request" if has_tooltip - btn_class = "btn btn-#{btn_class}" unless btn_class.nil? - - if can_collaborate_with_project? - link_to 'Cherry-pick', '#modal-cherry-pick-commit', 'data-toggle' => 'modal', 'data-container' => 'body', title: (tooltip if has_tooltip), class: "#{btn_class} #{'has-tooltip' if has_tooltip}" - elsif can?(current_user, :fork_project, @project) - fork_path = fork_path_url(continue_to_path, message: 'Try to cherry-pick this commit again.') - link_to 'Cherry-pick', fork_path, class: btn_class, method: :post, 'data-toggle' => 'tooltip', 'data-container' => 'body', title: (tooltip if has_tooltip) - end + commit_action_link('cherry-pick', commit, continue_to_path, btn_class: btn_class, has_tooltip: has_tooltip) end protected @@ -192,6 +172,28 @@ module CommitsHelper end end + def commit_action_link(action, commit, continue_to_path, btn_class: nil, has_tooltip: true) + return unless current_user + + tooltip = "#{action.capitalize} this #{commit.change_type_title(current_user)} in a new merge request" if has_tooltip + btn_class = "btn btn-#{btn_class}" unless btn_class.nil? + + if can_collaborate_with_project? + link_to action.capitalize, "#modal-#{action}-commit", 'data-toggle' => 'modal', 'data-container' => 'body', title: (tooltip if has_tooltip), class: "#{btn_class} #{'has-tooltip' if has_tooltip}" + elsif can?(current_user, :fork_project, @project) + continue_params = { + to: continue_to_path, + notice: "#{edit_in_new_fork_notice} Try to #{action} this commit again.", + notice_now: edit_in_new_fork_notice_now + } + fork_path = namespace_project_forks_path(@project.namespace, @project, + namespace_key: current_user.namespace.id, + continue: continue_params) + + link_to action.capitalize, fork_path, class: btn_class, method: :post, 'data-toggle' => 'tooltip', 'data-container' => 'body', title: (tooltip if has_tooltip) + end + end + def fork_path_url(continue_to_path, message: nil) notice = edit_in_new_fork_notice notice << " #{message}" unless message.nil? @@ -201,7 +203,7 @@ module CommitsHelper notice: notice, notice_now: edit_in_new_fork_notice_now } - fork_path = namespace_project_forks_path(@project.namespace, @project, + namespace_project_forks_path(@project.namespace, @project, namespace_key: current_user.namespace.id, continue: continue_params) end -- cgit v1.2.1 From c9165f845974134917927aa174a214a334d264fe Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Mon, 19 Dec 2016 11:12:30 -0600 Subject: remove unused helper method --- app/helpers/commits_helper.rb | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'app') diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index f1897119e20..e9461b9f859 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -194,20 +194,6 @@ module CommitsHelper end end - def fork_path_url(continue_to_path, message: nil) - notice = edit_in_new_fork_notice - notice << " #{message}" unless message.nil? - - continue_params = { - to: continue_to_path, - notice: notice, - notice_now: edit_in_new_fork_notice_now - } - namespace_project_forks_path(@project.namespace, @project, - namespace_key: current_user.namespace.id, - continue: continue_params) - end - def view_file_btn(commit_sha, diff_new_path, project) link_to( namespace_project_blob_path(project.namespace, project, -- cgit v1.2.1 From eda7db3bfbf915ccbfebe045807dafcc25b0a6a1 Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Mon, 19 Dec 2016 13:00:06 -0500 Subject: =?UTF-8?q?Set=20=E2=80=9CRemove=20branch=E2=80=9D=20button=20to?= =?UTF-8?q?=20default=20size?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/projects/merge_requests/widget/_merged_buttons.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/projects/merge_requests/widget/_merged_buttons.haml b/app/views/projects/merge_requests/widget/_merged_buttons.haml index 81abb543d57..9eef011b591 100644 --- a/app/views/projects/merge_requests/widget/_merged_buttons.haml +++ b/app/views/projects/merge_requests/widget/_merged_buttons.haml @@ -5,7 +5,7 @@ - if can_remove_source_branch || mr_can_be_reverted || mr_can_be_cherry_picked .clearfix.merged-buttons - if can_remove_source_branch - = link_to namespace_project_branch_path(@merge_request.source_project.namespace, @merge_request.source_project, @merge_request.source_branch), remote: true, method: :delete, class: "btn btn-default btn-sm remove_source_branch" do + = link_to namespace_project_branch_path(@merge_request.source_project.namespace, @merge_request.source_project, @merge_request.source_branch), remote: true, method: :delete, class: "btn btn-default remove_source_branch" do = icon('trash-o') Remove Source Branch - if mr_can_be_reverted -- cgit v1.2.1 From 071745141d86385aaa4215be1a5d829618962bb0 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Fri, 2 Dec 2016 16:44:49 +0530 Subject: Enable build log autoscroll when page scrolls to bottom --- app/assets/javascripts/build.js | 46 +++++++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 9 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index 824febe3fd3..bb135bec82e 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -10,6 +10,26 @@ Build.state = null; + function isInViewPort(el) { + var elTop = el.offset().top; + var elBottom = elTop + el.outerHeight(); + var vpBottom = $(window).scrollTop() + $(window).height(); + + return vpBottom > elTop; + } + + function toggleAutoScroll(state) { + var $autoScrollBtn = $('#autoscroll-button'); + + if (state) { + $autoScrollBtn.data("state", "enabled"); + $autoScrollBtn.text("Disable autoscroll"); + } else { + $autoScrollBtn.data("state", "disabled"); + $autoScrollBtn.text("Enable autoscroll"); + } + } + function Build(options) { options = options || $('.js-build-options').data(); this.pageUrl = options.pageUrl; @@ -40,18 +60,26 @@ this.initScrollButtonAffix(); } if (this.buildStatus === "running" || this.buildStatus === "pending") { - // Bind autoscroll button to follow build output - $('#autoscroll-button').on('click', function() { - var state; - state = $(this).data("state"); - if ("enabled" === state) { - $(this).data("state", "disabled"); - return $(this).text("Enable autoscroll"); + // Bind document scroll listener to detect if user has scrolled to page bottom + // and enable autoscroll of build log, disable autoscroll otherwise + this.$document.on('scroll', function() { + var $autoScrollBtn = $('#autoscroll-button'); + if (isInViewPort($('.js-build-refresh'))) { // Check if Refresh Animation is in Viewport + if ($autoScrollBtn.data("state") === 'disabled') { + toggleAutoScroll(true); // Enable Autoscroll + } } else { - $(this).data("state", "enabled"); - return $(this).text("Disable autoscroll"); + if ($autoScrollBtn.data("state") === 'enabled') { + toggleAutoScroll(false); // Disable Autoscroll + } } }); + + // Bind autoscroll button to follow build output + $('#autoscroll-button').on('click', function() { + toggleAutoScroll($(this).data("state") === 'disabled'); + }); + Build.interval = setInterval((function(_this) { // Check for new build output if user still watching build page // Only valid for runnig build when output changes during time -- cgit v1.2.1 From f1f45d4a6f8942040d9741604f503538e991f70a Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Mon, 5 Dec 2016 16:02:45 +0530 Subject: Improve isInViewport impl, autoscroll behavior - Improve isInViewport impementation to be robust. - Autoscroll is now a status indicator instead of toggle button - Scrolling build log enables autoscroll itself when scrolled to bottom. --- app/assets/javascripts/build.js | 130 +++++++++++++++++++++++++--------------- 1 file changed, 83 insertions(+), 47 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index bb135bec82e..99cd5c88479 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -10,24 +10,16 @@ Build.state = null; - function isInViewPort(el) { - var elTop = el.offset().top; - var elBottom = elTop + el.outerHeight(); - var vpBottom = $(window).scrollTop() + $(window).height(); - - return vpBottom > elTop; - } - - function toggleAutoScroll(state) { - var $autoScrollBtn = $('#autoscroll-button'); - - if (state) { - $autoScrollBtn.data("state", "enabled"); - $autoScrollBtn.text("Disable autoscroll"); - } else { - $autoScrollBtn.data("state", "disabled"); - $autoScrollBtn.text("Enable autoscroll"); - } + function isInViewport(el) { + // Courtesy http://stackoverflow.com/a/7557433/414749 + var rect = el[0].getBoundingClientRect(); + + return ( + rect.top >= 0 && + rect.left >= 0 && + rect.bottom <= $(window).height() && + rect.right <= $(window).width() + ); } function Build(options) { @@ -52,6 +44,7 @@ this.$document.off('click', '.js-sidebar-build-toggle').on('click', '.js-sidebar-build-toggle', this.sidebarOnClick.bind(this)); this.$document.off('click', '.stage-item').on('click', '.stage-item', this.updateDropdown); + this.$document.on('scroll', this.initScrollMonitor.bind(this)); $(window).off('resize.build').on('resize.build', this.sidebarOnResize.bind(this)); $('a', this.$buildScroll).off('click.stepTrace').on('click.stepTrace', this.stepTrace); this.updateArtifactRemoveDate(); @@ -60,26 +53,6 @@ this.initScrollButtonAffix(); } if (this.buildStatus === "running" || this.buildStatus === "pending") { - // Bind document scroll listener to detect if user has scrolled to page bottom - // and enable autoscroll of build log, disable autoscroll otherwise - this.$document.on('scroll', function() { - var $autoScrollBtn = $('#autoscroll-button'); - if (isInViewPort($('.js-build-refresh'))) { // Check if Refresh Animation is in Viewport - if ($autoScrollBtn.data("state") === 'disabled') { - toggleAutoScroll(true); // Enable Autoscroll - } - } else { - if ($autoScrollBtn.data("state") === 'enabled') { - toggleAutoScroll(false); // Disable Autoscroll - } - } - }); - - // Bind autoscroll button to follow build output - $('#autoscroll-button').on('click', function() { - toggleAutoScroll($(this).data("state") === 'disabled'); - }); - Build.interval = setInterval((function(_this) { // Check for new build output if user still watching build page // Only valid for runnig build when output changes during time @@ -150,22 +123,85 @@ }; Build.prototype.checkAutoscroll = function() { - if ("enabled" === $("#autoscroll-button").data("state")) { + if ("enabled" === $("#autoscroll-status").data("state")) { return $("html,body").scrollTop($("#build-trace").height()); } }; Build.prototype.initScrollButtonAffix = function() { - var $body, $buildTrace; - $body = $('body'); - $buildTrace = $('#build-trace'); - return this.$buildScroll.affix({ - offset: { - bottom: function() { - return $body.outerHeight() - ($buildTrace.outerHeight() + $buildTrace.offset().top); + var $body = $('body'); + var $buildTrace = $('#build-trace'); + var $scrollTopBtn = $('#scroll-top'); + var $scrollBottomBtn = $('#scroll-bottom'); + var $autoScrollContainer = $('.autoscroll-container'); + + $scrollTopBtn.hide().removeClass('sticky'); + $scrollBottomBtn.show().addClass('sticky'); + + if ($autoScrollContainer.length) { + $scrollBottomBtn.hide(); + $autoScrollContainer.show().css({ bottom: 50 }); + } + } + + // Page scroll listener to detect if user has scrolling page + // and handle following cases + // 1) User is at Top of Build Log; + // - Hide Top Arrow button + // - Show Bottom Arrow button + // - Disable Autoscroll and hide indicator (when build is running) + // 2) User is at Bottom of Build Log; + // - Show Top Arrow button + // - Hide Bottom Arrow button + // - Enable Autoscroll and show indicator (when build is running) + // 3) User is somewhere in middle of Build Log; + // - Show Top Arrow button + // - Show Bottom Arrow button + // - Disable Autoscroll and hide indicator (when build is running) + Build.prototype.initScrollMonitor = function() { + var $body = $('body'); + var $buildTrace = $('#build-trace'); + var $autoScrollContainer = $('.autoscroll-container'); + var $autoScrollStatus = $('#autoscroll-status'); + var $upBuildTrace = $('#up-build-trace'); + var $downBuildTrace = $('#down-build-trace'); + var $scrollTopBtn = $('#scroll-top'); + var $scrollBottomBtn = $('#scroll-bottom'); + + if (isInViewport($upBuildTrace)) { // User is at Top of Build Log + $scrollTopBtn.hide().removeClass('sticky'); + $scrollBottomBtn.show().addClass('sticky'); + } + + if (isInViewport($downBuildTrace)) { // User is at Bottom of Build Log + $scrollTopBtn.show().addClass('sticky'); + $scrollBottomBtn.hide().removeClass('sticky'); + + if ($autoScrollContainer.length) { // Show and Reposition Autoscroll Status Message + $autoScrollContainer.show().css({ top: $body.outerHeight() - 75 }); + } + } + + if (!isInViewport($upBuildTrace) && !isInViewport($downBuildTrace)) { // User is somewhere in middle of Build Log + $scrollTopBtn.show().addClass('sticky'); + $scrollBottomBtn.show().addClass('sticky'); + + if ($autoScrollContainer.length) { + $autoScrollContainer.hide(); + } + } + + if (this.buildStatus === "running" || this.buildStatus === "pending") { + if (isInViewport($('.js-build-refresh'))) { // Check if Refresh Animation is in Viewport + if ($autoScrollStatus.data("state") === 'disabled') { + $autoScrollStatus.data("state", 'enabled'); // Enable Autoscroll + } + } else { + if ($autoScrollStatus.data("state") === 'enabled') { + $autoScrollStatus.data("state", 'disabled'); // Disable Autoscroll } } - }); + } }; Build.prototype.shouldHideSidebarForViewport = function() { -- cgit v1.2.1 From 54fe47b876ebb717616140fb7aa0e506823f6dd1 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Mon, 5 Dec 2016 16:03:28 +0530 Subject: Enhance styling of scroll buttons, make build log wide --- app/assets/stylesheets/pages/builds.scss | 68 +++++++++++++++++++++++++++----- 1 file changed, 58 insertions(+), 10 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index 66f7e7f97c8..76bb09c6c7d 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -15,29 +15,69 @@ } .scroll-controls { + height: 100%; + .scroll-step { width: 31px; margin: 0 0 0 auto; } - &.affix-bottom { - position: absolute; + .btn.sticky, + .autoscroll-container { right: 25px; + z-index: 1; } - &.affix { - right: 25px; - bottom: 15px; - z-index: 1; + .btn { + display: block; + margin-bottom: 10px; + color: $white-light; + border-color: $white-light; + background-color: transparent; + + &.sticky { + position: fixed; + } + } + + .autoscroll-container { + position: absolute; + + .status-message { + color: $white-light; + + label { + margin-left: 5px; + font-weight: normal; + } + } + } + + #scroll-top.btn.sticky { + top: 115px; + } + + #scroll-bottom.btn.sticky { + bottom: 5px; } &.sidebar-expanded { - right: #{$gutter_width + ($gl-padding * 2)}; + + .btn.sticky, + .autoscroll-container { + right: #{$gutter_width + ($gl-padding * 2)}; + } } - a { - display: block; - margin-bottom: 10px; + @media (max-width: $screen-sm-max) { + i.fa { + margin-right: 0; + } + + .scroll-step-label, + .status-message label { + display: none; + } } } @@ -248,6 +288,12 @@ } } +.build-sidebar { + .container-fluid.container-limited { + max-width: 100%; + } +} + .build-detail-row { margin-bottom: 5px; @@ -267,6 +313,8 @@ margin-top: -17px; } + + @media (min-width: $screen-md-min) { .sub-nav.build { width: calc(100% + #{$gutter_width}); -- cgit v1.2.1 From c4dfd07b3615b008feeb177f0aa61d0f83b9f696 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Mon, 5 Dec 2016 16:03:54 +0530 Subject: Update look of scroll buttons, autoscroll indicator --- app/views/projects/builds/show.html.haml | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'app') diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml index cdeb81372ee..70b2140c9ab 100644 --- a/app/views/projects/builds/show.html.haml +++ b/app/views/projects/builds/show.html.haml @@ -56,14 +56,18 @@ - else #js-build-scroll.scroll-controls .scroll-step - = link_to '#build-trace', class: 'btn' do - %i.fa.fa-angle-up - = link_to '#down-build-trace', class: 'btn' do - %i.fa.fa-angle-down + = link_to '#up-build-trace', id: 'scroll-top', class: 'btn', title: 'Scroll to top' do + %i.fa.fa-long-arrow-up + %span.scroll-step-label Scroll to top + = link_to '#down-build-trace', id: 'scroll-bottom', class: 'btn', title: 'Scroll to bottom' do + %i.fa.fa-long-arrow-down + %span.scroll-step-label Scroll to bottom - if @build.active? .autoscroll-container - %button.btn.btn-sm#autoscroll-button{:type => "button", :data => {:state => 'disabled'}} - Enable autoscroll + %span.status-message#autoscroll-status{:data => {:state => 'enabled'}} + %i.fa.fa-toggle-on + %label Autoscroll active + #up-build-trace %pre.build-trace#build-trace %code.bash.js-build-output = icon("refresh spin", class: "js-build-refresh") -- cgit v1.2.1 From 394d0fd3c8d07538af9d2065178ee4845b25c7d3 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Mon, 5 Dec 2016 17:23:51 +0530 Subject: ESLint: Clean up nested if blocks --- app/assets/javascripts/build.js | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index 99cd5c88479..e9107f1b553 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -192,15 +192,8 @@ } if (this.buildStatus === "running" || this.buildStatus === "pending") { - if (isInViewport($('.js-build-refresh'))) { // Check if Refresh Animation is in Viewport - if ($autoScrollStatus.data("state") === 'disabled') { - $autoScrollStatus.data("state", 'enabled'); // Enable Autoscroll - } - } else { - if ($autoScrollStatus.data("state") === 'enabled') { - $autoScrollStatus.data("state", 'disabled'); // Disable Autoscroll - } - } + // Check if Refresh Animation is in Viewport and enable Autoscroll, disable otherwise. + $autoScrollStatus.data("state", isInViewport($('.js-build-refresh')) ? 'enabled' : 'disabled'); } }; -- cgit v1.2.1 From 3ea8d17e8756fa2fc7978a6ea815ff37ded2e76b Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Mon, 5 Dec 2016 17:40:01 +0530 Subject: ESLint: remove extra indentation --- app/assets/javascripts/build.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index e9107f1b553..fc4b4aeb73c 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -192,8 +192,8 @@ } if (this.buildStatus === "running" || this.buildStatus === "pending") { - // Check if Refresh Animation is in Viewport and enable Autoscroll, disable otherwise. - $autoScrollStatus.data("state", isInViewport($('.js-build-refresh')) ? 'enabled' : 'disabled'); + // Check if Refresh Animation is in Viewport and enable Autoscroll, disable otherwise. + $autoScrollStatus.data("state", isInViewport($('.js-build-refresh')) ? 'enabled' : 'disabled'); } }; -- cgit v1.2.1 From 3d134c50b3baf83b5f675d5e6bda2171924d2ab8 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Mon, 5 Dec 2016 16:02:45 +0530 Subject: Improve isInViewport impl, autoscroll behavior - Improve isInViewport impementation to be robust. - Autoscroll is now a status indicator instead of toggle button - Scrolling build log enables autoscroll itself when scrolled to bottom. --- app/assets/javascripts/build.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'app') diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index fc4b4aeb73c..874cf0d3023 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -179,6 +179,7 @@ if ($autoScrollContainer.length) { // Show and Reposition Autoscroll Status Message $autoScrollContainer.show().css({ top: $body.outerHeight() - 75 }); +<<<<<<< fbd5f4507b310d6dc1305696851e9860b48fa0ba } } @@ -195,6 +196,31 @@ // Check if Refresh Animation is in Viewport and enable Autoscroll, disable otherwise. $autoScrollStatus.data("state", isInViewport($('.js-build-refresh')) ? 'enabled' : 'disabled'); } +======= + } + } + + if (!isInViewport($upBuildTrace) && !isInViewport($downBuildTrace)) { // User is somewhere in middle of Build Log + $scrollTopBtn.show().addClass('sticky'); + $scrollBottomBtn.show().addClass('sticky'); + + if ($autoScrollContainer.length) { + $autoScrollContainer.hide(); + } + } + + if (this.buildStatus === "running" || this.buildStatus === "pending") { + if (isInViewport($('.js-build-refresh'))) { // Check if Refresh Animation is in Viewport + if ($autoScrollStatus.data("state") === 'disabled') { + $autoScrollStatus.data("state", 'enabled'); // Enable Autoscroll + } + } else { + if ($autoScrollStatus.data("state") === 'enabled') { + $autoScrollStatus.data("state", 'disabled'); // Disable Autoscroll + } + } + } +>>>>>>> Improve isInViewport impl, autoscroll behavior }; Build.prototype.shouldHideSidebarForViewport = function() { -- cgit v1.2.1 From daa08cbe04028e8303321e16dd96c71bb7a6c703 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Mon, 5 Dec 2016 17:23:51 +0530 Subject: ESLint: Clean up nested if blocks --- app/assets/javascripts/build.js | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index 874cf0d3023..e0ae5e5ed6a 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -210,15 +210,8 @@ } if (this.buildStatus === "running" || this.buildStatus === "pending") { - if (isInViewport($('.js-build-refresh'))) { // Check if Refresh Animation is in Viewport - if ($autoScrollStatus.data("state") === 'disabled') { - $autoScrollStatus.data("state", 'enabled'); // Enable Autoscroll - } - } else { - if ($autoScrollStatus.data("state") === 'enabled') { - $autoScrollStatus.data("state", 'disabled'); // Disable Autoscroll - } - } + // Check if Refresh Animation is in Viewport and enable Autoscroll, disable otherwise. + $autoScrollStatus.data("state", isInViewport($('.js-build-refresh')) ? 'enabled' : 'disabled'); } >>>>>>> Improve isInViewport impl, autoscroll behavior }; -- cgit v1.2.1 From cf669e5d5a61465aa605b5d31253fe23a5569b00 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Mon, 5 Dec 2016 17:40:01 +0530 Subject: ESLint: remove extra indentation --- app/assets/javascripts/build.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index e0ae5e5ed6a..e435ff90075 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -210,8 +210,8 @@ } if (this.buildStatus === "running" || this.buildStatus === "pending") { - // Check if Refresh Animation is in Viewport and enable Autoscroll, disable otherwise. - $autoScrollStatus.data("state", isInViewport($('.js-build-refresh')) ? 'enabled' : 'disabled'); + // Check if Refresh Animation is in Viewport and enable Autoscroll, disable otherwise. + $autoScrollStatus.data("state", isInViewport($('.js-build-refresh')) ? 'enabled' : 'disabled'); } >>>>>>> Improve isInViewport impl, autoscroll behavior }; -- cgit v1.2.1 From 7f6ac4f44c8cf071a6ec2f3f1ffc400dcb5d1e40 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Mon, 5 Dec 2016 20:00:34 +0530 Subject: Add title for autoscroll status indicator for a11y --- app/views/projects/builds/show.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml index 70b2140c9ab..3cfbdb2d367 100644 --- a/app/views/projects/builds/show.html.haml +++ b/app/views/projects/builds/show.html.haml @@ -64,7 +64,7 @@ %span.scroll-step-label Scroll to bottom - if @build.active? .autoscroll-container - %span.status-message#autoscroll-status{:data => {:state => 'enabled'}} + %span.status-message#autoscroll-status{:data => {:state => 'enabled'}, :title => 'Autoscroll active'} %i.fa.fa-toggle-on %label Autoscroll active #up-build-trace -- cgit v1.2.1 From 985e84a3b24f18f8dd3e15d2f7225124f0c2d5c6 Mon Sep 17 00:00:00 2001 From: Dimitrie Hoekstra Date: Mon, 5 Dec 2016 15:47:05 +0100 Subject: added hoverstate on buttons, plus added spacing to make them more square when only the arrows are visible --- app/assets/stylesheets/pages/builds.scss | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'app') diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index 76bb09c6c7d..407d4b1e17a 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -38,6 +38,11 @@ &.sticky { position: fixed; } + + &:hover{ + color: $ci-output-bg; + background-color: $white-light; + } } .autoscroll-container { @@ -70,6 +75,10 @@ } @media (max-width: $screen-sm-max) { + .btn { + padding: 6px 13px; + } + i.fa { margin-right: 0; } -- cgit v1.2.1 From 65082b66c3f3baaa088d0ee7bc5b59661960c020 Mon Sep 17 00:00:00 2001 From: Dimitrie Hoekstra Date: Mon, 5 Dec 2016 15:56:39 +0100 Subject: added default half transparent background for sticky scroll buttons --- app/assets/stylesheets/pages/builds.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index 407d4b1e17a..b8ce74697f1 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -33,7 +33,7 @@ margin-bottom: 10px; color: $white-light; border-color: $white-light; - background-color: transparent; + background-color: rgba($ci-output-bg, .5); &.sticky { position: fixed; -- cgit v1.2.1 From 407c90bebf09fb0668940ba93ddec875a4644116 Mon Sep 17 00:00:00 2001 From: Dimitrie Hoekstra Date: Mon, 5 Dec 2016 16:01:06 +0100 Subject: positioned sticky buttons slightly more up and down --- app/assets/stylesheets/pages/builds.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index b8ce74697f1..b256d907649 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -59,11 +59,11 @@ } #scroll-top.btn.sticky { - top: 115px; + top: 110px; } #scroll-bottom.btn.sticky { - bottom: 5px; + bottom: -2px; } &.sidebar-expanded { -- cgit v1.2.1 From 8d7d6bcbd02020ea4b75cb4cec31dfd4b2b6292b Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Tue, 6 Dec 2016 15:04:42 +0530 Subject: Fix rebase conflicts --- app/assets/javascripts/build.js | 19 ------------------- 1 file changed, 19 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index e435ff90075..fc4b4aeb73c 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -179,7 +179,6 @@ if ($autoScrollContainer.length) { // Show and Reposition Autoscroll Status Message $autoScrollContainer.show().css({ top: $body.outerHeight() - 75 }); -<<<<<<< fbd5f4507b310d6dc1305696851e9860b48fa0ba } } @@ -196,24 +195,6 @@ // Check if Refresh Animation is in Viewport and enable Autoscroll, disable otherwise. $autoScrollStatus.data("state", isInViewport($('.js-build-refresh')) ? 'enabled' : 'disabled'); } -======= - } - } - - if (!isInViewport($upBuildTrace) && !isInViewport($downBuildTrace)) { // User is somewhere in middle of Build Log - $scrollTopBtn.show().addClass('sticky'); - $scrollBottomBtn.show().addClass('sticky'); - - if ($autoScrollContainer.length) { - $autoScrollContainer.hide(); - } - } - - if (this.buildStatus === "running" || this.buildStatus === "pending") { - // Check if Refresh Animation is in Viewport and enable Autoscroll, disable otherwise. - $autoScrollStatus.data("state", isInViewport($('.js-build-refresh')) ? 'enabled' : 'disabled'); - } ->>>>>>> Improve isInViewport impl, autoscroll behavior }; Build.prototype.shouldHideSidebarForViewport = function() { -- cgit v1.2.1 From 1f22e7dc8581378bc75dd01822869c2d08650624 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Tue, 6 Dec 2016 16:24:18 +0530 Subject: Icon for Build Scroll --- app/assets/images/scroll_down.svg | 1 + app/assets/images/scroll_down_hover_active.svg | 1 + app/assets/images/scroll_up.svg | 1 + app/assets/images/scroll_up_hover_active.svg | 1 + 4 files changed, 4 insertions(+) create mode 100644 app/assets/images/scroll_down.svg create mode 100644 app/assets/images/scroll_down_hover_active.svg create mode 100644 app/assets/images/scroll_up.svg create mode 100644 app/assets/images/scroll_up_hover_active.svg (limited to 'app') diff --git a/app/assets/images/scroll_down.svg b/app/assets/images/scroll_down.svg new file mode 100644 index 00000000000..5b3a6250a7e --- /dev/null +++ b/app/assets/images/scroll_down.svg @@ -0,0 +1 @@ + diff --git a/app/assets/images/scroll_down_hover_active.svg b/app/assets/images/scroll_down_hover_active.svg new file mode 100644 index 00000000000..d622c591df4 --- /dev/null +++ b/app/assets/images/scroll_down_hover_active.svg @@ -0,0 +1 @@ + diff --git a/app/assets/images/scroll_up.svg b/app/assets/images/scroll_up.svg new file mode 100644 index 00000000000..0d7a7f51a11 --- /dev/null +++ b/app/assets/images/scroll_up.svg @@ -0,0 +1 @@ + diff --git a/app/assets/images/scroll_up_hover_active.svg b/app/assets/images/scroll_up_hover_active.svg new file mode 100644 index 00000000000..86e1cae2c51 --- /dev/null +++ b/app/assets/images/scroll_up_hover_active.svg @@ -0,0 +1 @@ + -- cgit v1.2.1 From 16ad6ed0387f0152ed3a71e643b948be59bcf3d7 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Tue, 6 Dec 2016 16:25:36 +0530 Subject: Replace scroll buttons with new icons --- app/views/projects/builds/show.html.haml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'app') diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml index 3cfbdb2d367..3cbdab07889 100644 --- a/app/views/projects/builds/show.html.haml +++ b/app/views/projects/builds/show.html.haml @@ -56,17 +56,13 @@ - else #js-build-scroll.scroll-controls .scroll-step - = link_to '#up-build-trace', id: 'scroll-top', class: 'btn', title: 'Scroll to top' do - %i.fa.fa-long-arrow-up - %span.scroll-step-label Scroll to top - = link_to '#down-build-trace', id: 'scroll-bottom', class: 'btn', title: 'Scroll to bottom' do - %i.fa.fa-long-arrow-down - %span.scroll-step-label Scroll to bottom + %a{ href: '#up-build-trace', id: 'scroll-top', class: 'scroll-link scroll-top', title: 'Scroll to top'} + %a{ href: '#down-build-trace', id: 'scroll-bottom', class: 'scroll-link scroll-bottom', title: 'Scroll to bottom'} - if @build.active? .autoscroll-container - %span.status-message#autoscroll-status{:data => {:state => 'enabled'}, :title => 'Autoscroll active'} - %i.fa.fa-toggle-on + %span.status-message#autoscroll-status{:data => {:state => 'enabled'}} %label Autoscroll active + %i.status-icon #up-build-trace %pre.build-trace#build-trace %code.bash.js-build-output -- cgit v1.2.1 From ba63e4f1ed9f8d8e452a80c6f96b50c5487510c8 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Tue, 6 Dec 2016 16:27:08 +0530 Subject: Updated styles to use scroll icons --- app/assets/stylesheets/pages/builds.scss | 68 +++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 22 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index b256d907649..0185491bc93 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -22,26 +22,44 @@ margin: 0 0 0 auto; } - .btn.sticky, + .scroll-link.sticky, .autoscroll-container { right: 25px; z-index: 1; } - .btn { + .scroll-link { display: block; margin-bottom: 10px; - color: $white-light; - border-color: $white-light; - background-color: rgba($ci-output-bg, .5); + width: 16px; + height: 33px; + + &.scroll-top { + background-image: image-url('scroll_up'); + + &:hover { + background-image: image-url('scroll_up_hover_active'); + } + } + + &.scroll-bottom { + background-image: image-url('scroll_down'); + + &:hover { + background-image: image-url('scroll_down_hover_active'); + } + } &.sticky { position: fixed; - } - &:hover{ - color: $ci-output-bg; - background-color: $white-light; + &.scroll-top { + top: 110px; + } + + &.scroll-bottom { + bottom: -2px; + } } } @@ -49,33 +67,41 @@ position: absolute; .status-message { + display: inline-block; color: $white-light; + i { + display: inline-block; + width: 16px; + height: 33px; + background-image: image-url('scroll_down_hover_active'); + } + label { - margin-left: 5px; + float: left; + opacity: 0; + margin-right: 10px; font-weight: normal; + line-height: 1.8; + transition: opacity 1s ease-out; } - } - } - #scroll-top.btn.sticky { - top: 110px; - } - - #scroll-bottom.btn.sticky { - bottom: -2px; + &:hover label { + opacity: 1; + } + } } &.sidebar-expanded { - .btn.sticky, + .scroll-link.sticky, .autoscroll-container { right: #{$gutter_width + ($gl-padding * 2)}; } } @media (max-width: $screen-sm-max) { - .btn { + .scroll-link { padding: 6px 13px; } @@ -322,8 +348,6 @@ margin-top: -17px; } - - @media (min-width: $screen-md-min) { .sub-nav.build { width: calc(100% + #{$gutter_width}); -- cgit v1.2.1 From c245a667d279066ee819230ec373ee0502c0e0f4 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Thu, 8 Dec 2016 16:07:30 +0530 Subject: Add autoscroll status indicator animation --- app/assets/stylesheets/pages/builds.scss | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index 0185491bc93..ece9568cba3 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -1,3 +1,8 @@ +@keyframes fade-out-status { + 0%, 50% { opacity: 1; } + 100% { opacity: 0; } +} + .build-page { pre.trace { background: $builds-trace-bg; @@ -84,6 +89,10 @@ font-weight: normal; line-height: 1.8; transition: opacity 1s ease-out; + + &.animate { + animation: fade-out-status 2s ease; + } } &:hover label { @@ -99,21 +108,6 @@ right: #{$gutter_width + ($gl-padding * 2)}; } } - - @media (max-width: $screen-sm-max) { - .scroll-link { - padding: 6px 13px; - } - - i.fa { - margin-right: 0; - } - - .scroll-step-label, - .status-message label { - display: none; - } - } } .environment-information { -- cgit v1.2.1 From 1549db64715596437332aaee64eef3f2655a1c77 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Thu, 8 Dec 2016 16:07:59 +0530 Subject: Add animation to autoscroll indicator when activated --- app/assets/javascripts/build.js | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app') diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index fc4b4aeb73c..11eaa2858b6 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -179,6 +179,7 @@ if ($autoScrollContainer.length) { // Show and Reposition Autoscroll Status Message $autoScrollContainer.show().css({ top: $body.outerHeight() - 75 }); + $autoScrollStatus.find('label').addClass('animate'); } } @@ -188,6 +189,7 @@ if ($autoScrollContainer.length) { $autoScrollContainer.hide(); + $autoScrollStatus.find('label').removeClass('animate'); } } -- cgit v1.2.1 From 46f0633272e5a9af708bbb09f6c6df9b7734ba0c Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Thu, 8 Dec 2016 16:32:43 +0530 Subject: Autoscroll is disabled by default --- app/views/projects/builds/show.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml index 3cbdab07889..bf728983f36 100644 --- a/app/views/projects/builds/show.html.haml +++ b/app/views/projects/builds/show.html.haml @@ -60,7 +60,7 @@ %a{ href: '#down-build-trace', id: 'scroll-bottom', class: 'scroll-link scroll-bottom', title: 'Scroll to bottom'} - if @build.active? .autoscroll-container - %span.status-message#autoscroll-status{:data => {:state => 'enabled'}} + %span.status-message#autoscroll-status{:data => {:state => 'disabled'}} %label Autoscroll active %i.status-icon #up-build-trace -- cgit v1.2.1 From f06678cb1af25a4d7e3b3dae29c15eda58935e59 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Thu, 8 Dec 2016 16:33:00 +0530 Subject: Fix Autoscroll status icon misalignment on page reload --- app/assets/javascripts/build.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index 11eaa2858b6..e14e22c8dae 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -139,8 +139,7 @@ $scrollBottomBtn.show().addClass('sticky'); if ($autoScrollContainer.length) { - $scrollBottomBtn.hide(); - $autoScrollContainer.show().css({ bottom: 50 }); + $autoScrollContainer.hide(); } } -- cgit v1.2.1 From ff0c3fc23b9808438c8959e835937c48297de9b3 Mon Sep 17 00:00:00 2001 From: Dimitrie Hoekstra Date: Thu, 8 Dec 2016 14:08:08 +0100 Subject: added a running loading indicator --- app/assets/stylesheets/pages/builds.scss | 33 ++++++++++++++++++++++++++++++++ app/views/projects/builds/show.html.haml | 2 +- 2 files changed, 34 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index ece9568cba3..b50971af4e6 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -178,6 +178,39 @@ .bash { display: block; } + + .typing_loader{ + width: 6px; + height: 6px; + border-radius: 50%; + animation: typing 1s linear infinite; + position: relative; + margin-bottom: 12px; + margin-left: 2px; + } + + @keyframes typing{ + 0%{ + background-color: rgba(255,255,255, 1); + box-shadow: 12px 0px 0px 0px rgba(255,255,255,0.2), + 24px 0px 0px 0px rgba(255,255,255,0.2); + } + 25%{ + background-color: rgba(255,255,255, 0.4); + box-shadow: 12px 0px 0px 0px rgba(255,255,255,2), + 24px 0px 0px 0px rgba(255,255,255,0.2); + } + 75%{ + background-color: rgba(255,255,255, 0.4); + box-shadow: 12px 0px 0px 0px rgba(255,255,255,0.2), + 24px 0px 0px 0px rgba(255,255,255,1); + } + 100%{ + background-color: rgba(255,255,255, 1); + box-shadow: 12px 0px 0px 0px rgba(255,255,255,0.2), + 24px 0px 0px 0px rgba(255,255,255,0.2); + } + } } .right-sidebar.build-sidebar { diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml index bf728983f36..c32cce15544 100644 --- a/app/views/projects/builds/show.html.haml +++ b/app/views/projects/builds/show.html.haml @@ -66,7 +66,7 @@ #up-build-trace %pre.build-trace#build-trace %code.bash.js-build-output - = icon("refresh spin", class: "js-build-refresh") + .typing_loader.js-build-refresh #down-build-trace -- cgit v1.2.1 From 2421fc7e089d634e0069285cf2addb0745df53dd Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Fri, 9 Dec 2016 17:09:06 +0530 Subject: Refactor SCSS: fix SCSSLints, simplify specificity --- app/assets/stylesheets/pages/builds.scss | 219 ++++++++++++++++--------------- 1 file changed, 111 insertions(+), 108 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index b50971af4e6..23028ae01de 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -3,6 +3,32 @@ 100% { opacity: 0; } } +@keyframes blinking-dots { + 0% { + background-color: rgba($white-light, 1); + box-shadow: 12px 0 0 0 rgba($white-light,0.2), + 24px 0 0 0 rgba($white-light,0.2); + } + + 25% { + background-color: rgba($white-light, 0.4); + box-shadow: 12px 0 0 0 rgba($white-light,2), + 24px 0 0 0 rgba($white-light,0.2); + } + + 75%{ + background-color: rgba($white-light, 0.4); + box-shadow: 12px 0 0 0 rgba($white-light,0.2), + 24px 0 0 0 rgba($white-light,1); + } + + 100% { + background-color: rgba($white-light, 1); + box-shadow: 12px 0 0 0 rgba($white-light,0.2), + 24px 0 0 0 rgba($white-light,0.2); + } +} + .build-page { pre.trace { background: $builds-trace-bg; @@ -19,109 +45,109 @@ } } - .scroll-controls { - height: 100%; + .environment-information { + background-color: $gray-light; + border: 1px solid $border-color; + padding: 12px $gl-padding; + border-radius: $border-radius-default; - .scroll-step { - width: 31px; - margin: 0 0 0 auto; + svg { + position: relative; + top: 1px; + margin-right: 5px; } + } +} - .scroll-link.sticky, - .autoscroll-container { - right: 25px; - z-index: 1; - } +.scroll-controls { + height: 100%; - .scroll-link { - display: block; - margin-bottom: 10px; - width: 16px; - height: 33px; + .scroll-step { + width: 31px; + margin: 0 0 0 auto; + } - &.scroll-top { - background-image: image-url('scroll_up'); + .scroll-link.sticky, + .autoscroll-container { + right: 25px; + z-index: 1; + } - &:hover { - background-image: image-url('scroll_up_hover_active'); - } - } + .scroll-link { + display: block; + margin-bottom: 10px; + width: 16px; + height: 33px; - &.scroll-bottom { - background-image: image-url('scroll_down'); + &.scroll-top { + background-image: image-url('scroll_up'); - &:hover { - background-image: image-url('scroll_down_hover_active'); - } + &:hover { + background-image: image-url('scroll_up_hover_active'); } + } - &.sticky { - position: fixed; - - &.scroll-top { - top: 110px; - } + &.scroll-bottom { + background-image: image-url('scroll_down'); - &.scroll-bottom { - bottom: -2px; - } + &:hover { + background-image: image-url('scroll_down_hover_active'); } } - .autoscroll-container { - position: absolute; - - .status-message { - display: inline-block; - color: $white-light; + &.sticky { + position: fixed; - i { - display: inline-block; - width: 16px; - height: 33px; - background-image: image-url('scroll_down_hover_active'); - } - - label { - float: left; - opacity: 0; - margin-right: 10px; - font-weight: normal; - line-height: 1.8; - transition: opacity 1s ease-out; - - &.animate { - animation: fade-out-status 2s ease; - } - } + &.scroll-top { + top: 110px; + } - &:hover label { - opacity: 1; - } + &.scroll-bottom { + bottom: -2px; } } + } - &.sidebar-expanded { + .autoscroll-container { + position: absolute; + } - .scroll-link.sticky, - .autoscroll-container { - right: #{$gutter_width + ($gl-padding * 2)}; - } + &.sidebar-expanded { + + .scroll-link.sticky, + .autoscroll-container { + right: ($gutter_width + ($gl-padding * 2)); } } +} - .environment-information { - background-color: $gray-light; - border: 1px solid $border-color; - padding: 12px $gl-padding; - border-radius: $border-radius-default; +.status-message { + display: inline-block; + color: $white-light; - svg { - position: relative; - top: 1px; - margin-right: 5px; + .status-icon { + display: inline-block; + width: 16px; + height: 33px; + background-image: image-url('scroll_down_hover_active'); + } + + .status-text { + float: left; + opacity: 0; + margin-right: 10px; + font-weight: normal; + line-height: 1.8; + transition: opacity 1s ease-out; + + &.animate { + animation: fade-out-status 2s ease; } } + + &:hover .status-text { + opacity: 1; + } } .build-header { @@ -179,37 +205,14 @@ display: block; } - .typing_loader{ - width: 6px; - height: 6px; - border-radius: 50%; - animation: typing 1s linear infinite; - position: relative; - margin-bottom: 12px; - margin-left: 2px; - } - - @keyframes typing{ - 0%{ - background-color: rgba(255,255,255, 1); - box-shadow: 12px 0px 0px 0px rgba(255,255,255,0.2), - 24px 0px 0px 0px rgba(255,255,255,0.2); - } - 25%{ - background-color: rgba(255,255,255, 0.4); - box-shadow: 12px 0px 0px 0px rgba(255,255,255,2), - 24px 0px 0px 0px rgba(255,255,255,0.2); - } - 75%{ - background-color: rgba(255,255,255, 0.4); - box-shadow: 12px 0px 0px 0px rgba(255,255,255,0.2), - 24px 0px 0px 0px rgba(255,255,255,1); - } - 100%{ - background-color: rgba(255,255,255, 1); - box-shadow: 12px 0px 0px 0px rgba(255,255,255,0.2), - 24px 0px 0px 0px rgba(255,255,255,0.2); - } + .build-loader-animation { + position: relative; + width: 6px; + height: 6px; + margin-bottom: 12px; + margin-left: 2px; + border-radius: 50%; + animation: blinking-dots 1s linear infinite; } } -- cgit v1.2.1 From 94fd6cf74b44404e5f450a195e252b1b76e844cc Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Fri, 9 Dec 2016 17:09:41 +0530 Subject: Update selector for build status text --- app/assets/javascripts/build.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index e14e22c8dae..51ac8d7970b 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -178,7 +178,7 @@ if ($autoScrollContainer.length) { // Show and Reposition Autoscroll Status Message $autoScrollContainer.show().css({ top: $body.outerHeight() - 75 }); - $autoScrollStatus.find('label').addClass('animate'); + $autoScrollStatus.find('.status-text').addClass('animate'); } } @@ -188,7 +188,7 @@ if ($autoScrollContainer.length) { $autoScrollContainer.hide(); - $autoScrollStatus.find('label').removeClass('animate'); + $autoScrollStatus.find('.status-text').removeClass('animate'); } } -- cgit v1.2.1 From a8fa87ce9d0dea1baed7c40e10a6b19da99ec6e4 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Fri, 9 Dec 2016 17:09:57 +0530 Subject: Update class names & element types --- app/views/projects/builds/show.html.haml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml index c32cce15544..0c3b7597c91 100644 --- a/app/views/projects/builds/show.html.haml +++ b/app/views/projects/builds/show.html.haml @@ -60,13 +60,13 @@ %a{ href: '#down-build-trace', id: 'scroll-bottom', class: 'scroll-link scroll-bottom', title: 'Scroll to bottom'} - if @build.active? .autoscroll-container - %span.status-message#autoscroll-status{:data => {:state => 'disabled'}} - %label Autoscroll active + %span.status-message#autoscroll-status{ data: { state: 'disabled' } } + %span.status-text Autoscroll active %i.status-icon #up-build-trace %pre.build-trace#build-trace %code.bash.js-build-output - .typing_loader.js-build-refresh + .build-loader-animation.js-build-refresh #down-build-trace -- cgit v1.2.1 From c02945ac95ee3374007249f07211cbf6002a2fa2 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Fri, 9 Dec 2016 17:56:25 +0530 Subject: Cache commonly referenced DOM elements, cleaning up --- app/assets/javascripts/build.js | 69 +++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 40 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index 51ac8d7970b..5983bd86e8e 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -31,6 +31,15 @@ this.buildStage = options.buildStage; this.updateDropdown = bind(this.updateDropdown, this); this.$document = $(document); + this.$body = $('body'); + this.$buildTrace = $('#build-trace'); + this.$autoScrollContainer = $('.autoscroll-container'); + this.$autoScrollStatus = $('#autoscroll-status'); + this.$upBuildTrace = $('#up-build-trace'); + this.$downBuildTrace = $('#down-build-trace'); + this.$scrollTopBtn = $('#scroll-top'); + this.$scrollBottomBtn = $('#scroll-bottom'); + clearInterval(Build.interval); // Init breakpoint checker this.bp = Breakpoints.get(); @@ -123,24 +132,15 @@ }; Build.prototype.checkAutoscroll = function() { - if ("enabled" === $("#autoscroll-status").data("state")) { + if ($("#autoscroll-status").data("state") === "enabled") { return $("html,body").scrollTop($("#build-trace").height()); } }; Build.prototype.initScrollButtonAffix = function() { - var $body = $('body'); - var $buildTrace = $('#build-trace'); - var $scrollTopBtn = $('#scroll-top'); - var $scrollBottomBtn = $('#scroll-bottom'); - var $autoScrollContainer = $('.autoscroll-container'); - - $scrollTopBtn.hide().removeClass('sticky'); - $scrollBottomBtn.show().addClass('sticky'); - - if ($autoScrollContainer.length) { - $autoScrollContainer.hide(); - } + this.$scrollTopBtn.hide().removeClass('sticky'); + this.$scrollBottomBtn.show().addClass('sticky'); + this.$autoScrollContainer.hide(); } // Page scroll listener to detect if user has scrolling page @@ -158,43 +158,32 @@ // - Show Bottom Arrow button // - Disable Autoscroll and hide indicator (when build is running) Build.prototype.initScrollMonitor = function() { - var $body = $('body'); - var $buildTrace = $('#build-trace'); - var $autoScrollContainer = $('.autoscroll-container'); - var $autoScrollStatus = $('#autoscroll-status'); - var $upBuildTrace = $('#up-build-trace'); - var $downBuildTrace = $('#down-build-trace'); - var $scrollTopBtn = $('#scroll-top'); - var $scrollBottomBtn = $('#scroll-bottom'); - - if (isInViewport($upBuildTrace)) { // User is at Top of Build Log - $scrollTopBtn.hide().removeClass('sticky'); - $scrollBottomBtn.show().addClass('sticky'); + if (isInViewport(this.$upBuildTrace)) { // User is at Top of Build Log + this.$scrollTopBtn.hide().removeClass('sticky'); + this.$scrollBottomBtn.show().addClass('sticky'); } - if (isInViewport($downBuildTrace)) { // User is at Bottom of Build Log - $scrollTopBtn.show().addClass('sticky'); - $scrollBottomBtn.hide().removeClass('sticky'); + if (isInViewport(this.$downBuildTrace)) { // User is at Bottom of Build Log + this.$scrollTopBtn.show().addClass('sticky'); + this.$scrollBottomBtn.hide().removeClass('sticky'); - if ($autoScrollContainer.length) { // Show and Reposition Autoscroll Status Message - $autoScrollContainer.show().css({ top: $body.outerHeight() - 75 }); - $autoScrollStatus.find('.status-text').addClass('animate'); - } + // Show and Reposition Autoscroll Status Indicator + this.$autoScrollContainer.css({ top: this.$body.outerHeight() - 75 }).fadeIn(100); + this.$autoScrollStatus.find('.status-text').addClass('animate'); } - if (!isInViewport($upBuildTrace) && !isInViewport($downBuildTrace)) { // User is somewhere in middle of Build Log - $scrollTopBtn.show().addClass('sticky'); - $scrollBottomBtn.show().addClass('sticky'); + if (!isInViewport(this.$upBuildTrace) && !isInViewport(this.$downBuildTrace)) { // User is somewhere in middle of Build Log + this.$scrollTopBtn.show().addClass('sticky'); + this.$scrollBottomBtn.show().addClass('sticky'); - if ($autoScrollContainer.length) { - $autoScrollContainer.hide(); - $autoScrollStatus.find('.status-text').removeClass('animate'); - } + // Hide Autoscroll Status Indicator + this.$autoScrollContainer.hide(); + this.$autoScrollStatus.find('.status-text').removeClass('animate'); } if (this.buildStatus === "running" || this.buildStatus === "pending") { // Check if Refresh Animation is in Viewport and enable Autoscroll, disable otherwise. - $autoScrollStatus.data("state", isInViewport($('.js-build-refresh')) ? 'enabled' : 'disabled'); + this.$autoScrollStatus.data("state", isInViewport($('.js-build-refresh')) ? 'enabled' : 'disabled'); } }; -- cgit v1.2.1 From 3202c9c01b6c638ed9a8b7195b83b862b97ee33d Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Fri, 9 Dec 2016 19:05:35 +0530 Subject: Embed SVG using `custom_icon` --- app/assets/images/scroll_down.svg | 1 - app/assets/images/scroll_down_hover_active.svg | 1 - app/assets/images/scroll_up.svg | 1 - app/assets/images/scroll_up_hover_active.svg | 1 - app/views/shared/icons/_scroll_down.svg.erb | 3 +++ app/views/shared/icons/_scroll_down_hover_active.svg.erb | 3 +++ app/views/shared/icons/_scroll_up.svg.erb | 3 +++ app/views/shared/icons/_scroll_up_hover_active.svg.erb | 3 +++ 8 files changed, 12 insertions(+), 4 deletions(-) delete mode 100644 app/assets/images/scroll_down.svg delete mode 100644 app/assets/images/scroll_down_hover_active.svg delete mode 100644 app/assets/images/scroll_up.svg delete mode 100644 app/assets/images/scroll_up_hover_active.svg create mode 100644 app/views/shared/icons/_scroll_down.svg.erb create mode 100644 app/views/shared/icons/_scroll_down_hover_active.svg.erb create mode 100644 app/views/shared/icons/_scroll_up.svg.erb create mode 100644 app/views/shared/icons/_scroll_up_hover_active.svg.erb (limited to 'app') diff --git a/app/assets/images/scroll_down.svg b/app/assets/images/scroll_down.svg deleted file mode 100644 index 5b3a6250a7e..00000000000 --- a/app/assets/images/scroll_down.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/app/assets/images/scroll_down_hover_active.svg b/app/assets/images/scroll_down_hover_active.svg deleted file mode 100644 index d622c591df4..00000000000 --- a/app/assets/images/scroll_down_hover_active.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/app/assets/images/scroll_up.svg b/app/assets/images/scroll_up.svg deleted file mode 100644 index 0d7a7f51a11..00000000000 --- a/app/assets/images/scroll_up.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/app/assets/images/scroll_up_hover_active.svg b/app/assets/images/scroll_up_hover_active.svg deleted file mode 100644 index 86e1cae2c51..00000000000 --- a/app/assets/images/scroll_up_hover_active.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/app/views/shared/icons/_scroll_down.svg.erb b/app/views/shared/icons/_scroll_down.svg.erb new file mode 100644 index 00000000000..acf22ac9314 --- /dev/null +++ b/app/views/shared/icons/_scroll_down.svg.erb @@ -0,0 +1,3 @@ + + + diff --git a/app/views/shared/icons/_scroll_down_hover_active.svg.erb b/app/views/shared/icons/_scroll_down_hover_active.svg.erb new file mode 100644 index 00000000000..262576acf54 --- /dev/null +++ b/app/views/shared/icons/_scroll_down_hover_active.svg.erb @@ -0,0 +1,3 @@ + + + diff --git a/app/views/shared/icons/_scroll_up.svg.erb b/app/views/shared/icons/_scroll_up.svg.erb new file mode 100644 index 00000000000..f11288fd59c --- /dev/null +++ b/app/views/shared/icons/_scroll_up.svg.erb @@ -0,0 +1,3 @@ + + + diff --git a/app/views/shared/icons/_scroll_up_hover_active.svg.erb b/app/views/shared/icons/_scroll_up_hover_active.svg.erb new file mode 100644 index 00000000000..4658dbb1bb7 --- /dev/null +++ b/app/views/shared/icons/_scroll_up_hover_active.svg.erb @@ -0,0 +1,3 @@ + + + -- cgit v1.2.1 From d144160f9f1f7b59ea2cc49d511b6a195b8b6e2d Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Fri, 9 Dec 2016 19:06:21 +0530 Subject: Flip embedded SVG on hover --- app/assets/stylesheets/pages/builds.scss | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index 23028ae01de..04cd9db2acf 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -80,18 +80,36 @@ height: 33px; &.scroll-top { - background-image: image-url('scroll_up'); + .gitlab-icon-scroll-up-hover { + display: none; + } &:hover { - background-image: image-url('scroll_up_hover_active'); + + .gitlab-icon-scroll-up { + display: none; + } + + .gitlab-icon-scroll-up-hover { + display: inline-block; + } } } &.scroll-bottom { - background-image: image-url('scroll_down'); + .gitlab-icon-scroll-down-hover { + display: none; + } &:hover { - background-image: image-url('scroll_down_hover_active'); + + .gitlab-icon-scroll-down { + display: none; + } + + .gitlab-icon-scroll-down-hover { + display: inline-block; + } } } @@ -129,7 +147,6 @@ display: inline-block; width: 16px; height: 33px; - background-image: image-url('scroll_down_hover_active'); } .status-text { -- cgit v1.2.1 From 5fc161c2a78710bb026e73bd502e4955022ec3b0 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Fri, 9 Dec 2016 19:06:38 +0530 Subject: Embed SVG using `custom_icon` --- app/views/projects/builds/show.html.haml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml index 0c3b7597c91..c69c53b656f 100644 --- a/app/views/projects/builds/show.html.haml +++ b/app/views/projects/builds/show.html.haml @@ -56,13 +56,18 @@ - else #js-build-scroll.scroll-controls .scroll-step - %a{ href: '#up-build-trace', id: 'scroll-top', class: 'scroll-link scroll-top', title: 'Scroll to top'} - %a{ href: '#down-build-trace', id: 'scroll-bottom', class: 'scroll-link scroll-bottom', title: 'Scroll to bottom'} + %a{ href: '#up-build-trace', id: 'scroll-top', class: 'scroll-link scroll-top', title: 'Scroll to top' } + = custom_icon('scroll_up') + = custom_icon('scroll_up_hover_active') + %a{ href: '#down-build-trace', id: 'scroll-bottom', class: 'scroll-link scroll-bottom', title: 'Scroll to bottom' } + = custom_icon('scroll_down') + = custom_icon('scroll_down_hover_active') - if @build.active? .autoscroll-container %span.status-message#autoscroll-status{ data: { state: 'disabled' } } %span.status-text Autoscroll active %i.status-icon + = custom_icon('scroll_down_hover_active') #up-build-trace %pre.build-trace#build-trace %code.bash.js-build-output -- cgit v1.2.1 From df0aeae7da14fa3627c5627c11c521d91170aca9 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Fri, 9 Dec 2016 20:05:36 +0530 Subject: Move `isInViewport` to `gl.utils`, make scroll buttons sticky always --- app/assets/javascripts/build.js | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index 5983bd86e8e..56b48b2cd60 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -10,18 +10,6 @@ Build.state = null; - function isInViewport(el) { - // Courtesy http://stackoverflow.com/a/7557433/414749 - var rect = el[0].getBoundingClientRect(); - - return ( - rect.top >= 0 && - rect.left >= 0 && - rect.bottom <= $(window).height() && - rect.right <= $(window).width() - ); - } - function Build(options) { options = options || $('.js-build-options').data(); this.pageUrl = options.pageUrl; @@ -138,8 +126,8 @@ }; Build.prototype.initScrollButtonAffix = function() { - this.$scrollTopBtn.hide().removeClass('sticky'); - this.$scrollBottomBtn.show().addClass('sticky'); + this.$scrollTopBtn.hide(); + this.$scrollBottomBtn.show(); this.$autoScrollContainer.hide(); } @@ -158,23 +146,23 @@ // - Show Bottom Arrow button // - Disable Autoscroll and hide indicator (when build is running) Build.prototype.initScrollMonitor = function() { - if (isInViewport(this.$upBuildTrace)) { // User is at Top of Build Log - this.$scrollTopBtn.hide().removeClass('sticky'); - this.$scrollBottomBtn.show().addClass('sticky'); + if (gl.utils.isInViewport(this.$upBuildTrace[0])) { // User is at Top of Build Log + this.$scrollTopBtn.hide(); + this.$scrollBottomBtn.show(); } - if (isInViewport(this.$downBuildTrace)) { // User is at Bottom of Build Log - this.$scrollTopBtn.show().addClass('sticky'); - this.$scrollBottomBtn.hide().removeClass('sticky'); + if (gl.utils.isInViewport(this.$downBuildTrace[0])) { // User is at Bottom of Build Log + this.$scrollTopBtn.show(); + this.$scrollBottomBtn.hide(); // Show and Reposition Autoscroll Status Indicator this.$autoScrollContainer.css({ top: this.$body.outerHeight() - 75 }).fadeIn(100); this.$autoScrollStatus.find('.status-text').addClass('animate'); } - if (!isInViewport(this.$upBuildTrace) && !isInViewport(this.$downBuildTrace)) { // User is somewhere in middle of Build Log - this.$scrollTopBtn.show().addClass('sticky'); - this.$scrollBottomBtn.show().addClass('sticky'); + if (!gl.utils.isInViewport(this.$upBuildTrace[0]) && !gl.utils.isInViewport(this.$downBuildTrace[0])) { // User is somewhere in middle of Build Log + this.$scrollTopBtn.show(); + this.$scrollBottomBtn.show(); // Hide Autoscroll Status Indicator this.$autoScrollContainer.hide(); @@ -183,7 +171,7 @@ if (this.buildStatus === "running" || this.buildStatus === "pending") { // Check if Refresh Animation is in Viewport and enable Autoscroll, disable otherwise. - this.$autoScrollStatus.data("state", isInViewport($('.js-build-refresh')) ? 'enabled' : 'disabled'); + this.$autoScrollStatus.data("state", gl.utils.isInViewport($('.js-build-refresh')[0]) ? 'enabled' : 'disabled'); } }; -- cgit v1.2.1 From 719e59c71066748f10bedab35b4006e37e3d025f Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Fri, 9 Dec 2016 20:06:03 +0530 Subject: Make scroll buttons sticky always --- app/assets/stylesheets/pages/builds.scss | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index 04cd9db2acf..173bc2d80cf 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -67,19 +67,20 @@ margin: 0 0 0 auto; } - .scroll-link.sticky, + .scroll-link, .autoscroll-container { right: 25px; z-index: 1; } .scroll-link { + position: fixed; display: block; margin-bottom: 10px; - width: 16px; - height: 33px; &.scroll-top { + top: 110px; + .gitlab-icon-scroll-up-hover { display: none; } @@ -97,6 +98,8 @@ } &.scroll-bottom { + bottom: -2px; + .gitlab-icon-scroll-down-hover { display: none; } @@ -112,18 +115,6 @@ } } } - - &.sticky { - position: fixed; - - &.scroll-top { - top: 110px; - } - - &.scroll-bottom { - bottom: -2px; - } - } } .autoscroll-container { @@ -132,7 +123,7 @@ &.sidebar-expanded { - .scroll-link.sticky, + .scroll-link, .autoscroll-container { right: ($gutter_width + ($gl-padding * 2)); } -- cgit v1.2.1 From 6fe5bb40b6dde14b3594a37b008265e1f9083296 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Fri, 9 Dec 2016 20:06:18 +0530 Subject: Add `isInViewport` --- app/assets/javascripts/lib/utils/common_utils.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'app') diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js index 8fa80502d92..0a0e73e0ccc 100644 --- a/app/assets/javascripts/lib/utils/common_utils.js +++ b/app/assets/javascripts/lib/utils/common_utils.js @@ -93,6 +93,19 @@ } }; + // Check if element scrolled into viewport from above or below + // Courtesy http://stackoverflow.com/a/7557433/414749 + w.gl.utils.isInViewport = function(el) { + var rect = el.getBoundingClientRect(); + + return ( + rect.top >= 0 && + rect.left >= 0 && + rect.bottom <= window.innerHeight && + rect.right <= window.innerWidth + ); + }; + gl.utils.getPagePath = function() { return $('body').data('page').split(':')[0]; }; -- cgit v1.2.1 From ad0b81872a52e984f240f229c3de03bae4d44c7e Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Fri, 9 Dec 2016 20:34:19 +0530 Subject: Fix incorrect scroll button appearance in certain cases --- app/assets/javascripts/build.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index 56b48b2cd60..b4e1d3d9346 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -81,6 +81,7 @@ }; Build.prototype.getInitialBuildTrace = function() { + var _this = this; var removeRefreshStatuses = ['success', 'failed', 'canceled', 'skipped'] return $.ajax({ @@ -89,6 +90,7 @@ success: function(buildData) { $('.js-build-output').html(buildData.trace_html); if (removeRefreshStatuses.indexOf(buildData.status) >= 0) { + _this.initScrollMonitor(); return $('.js-build-refresh').remove(); } } @@ -123,11 +125,20 @@ if ($("#autoscroll-status").data("state") === "enabled") { return $("html,body").scrollTop($("#build-trace").height()); } + + // Handle a situation where user started new build + // but never scrolled a page + if (!this.$scrollTopBtn.is(':visible') && + !this.$scrollBottomBtn.is(':visible') && + !gl.utils.isInViewport(this.$downBuildTrace[0])) { + this.$scrollBottomBtn.show(); + } }; Build.prototype.initScrollButtonAffix = function() { + // Hide everything initially this.$scrollTopBtn.hide(); - this.$scrollBottomBtn.show(); + this.$scrollBottomBtn.hide(); this.$autoScrollContainer.hide(); } -- cgit v1.2.1 From 95d535921214740d0f26f65b1567aa03b9e53b2b Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Mon, 12 Dec 2016 12:17:20 +0530 Subject: ESLint: use outer `this` by currying function --- app/assets/javascripts/build.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index b4e1d3d9346..5c6f0083e57 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -81,19 +81,20 @@ }; Build.prototype.getInitialBuildTrace = function() { - var _this = this; var removeRefreshStatuses = ['success', 'failed', 'canceled', 'skipped'] return $.ajax({ url: this.buildUrl, dataType: 'json', - success: function(buildData) { - $('.js-build-output').html(buildData.trace_html); - if (removeRefreshStatuses.indexOf(buildData.status) >= 0) { - _this.initScrollMonitor(); - return $('.js-build-refresh').remove(); - } - } + success: (function(_this) { + return function(buildData) { + $('.js-build-output').html(buildData.trace_html); + if (removeRefreshStatuses.indexOf(buildData.status) >= 0) { + _this.initScrollMonitor(); + return $('.js-build-refresh').remove(); + } + }; + })(this) }); }; -- cgit v1.2.1 From 2b6b28da740476c02a7bab2113737458e3e6af30 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Mon, 12 Dec 2016 12:17:50 +0530 Subject: SCSSLint: Space before brace --- app/assets/stylesheets/pages/builds.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index 173bc2d80cf..2f7448a0b9d 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -16,7 +16,7 @@ 24px 0 0 0 rgba($white-light,0.2); } - 75%{ + 75% { background-color: rgba($white-light, 0.4); box-shadow: 12px 0 0 0 rgba($white-light,0.2), 24px 0 0 0 rgba($white-light,1); -- cgit v1.2.1 From 45220e310cd12da9bd7b0b07fe3509def063a60c Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Mon, 12 Dec 2016 22:05:17 +0530 Subject: Use `bind` instead of currying to access outer context --- app/assets/javascripts/build.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index 5c6f0083e57..8646ce99726 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -86,15 +86,13 @@ return $.ajax({ url: this.buildUrl, dataType: 'json', - success: (function(_this) { - return function(buildData) { - $('.js-build-output').html(buildData.trace_html); - if (removeRefreshStatuses.indexOf(buildData.status) >= 0) { - _this.initScrollMonitor(); - return $('.js-build-refresh').remove(); - } - }; - })(this) + success: function(buildData) { + $('.js-build-output').html(buildData.trace_html); + if (removeRefreshStatuses.indexOf(buildData.status) >= 0) { + this.initScrollMonitor(); + return $('.js-build-refresh').remove(); + } + }.bind(this) }); }; -- cgit v1.2.1 From 3ed1f6dca770f11e9b86eb3163bbd5476c94e4e0 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Mon, 12 Dec 2016 22:12:24 +0530 Subject: Cache common references to `.status-text` element --- app/assets/javascripts/build.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index 8646ce99726..d8c10457a4a 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -23,6 +23,7 @@ this.$buildTrace = $('#build-trace'); this.$autoScrollContainer = $('.autoscroll-container'); this.$autoScrollStatus = $('#autoscroll-status'); + this.$autoScrollStatusText = this.$autoScrollStatus.find('.status-text'); this.$upBuildTrace = $('#up-build-trace'); this.$downBuildTrace = $('#down-build-trace'); this.$scrollTopBtn = $('#scroll-top'); @@ -167,7 +168,7 @@ // Show and Reposition Autoscroll Status Indicator this.$autoScrollContainer.css({ top: this.$body.outerHeight() - 75 }).fadeIn(100); - this.$autoScrollStatus.find('.status-text').addClass('animate'); + this.$autoScrollStatusText.addClass('animate'); } if (!gl.utils.isInViewport(this.$upBuildTrace[0]) && !gl.utils.isInViewport(this.$downBuildTrace[0])) { // User is somewhere in middle of Build Log @@ -176,7 +177,7 @@ // Hide Autoscroll Status Indicator this.$autoScrollContainer.hide(); - this.$autoScrollStatus.find('.status-text').removeClass('animate'); + this.$autoScrollStatusText.removeClass('animate'); } if (this.buildStatus === "running" || this.buildStatus === "pending") { -- cgit v1.2.1 From dfd156972df7d47465e9222e1979fa9c91b702aa Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Tue, 13 Dec 2016 18:14:04 +0530 Subject: Refactor build log scroll button logic to prevent icon overlaps --- app/assets/javascripts/build.js | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index d8c10457a4a..36612957b39 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -28,6 +28,7 @@ this.$downBuildTrace = $('#down-build-trace'); this.$scrollTopBtn = $('#scroll-top'); this.$scrollBottomBtn = $('#scroll-bottom'); + this.$buildRefreshAnimation = $('.js-build-refresh'); clearInterval(Build.interval); // Init breakpoint checker @@ -91,7 +92,7 @@ $('.js-build-output').html(buildData.trace_html); if (removeRefreshStatuses.indexOf(buildData.status) >= 0) { this.initScrollMonitor(); - return $('.js-build-refresh').remove(); + return this.$buildRefreshAnimation.remove(); } }.bind(this) }); @@ -157,23 +158,27 @@ // - Show Bottom Arrow button // - Disable Autoscroll and hide indicator (when build is running) Build.prototype.initScrollMonitor = function() { - if (gl.utils.isInViewport(this.$upBuildTrace[0])) { // User is at Top of Build Log - this.$scrollTopBtn.hide(); + if (!gl.utils.isInViewport(this.$upBuildTrace[0]) && !gl.utils.isInViewport(this.$downBuildTrace[0])) { // User is somewhere in middle of Build Log + this.$scrollTopBtn.show(); this.$scrollBottomBtn.show(); - } - if (gl.utils.isInViewport(this.$downBuildTrace[0])) { // User is at Bottom of Build Log + // Hide Autoscroll Status Indicator + this.$autoScrollContainer.hide(); + this.$autoScrollStatusText.removeClass('animate'); + } else if (gl.utils.isInViewport(this.$upBuildTrace[0]) && !gl.utils.isInViewport(this.$downBuildTrace[0])) { // User is at Top of Build Log + this.$scrollTopBtn.hide(); + this.$scrollBottomBtn.show(); + } else if ((!gl.utils.isInViewport(this.$upBuildTrace[0]) && gl.utils.isInViewport(this.$downBuildTrace[0])) || + gl.utils.isInViewport(this.$buildRefreshAnimation[0])) { // User is at Bottom of Build Log this.$scrollTopBtn.show(); this.$scrollBottomBtn.hide(); // Show and Reposition Autoscroll Status Indicator this.$autoScrollContainer.css({ top: this.$body.outerHeight() - 75 }).fadeIn(100); this.$autoScrollStatusText.addClass('animate'); - } - - if (!gl.utils.isInViewport(this.$upBuildTrace[0]) && !gl.utils.isInViewport(this.$downBuildTrace[0])) { // User is somewhere in middle of Build Log - this.$scrollTopBtn.show(); - this.$scrollBottomBtn.show(); + } else if (gl.utils.isInViewport(this.$upBuildTrace[0]) && gl.utils.isInViewport(this.$downBuildTrace[0])) { // Build Log height is small + this.$scrollTopBtn.hide(); + this.$scrollBottomBtn.hide(); // Hide Autoscroll Status Indicator this.$autoScrollContainer.hide(); @@ -182,7 +187,7 @@ if (this.buildStatus === "running" || this.buildStatus === "pending") { // Check if Refresh Animation is in Viewport and enable Autoscroll, disable otherwise. - this.$autoScrollStatus.data("state", gl.utils.isInViewport($('.js-build-refresh')[0]) ? 'enabled' : 'disabled'); + this.$autoScrollStatus.data("state", gl.utils.isInViewport(this.$buildRefreshAnimation[0]) ? 'enabled' : 'disabled'); } }; -- cgit v1.2.1 From cc62a416560267d4a87b823faa333bcdaa5867b4 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Tue, 13 Dec 2016 21:13:27 +0530 Subject: Fix case where Autoscroll indicator overlays scroll bottom button --- app/assets/javascripts/build.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index 36612957b39..81149a427dc 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -160,11 +160,23 @@ Build.prototype.initScrollMonitor = function() { if (!gl.utils.isInViewport(this.$upBuildTrace[0]) && !gl.utils.isInViewport(this.$downBuildTrace[0])) { // User is somewhere in middle of Build Log this.$scrollTopBtn.show(); - this.$scrollBottomBtn.show(); + + if (this.buildStatus === 'success' || this.buildStatus === 'failed') { // Check if Build is completed + this.$scrollBottomBtn.show(); + } else if (this.$buildRefreshAnimation.is(':visible') && !gl.utils.isInViewport(this.$buildRefreshAnimation[0])) { + this.$scrollBottomBtn.show(); + } else { + this.$scrollBottomBtn.hide(); + } // Hide Autoscroll Status Indicator - this.$autoScrollContainer.hide(); - this.$autoScrollStatusText.removeClass('animate'); + if (this.$scrollBottomBtn.is(':visible')) { + this.$autoScrollContainer.hide(); + this.$autoScrollStatusText.removeClass('animate'); + } else { + this.$autoScrollContainer.css({ top: this.$body.outerHeight() - 75 }).fadeIn(100); + this.$autoScrollStatusText.addClass('animate'); + } } else if (gl.utils.isInViewport(this.$upBuildTrace[0]) && !gl.utils.isInViewport(this.$downBuildTrace[0])) { // User is at Top of Build Log this.$scrollTopBtn.hide(); this.$scrollBottomBtn.show(); -- cgit v1.2.1 From 3f2fd48c7cdcbefc4d26b5b45c9150433d394271 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Tue, 13 Dec 2016 21:21:13 +0530 Subject: Prevent scroll bottom button and scroll indicator clashes --- app/assets/javascripts/build.js | 3 +++ 1 file changed, 3 insertions(+) (limited to 'app') diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index 81149a427dc..c3cbd07ae21 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -180,6 +180,9 @@ } else if (gl.utils.isInViewport(this.$upBuildTrace[0]) && !gl.utils.isInViewport(this.$downBuildTrace[0])) { // User is at Top of Build Log this.$scrollTopBtn.hide(); this.$scrollBottomBtn.show(); + + this.$autoScrollContainer.hide(); + this.$autoScrollStatusText.removeClass('animate'); } else if ((!gl.utils.isInViewport(this.$upBuildTrace[0]) && gl.utils.isInViewport(this.$downBuildTrace[0])) || gl.utils.isInViewport(this.$buildRefreshAnimation[0])) { // User is at Bottom of Build Log this.$scrollTopBtn.show(); -- cgit v1.2.1 From 63ca9fd0c85fbb5364ee8bf96e78e8ea6bb0427b Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Wed, 14 Dec 2016 21:46:45 +0530 Subject: Combine common rules --- app/assets/stylesheets/pages/builds.scss | 45 +++++++++----------------------- 1 file changed, 13 insertions(+), 32 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index 2f7448a0b9d..f9e8d297c05 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -78,42 +78,24 @@ display: block; margin-bottom: 10px; - &.scroll-top { - top: 110px; - - .gitlab-icon-scroll-up-hover { - display: none; - } - - &:hover { + &.scroll-top .gitlab-icon-scroll-up-hover, + &.scroll-top:hover .gitlab-icon-scroll-up, + &.scroll-bottom .gitlab-icon-scroll-down-hover, + &.scroll-bottom:hover .gitlab-icon-scroll-down { + display: none; + } - .gitlab-icon-scroll-up { - display: none; - } + &.scroll-top:hover .gitlab-icon-scroll-up-hover, + &.scroll-bottom:hover .gitlab-icon-scroll-down-hover { + display: inline-block; + } - .gitlab-icon-scroll-up-hover { - display: inline-block; - } - } + &.scroll-top { + top: 110px; } &.scroll-bottom { bottom: -2px; - - .gitlab-icon-scroll-down-hover { - display: none; - } - - &:hover { - - .gitlab-icon-scroll-down { - display: none; - } - - .gitlab-icon-scroll-down-hover { - display: inline-block; - } - } } } @@ -217,8 +199,7 @@ position: relative; width: 6px; height: 6px; - margin-bottom: 12px; - margin-left: 2px; + margin: auto auto 12px 2px; border-radius: 50%; animation: blinking-dots 1s linear infinite; } -- cgit v1.2.1 From 3817daa37a77193c5f9479136a06c4737b037818 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Wed, 14 Dec 2016 21:47:08 +0530 Subject: Fix scroll top button overlapping --- app/assets/javascripts/build.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index c3cbd07ae21..1cf5e22d7f6 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -184,7 +184,7 @@ this.$autoScrollContainer.hide(); this.$autoScrollStatusText.removeClass('animate'); } else if ((!gl.utils.isInViewport(this.$upBuildTrace[0]) && gl.utils.isInViewport(this.$downBuildTrace[0])) || - gl.utils.isInViewport(this.$buildRefreshAnimation[0])) { // User is at Bottom of Build Log + (this.$buildRefreshAnimation.is(':visible') && gl.utils.isInViewport(this.$buildRefreshAnimation[0]))) { // User is at Bottom of Build Log this.$scrollTopBtn.show(); this.$scrollBottomBtn.hide(); -- cgit v1.2.1 From 09738ad09843721d0b0849702daf51292a372df1 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Wed, 21 Dec 2016 10:04:12 +0530 Subject: Use `get(0)` instead of direct array index access --- app/assets/javascripts/build.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index 1cf5e22d7f6..867238e205e 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -131,7 +131,7 @@ // but never scrolled a page if (!this.$scrollTopBtn.is(':visible') && !this.$scrollBottomBtn.is(':visible') && - !gl.utils.isInViewport(this.$downBuildTrace[0])) { + !gl.utils.isInViewport(this.$downBuildTrace.get(0))) { this.$scrollBottomBtn.show(); } }; @@ -158,12 +158,12 @@ // - Show Bottom Arrow button // - Disable Autoscroll and hide indicator (when build is running) Build.prototype.initScrollMonitor = function() { - if (!gl.utils.isInViewport(this.$upBuildTrace[0]) && !gl.utils.isInViewport(this.$downBuildTrace[0])) { // User is somewhere in middle of Build Log + if (!gl.utils.isInViewport(this.$upBuildTrace.get(0)) && !gl.utils.isInViewport(this.$downBuildTrace.get(0))) { // User is somewhere in middle of Build Log this.$scrollTopBtn.show(); if (this.buildStatus === 'success' || this.buildStatus === 'failed') { // Check if Build is completed this.$scrollBottomBtn.show(); - } else if (this.$buildRefreshAnimation.is(':visible') && !gl.utils.isInViewport(this.$buildRefreshAnimation[0])) { + } else if (this.$buildRefreshAnimation.is(':visible') && !gl.utils.isInViewport(this.$buildRefreshAnimation.get(0))) { this.$scrollBottomBtn.show(); } else { this.$scrollBottomBtn.hide(); @@ -177,21 +177,21 @@ this.$autoScrollContainer.css({ top: this.$body.outerHeight() - 75 }).fadeIn(100); this.$autoScrollStatusText.addClass('animate'); } - } else if (gl.utils.isInViewport(this.$upBuildTrace[0]) && !gl.utils.isInViewport(this.$downBuildTrace[0])) { // User is at Top of Build Log + } else if (gl.utils.isInViewport(this.$upBuildTrace.get(0)) && !gl.utils.isInViewport(this.$downBuildTrace.get(0))) { // User is at Top of Build Log this.$scrollTopBtn.hide(); this.$scrollBottomBtn.show(); this.$autoScrollContainer.hide(); this.$autoScrollStatusText.removeClass('animate'); - } else if ((!gl.utils.isInViewport(this.$upBuildTrace[0]) && gl.utils.isInViewport(this.$downBuildTrace[0])) || - (this.$buildRefreshAnimation.is(':visible') && gl.utils.isInViewport(this.$buildRefreshAnimation[0]))) { // User is at Bottom of Build Log + } else if ((!gl.utils.isInViewport(this.$upBuildTrace.get(0)) && gl.utils.isInViewport(this.$downBuildTrace.get(0))) || + (this.$buildRefreshAnimation.is(':visible') && gl.utils.isInViewport(this.$buildRefreshAnimation.get(0)))) { // User is at Bottom of Build Log this.$scrollTopBtn.show(); this.$scrollBottomBtn.hide(); // Show and Reposition Autoscroll Status Indicator this.$autoScrollContainer.css({ top: this.$body.outerHeight() - 75 }).fadeIn(100); this.$autoScrollStatusText.addClass('animate'); - } else if (gl.utils.isInViewport(this.$upBuildTrace[0]) && gl.utils.isInViewport(this.$downBuildTrace[0])) { // Build Log height is small + } else if (gl.utils.isInViewport(this.$upBuildTrace.get(0)) && gl.utils.isInViewport(this.$downBuildTrace.get(0))) { // Build Log height is small this.$scrollTopBtn.hide(); this.$scrollBottomBtn.hide(); @@ -202,7 +202,7 @@ if (this.buildStatus === "running" || this.buildStatus === "pending") { // Check if Refresh Animation is in Viewport and enable Autoscroll, disable otherwise. - this.$autoScrollStatus.data("state", gl.utils.isInViewport(this.$buildRefreshAnimation[0]) ? 'enabled' : 'disabled'); + this.$autoScrollStatus.data("state", gl.utils.isInViewport(this.$buildRefreshAnimation.get(0)) ? 'enabled' : 'disabled'); } }; -- cgit v1.2.1 From 5bab7c57e3e108d603ceb41c53091ebfb027a37e Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Wed, 21 Dec 2016 10:11:05 +0530 Subject: Set offset via constant variable --- app/assets/javascripts/build.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index 867238e205e..eeafe436d6c 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -4,6 +4,7 @@ (function() { var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + var AUTO_SCROLL_OFFSET = 75; this.Build = (function() { Build.interval = null; @@ -174,7 +175,7 @@ this.$autoScrollContainer.hide(); this.$autoScrollStatusText.removeClass('animate'); } else { - this.$autoScrollContainer.css({ top: this.$body.outerHeight() - 75 }).fadeIn(100); + this.$autoScrollContainer.css({ top: this.$body.outerHeight() - AUTO_SCROLL_OFFSET }).fadeIn(100); this.$autoScrollStatusText.addClass('animate'); } } else if (gl.utils.isInViewport(this.$upBuildTrace.get(0)) && !gl.utils.isInViewport(this.$downBuildTrace.get(0))) { // User is at Top of Build Log @@ -189,7 +190,7 @@ this.$scrollBottomBtn.hide(); // Show and Reposition Autoscroll Status Indicator - this.$autoScrollContainer.css({ top: this.$body.outerHeight() - 75 }).fadeIn(100); + this.$autoScrollContainer.css({ top: this.$body.outerHeight() - AUTO_SCROLL_OFFSET }).fadeIn(100); this.$autoScrollStatusText.addClass('animate'); } else if (gl.utils.isInViewport(this.$upBuildTrace.get(0)) && gl.utils.isInViewport(this.$downBuildTrace.get(0))) { // Build Log height is small this.$scrollTopBtn.hide(); -- cgit v1.2.1 From 7dfd5aa69ed0db0157b475973ffcea592098267a Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Wed, 21 Dec 2016 13:10:35 +0530 Subject: Use cached element references --- app/assets/javascripts/build.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index eeafe436d6c..c9230a2d090 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -124,8 +124,8 @@ }; Build.prototype.checkAutoscroll = function() { - if ($("#autoscroll-status").data("state") === "enabled") { - return $("html,body").scrollTop($("#build-trace").height()); + if (this.$autoScrollStatus.data("state") === "enabled") { + return $("html,body").scrollTop(this.$buildTrace.height()); } // Handle a situation where user started new build -- cgit v1.2.1 From b4aabafaa48043a8b17b3bf927a684174ad31abd Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Wed, 21 Dec 2016 13:31:51 +0530 Subject: Replace `$.fadeIn()` usage with `$.show()` --- app/assets/javascripts/build.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index c9230a2d090..d6a9ab685f2 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -175,7 +175,7 @@ this.$autoScrollContainer.hide(); this.$autoScrollStatusText.removeClass('animate'); } else { - this.$autoScrollContainer.css({ top: this.$body.outerHeight() - AUTO_SCROLL_OFFSET }).fadeIn(100); + this.$autoScrollContainer.css({ top: this.$body.outerHeight() - AUTO_SCROLL_OFFSET }).show(); this.$autoScrollStatusText.addClass('animate'); } } else if (gl.utils.isInViewport(this.$upBuildTrace.get(0)) && !gl.utils.isInViewport(this.$downBuildTrace.get(0))) { // User is at Top of Build Log @@ -190,7 +190,7 @@ this.$scrollBottomBtn.hide(); // Show and Reposition Autoscroll Status Indicator - this.$autoScrollContainer.css({ top: this.$body.outerHeight() - AUTO_SCROLL_OFFSET }).fadeIn(100); + this.$autoScrollContainer.css({ top: this.$body.outerHeight() - AUTO_SCROLL_OFFSET }).show(); this.$autoScrollStatusText.addClass('animate'); } else if (gl.utils.isInViewport(this.$upBuildTrace.get(0)) && gl.utils.isInViewport(this.$downBuildTrace.get(0))) { // Build Log height is small this.$scrollTopBtn.hide(); -- cgit v1.2.1 From 11ba7a885674dd5428b92c2e43a109fa098320f4 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Wed, 21 Dec 2016 13:42:11 +0530 Subject: Move comments to next line --- app/assets/javascripts/build.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index d6a9ab685f2..5e449170cd3 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -159,7 +159,9 @@ // - Show Bottom Arrow button // - Disable Autoscroll and hide indicator (when build is running) Build.prototype.initScrollMonitor = function() { - if (!gl.utils.isInViewport(this.$upBuildTrace.get(0)) && !gl.utils.isInViewport(this.$downBuildTrace.get(0))) { // User is somewhere in middle of Build Log + if (!gl.utils.isInViewport(this.$upBuildTrace.get(0)) && !gl.utils.isInViewport(this.$downBuildTrace.get(0))) { + // User is somewhere in middle of Build Log + this.$scrollTopBtn.show(); if (this.buildStatus === 'success' || this.buildStatus === 'failed') { // Check if Build is completed @@ -178,21 +180,27 @@ this.$autoScrollContainer.css({ top: this.$body.outerHeight() - AUTO_SCROLL_OFFSET }).show(); this.$autoScrollStatusText.addClass('animate'); } - } else if (gl.utils.isInViewport(this.$upBuildTrace.get(0)) && !gl.utils.isInViewport(this.$downBuildTrace.get(0))) { // User is at Top of Build Log + } else if (gl.utils.isInViewport(this.$upBuildTrace.get(0)) && !gl.utils.isInViewport(this.$downBuildTrace.get(0))) { + // User is at Top of Build Log + this.$scrollTopBtn.hide(); this.$scrollBottomBtn.show(); this.$autoScrollContainer.hide(); this.$autoScrollStatusText.removeClass('animate'); } else if ((!gl.utils.isInViewport(this.$upBuildTrace.get(0)) && gl.utils.isInViewport(this.$downBuildTrace.get(0))) || - (this.$buildRefreshAnimation.is(':visible') && gl.utils.isInViewport(this.$buildRefreshAnimation.get(0)))) { // User is at Bottom of Build Log + (this.$buildRefreshAnimation.is(':visible') && gl.utils.isInViewport(this.$buildRefreshAnimation.get(0)))) { + // User is at Bottom of Build Log + this.$scrollTopBtn.show(); this.$scrollBottomBtn.hide(); // Show and Reposition Autoscroll Status Indicator this.$autoScrollContainer.css({ top: this.$body.outerHeight() - AUTO_SCROLL_OFFSET }).show(); this.$autoScrollStatusText.addClass('animate'); - } else if (gl.utils.isInViewport(this.$upBuildTrace.get(0)) && gl.utils.isInViewport(this.$downBuildTrace.get(0))) { // Build Log height is small + } else if (gl.utils.isInViewport(this.$upBuildTrace.get(0)) && gl.utils.isInViewport(this.$downBuildTrace.get(0))) { + // Build Log height is small + this.$scrollTopBtn.hide(); this.$scrollBottomBtn.hide(); -- cgit v1.2.1 From 120eeb5b5163f91220572de0d50c8359f115b7a8 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Wed, 21 Dec 2016 13:58:32 +0530 Subject: Renamed with `.svg` --- app/views/shared/icons/_scroll_down.svg | 3 +++ app/views/shared/icons/_scroll_down.svg.erb | 3 --- app/views/shared/icons/_scroll_down_hover_active.svg | 3 +++ app/views/shared/icons/_scroll_down_hover_active.svg.erb | 3 --- app/views/shared/icons/_scroll_up.svg | 3 +++ app/views/shared/icons/_scroll_up.svg.erb | 3 --- app/views/shared/icons/_scroll_up_hover_active.svg | 3 +++ app/views/shared/icons/_scroll_up_hover_active.svg.erb | 3 --- 8 files changed, 12 insertions(+), 12 deletions(-) create mode 100644 app/views/shared/icons/_scroll_down.svg delete mode 100644 app/views/shared/icons/_scroll_down.svg.erb create mode 100644 app/views/shared/icons/_scroll_down_hover_active.svg delete mode 100644 app/views/shared/icons/_scroll_down_hover_active.svg.erb create mode 100644 app/views/shared/icons/_scroll_up.svg delete mode 100644 app/views/shared/icons/_scroll_up.svg.erb create mode 100644 app/views/shared/icons/_scroll_up_hover_active.svg delete mode 100644 app/views/shared/icons/_scroll_up_hover_active.svg.erb (limited to 'app') diff --git a/app/views/shared/icons/_scroll_down.svg b/app/views/shared/icons/_scroll_down.svg new file mode 100644 index 00000000000..acf22ac9314 --- /dev/null +++ b/app/views/shared/icons/_scroll_down.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/views/shared/icons/_scroll_down.svg.erb b/app/views/shared/icons/_scroll_down.svg.erb deleted file mode 100644 index acf22ac9314..00000000000 --- a/app/views/shared/icons/_scroll_down.svg.erb +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/app/views/shared/icons/_scroll_down_hover_active.svg b/app/views/shared/icons/_scroll_down_hover_active.svg new file mode 100644 index 00000000000..262576acf54 --- /dev/null +++ b/app/views/shared/icons/_scroll_down_hover_active.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/views/shared/icons/_scroll_down_hover_active.svg.erb b/app/views/shared/icons/_scroll_down_hover_active.svg.erb deleted file mode 100644 index 262576acf54..00000000000 --- a/app/views/shared/icons/_scroll_down_hover_active.svg.erb +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/app/views/shared/icons/_scroll_up.svg b/app/views/shared/icons/_scroll_up.svg new file mode 100644 index 00000000000..f11288fd59c --- /dev/null +++ b/app/views/shared/icons/_scroll_up.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/views/shared/icons/_scroll_up.svg.erb b/app/views/shared/icons/_scroll_up.svg.erb deleted file mode 100644 index f11288fd59c..00000000000 --- a/app/views/shared/icons/_scroll_up.svg.erb +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/app/views/shared/icons/_scroll_up_hover_active.svg b/app/views/shared/icons/_scroll_up_hover_active.svg new file mode 100644 index 00000000000..4658dbb1bb7 --- /dev/null +++ b/app/views/shared/icons/_scroll_up_hover_active.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/views/shared/icons/_scroll_up_hover_active.svg.erb b/app/views/shared/icons/_scroll_up_hover_active.svg.erb deleted file mode 100644 index 4658dbb1bb7..00000000000 --- a/app/views/shared/icons/_scroll_up_hover_active.svg.erb +++ /dev/null @@ -1,3 +0,0 @@ - - - -- cgit v1.2.1 From 6e186b76bb22c5803e3d7105f8ff78c11128812d Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 11 Dec 2016 14:09:37 +0200 Subject: Added support for Authentiq oauth provider --- app/assets/images/auth_buttons/authentiq_64.png | Bin 0 -> 17679 bytes app/helpers/auth_helper.rb | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 app/assets/images/auth_buttons/authentiq_64.png (limited to 'app') diff --git a/app/assets/images/auth_buttons/authentiq_64.png b/app/assets/images/auth_buttons/authentiq_64.png new file mode 100644 index 00000000000..81767bbcc54 Binary files /dev/null and b/app/assets/images/auth_buttons/authentiq_64.png differ diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb index 92bac149313..1ee6c1d3afa 100644 --- a/app/helpers/auth_helper.rb +++ b/app/helpers/auth_helper.rb @@ -1,5 +1,5 @@ module AuthHelper - PROVIDERS_WITH_ICONS = %w(twitter github gitlab bitbucket google_oauth2 facebook azure_oauth2).freeze + PROVIDERS_WITH_ICONS = %w(twitter github gitlab bitbucket google_oauth2 facebook azure_oauth2 authentiq).freeze FORM_BASED_PROVIDERS = [/\Aldap/, 'crowd'].freeze def ldap_enabled? -- cgit v1.2.1 From fecebc7991283e5f9aff89119bb2e4dcde9deeab Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Wed, 14 Dec 2016 13:47:16 +0000 Subject: Fixed new line being included in bold/italic in GFM form Closes #25456 --- app/assets/javascripts/lib/utils/text_utility.js | 25 +++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/lib/utils/text_utility.js b/app/assets/javascripts/lib/utils/text_utility.js index ac44b81ee22..cf286dc30ee 100644 --- a/app/assets/javascripts/lib/utils/text_utility.js +++ b/app/assets/javascripts/lib/utils/text_utility.js @@ -44,9 +44,18 @@ } }; gl.text.insertText = function(textArea, text, tag, blockTag, selected, wrap) { - var insertText, inserted, selectedSplit, startChar; + var insertText, inserted, selectedSplit, startChar, removedLastNewLine; + removedLastNewLine = false; + + // Remove the last newline + if (textArea.selectionEnd - textArea.selectionStart > selected.replace(/\n$/, '').length) { + removedLastNewLine = true; + selected = selected.replace(/\n$/, ''); + } + selectedSplit = selected.split('\n'); startChar = !wrap && textArea.selectionStart > 0 ? '\n' : ''; + if (selectedSplit.length > 1 && (!wrap || (blockTag != null))) { if (blockTag != null) { insertText = this.blockTagText(text, textArea, blockTag, selected); @@ -62,6 +71,11 @@ } else { insertText = "" + startChar + tag + selected + (wrap ? tag : ' '); } + + if (removedLastNewLine) { + insertText += '\n'; + } + if (document.queryCommandSupported('insertText')) { inserted = document.execCommand('insertText', false, insertText); } @@ -74,9 +88,9 @@ document.execCommand("ms-endUndoUnit"); } catch (error) {} } - return this.moveCursor(textArea, tag, wrap); + return this.moveCursor(textArea, tag, wrap, removedLastNewLine); }; - gl.text.moveCursor = function(textArea, tag, wrapped) { + gl.text.moveCursor = function(textArea, tag, wrapped, removedLastNewLine) { var pos; if (!textArea.setSelectionRange) { return; @@ -87,6 +101,11 @@ } else { pos = textArea.selectionStart; } + + if (removedLastNewLine) { + pos -= 1; + } + return textArea.setSelectionRange(pos, pos); } }; -- cgit v1.2.1 From 6c81d03f53ec61cd76b56458b645ef318663ad69 Mon Sep 17 00:00:00 2001 From: Nur Rony Date: Thu, 8 Dec 2016 01:36:44 +0600 Subject: fixes left align issue for long system notes --- app/assets/stylesheets/pages/notes.scss | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss index 106c5d4d390..6ac4ec6ea0d 100644 --- a/app/assets/stylesheets/pages/notes.scss +++ b/app/assets/stylesheets/pages/notes.scss @@ -43,7 +43,7 @@ ul.notes { } .system-note-message { - display: inline-block; + display: inline; &::first-letter { text-transform: lowercase; @@ -55,7 +55,7 @@ ul.notes { } p { - display: inline-block; + display: inline; margin: 0; &::first-letter { @@ -151,6 +151,10 @@ ul.notes { } } } + + .note-headline-light { + display: inline; + } } .discussion-body { -- cgit v1.2.1 From fd5062a848d63b89248c384e0171c6f1af833a49 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 21 Dec 2016 11:50:31 +0100 Subject: update controller action to render error in form --- app/controllers/groups_controller.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'app') diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 5c7709ea013..b83c3a872cf 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -82,10 +82,7 @@ class GroupsController < Groups::ApplicationController if Groups::UpdateService.new(@group, current_user, group_params).execute redirect_to edit_group_path(@group), notice: "Group '#{@group.name}' was successfully updated." else - error = group.errors.full_messages.first - alert_message = "Group '#{@group.name}' cannot be updated: " + error - - redirect_to edit_group_path(@group.reload), alert: alert_message + render action: "edit" end end -- cgit v1.2.1 From 55c61d2e412733b0feefcb5fa33a96e584ffe2bc Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Wed, 21 Dec 2016 11:53:44 +0100 Subject: Improve API specs --- app/models/project_services/mattermost_slash_commands_service.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/models/project_services/mattermost_slash_commands_service.rb b/app/models/project_services/mattermost_slash_commands_service.rb index fc1e7d79d08..6c78c0af71c 100644 --- a/app/models/project_services/mattermost_slash_commands_service.rb +++ b/app/models/project_services/mattermost_slash_commands_service.rb @@ -30,8 +30,8 @@ class MattermostSlashCommandsService < ChatSlashCommandsService def list_teams(user) Mattermost::Team.new(user).all - rescue Mattermost::Error - [] + rescue Mattermost::Error => e + [[], e.message] end private @@ -44,7 +44,7 @@ class MattermostSlashCommandsService < ChatSlashCommandsService auto_complete_desc: "Perform common operations on: #{pretty_project_name}", auto_complete_hint: '[help]', description: "Perform common operations on: #{pretty_project_name}", - display_name: "GitLab / #{pretty_project_name}", + display_name: "GitLab / #{pretty_project_name}", method: 'P', user_name: 'GitLab') end -- cgit v1.2.1 From 8b92e9c08b730b02816f501c88e3c237fa77d813 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 21 Dec 2016 13:00:10 +0200 Subject: Allow projects with dashboard as path Signed-off-by: Dmitriy Zaporozhets --- app/validators/project_path_validator.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/validators/project_path_validator.rb b/app/validators/project_path_validator.rb index 927c67b65b0..d9ab8f167d8 100644 --- a/app/validators/project_path_validator.rb +++ b/app/validators/project_path_validator.rb @@ -14,7 +14,8 @@ class ProjectPathValidator < ActiveModel::EachValidator # without tree as reserved name routing can match 'group/project' as group name, # 'tree' as project name and 'deploy_keys' as route. # - RESERVED = (NamespaceValidator::RESERVED + + RESERVED = (NamespaceValidator::RESERVED - + %w[dashboard] + %w[tree commits wikis new edit create update logs_tree preview blob blame raw files create_dir find_file]).freeze -- cgit v1.2.1 From dfa842ce1de5b93bca2f336f3cf8c8769a555853 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Thu, 24 Nov 2016 15:45:34 +0000 Subject: Removes builds tab from merge request Fix specs --- app/assets/javascripts/merge_request_tabs.js | 416 +++++++++++++++++++++ app/assets/javascripts/merge_request_widget.js.es6 | 4 +- .../projects/merge_requests_controller.rb | 4 +- .../projects/merge_requests/_new_submit.html.haml | 11 +- app/views/projects/merge_requests/_show.html.haml | 7 - .../projects/merge_requests/widget/_show.html.haml | 2 - 6 files changed, 421 insertions(+), 23 deletions(-) create mode 100644 app/assets/javascripts/merge_request_tabs.js (limited to 'app') diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js new file mode 100644 index 00000000000..0fc05421d75 --- /dev/null +++ b/app/assets/javascripts/merge_request_tabs.js @@ -0,0 +1,416 @@ +/* eslint-disable max-len, func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, no-use-before-define, no-underscore-dangle, no-undef, one-var, one-var-declaration-per-line, quotes, comma-dangle, consistent-return, prefer-template, no-param-reassign, camelcase, vars-on-top, space-in-parens, curly, prefer-arrow-callback, no-unused-vars, no-return-assign, semi, object-shorthand, operator-assignment, padded-blocks, max-len */ +// MergeRequestTabs +// +// Handles persisting and restoring the current tab selection and lazily-loading +// content on the MergeRequests#show page. +// +/*= require js.cookie */ + +// +// ### Example Markup +// +// +// +//
    +//
    +// Notes Content +//
    +//
    +// Commits Content +//
    +//
    +// Diffs Content +//
    +//
    +// +//
    +//
    +// Loading Animation +//
    +//
    +// +(function() { + var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + + this.MergeRequestTabs = (function() { + MergeRequestTabs.prototype.diffsLoaded = false; + + MergeRequestTabs.prototype.pipelinesLoaded = false; + + MergeRequestTabs.prototype.commitsLoaded = false; + + MergeRequestTabs.prototype.fixedLayoutPref = null; + + function MergeRequestTabs(opts) { + this.opts = opts != null ? opts : {}; + this.opts.setUrl = this.opts.setUrl !== undefined ? this.opts.setUrl : true; + + this.setCurrentAction = bind(this.setCurrentAction, this); + this.tabShown = bind(this.tabShown, this); + this.showTab = bind(this.showTab, this); + // Store the `location` object, allowing for easier stubbing in tests + this._location = location; + this.bindEvents(); + this.activateTab(this.opts.action); + this.initAffix(); + } + + MergeRequestTabs.prototype.bindEvents = function() { + $(document).on('shown.bs.tab', '.merge-request-tabs a[data-toggle="tab"]', this.tabShown); + $(document).on('click', '.js-show-tab', this.showTab); + }; + + MergeRequestTabs.prototype.unbindEvents = function() { + $(document).off('shown.bs.tab', '.merge-request-tabs a[data-toggle="tab"]', this.tabShown); + $(document).off('click', '.js-show-tab', this.showTab); + }; + + MergeRequestTabs.prototype.showTab = function(event) { + event.preventDefault(); + return this.activateTab($(event.target).data('action')); + }; + + MergeRequestTabs.prototype.tabShown = function(event) { + var $target, action, navBarHeight; + $target = $(event.target); + action = $target.data('action'); + if (action === 'commits') { + this.loadCommits($target.attr('href')); + this.expandView(); + this.resetViewContainer(); + } else if (this.isDiffAction(action)) { + this.loadDiff($target.attr('href')); + if ((typeof bp !== "undefined" && bp !== null) && bp.getBreakpointSize() !== 'lg') { + this.shrinkView(); + } + if (this.diffViewType() === 'parallel') { + this.expandViewContainer(); + } + navBarHeight = $('.navbar-gitlab').outerHeight(); + $.scrollTo(".merge-request-details .merge-request-tabs", { + offset: -navBarHeight + }); + } else if (action === 'pipelines') { + this.loadPipelines($target.attr('href')); + this.expandView(); + this.resetViewContainer(); + } else { + this.expandView(); + this.resetViewContainer(); + } + if (this.opts.setUrl) { + this.setCurrentAction(action); + } + }; + + MergeRequestTabs.prototype.scrollToElement = function(container) { + var $el, navBarHeight; + if (window.location.hash) { + navBarHeight = $('.navbar-gitlab').outerHeight() + $('.layout-nav').outerHeight() + document.querySelector('.js-tabs-affix').offsetHeight; + $el = $(container + " " + window.location.hash + ":not(.match)"); + if ($el.length) { + return $.scrollTo(container + " " + window.location.hash + ":not(.match)", { + offset: -navBarHeight + }); + } + } + }; + + // Activate a tab based on the current action + MergeRequestTabs.prototype.activateTab = function(action) { + if (action === 'show') { + action = 'notes'; + } + // important note: the .tab('show') method triggers 'shown.bs.tab' event itself + $(".merge-request-tabs a[data-action='" + action + "']").tab('show'); + }; + + // Replaces the current Merge Request-specific action in the URL with a new one + // + // If the action is "notes", the URL is reset to the standard + // `MergeRequests#show` route. + // + // Examples: + // + // location.pathname # => "/namespace/project/merge_requests/1" + // setCurrentAction('diffs') + // location.pathname # => "/namespace/project/merge_requests/1/diffs" + // + // location.pathname # => "/namespace/project/merge_requests/1/diffs" + // setCurrentAction('notes') + // location.pathname # => "/namespace/project/merge_requests/1" + // + // location.pathname # => "/namespace/project/merge_requests/1/diffs" + // setCurrentAction('commits') + // location.pathname # => "/namespace/project/merge_requests/1/commits" + // + // Returns the new URL String + MergeRequestTabs.prototype.setCurrentAction = function(action) { + var new_state; + // Normalize action, just to be safe + if (action === 'show') { + action = 'notes'; + } + this.currentAction = action; + // Remove a trailing '/commits' '/diffs' '/pipelines' '/new' '/new/diffs' + new_state = this._location.pathname.replace(/\/(commits|diffs|pipelines|new|new\/diffs)(\.html)?\/?$/, ''); + + // Append the new action if we're on a tab other than 'notes' + if (action !== 'notes') { + new_state += "/" + action; + } + // Ensure parameters and hash come along for the ride + new_state += this._location.search + this._location.hash; + history.replaceState({ + turbolinks: true, + url: new_state + // Replace the current history state with the new one without breaking + // Turbolinks' history. + // + // See https://github.com/rails/turbolinks/issues/363 + }, document.title, new_state); + return new_state; + }; + + MergeRequestTabs.prototype.loadCommits = function(source) { + if (this.commitsLoaded) { + return; + } + return this._get({ + url: source + ".json", + success: (function(_this) { + return function(data) { + document.querySelector("div#commits").innerHTML = data.html; + gl.utils.localTimeAgo($('.js-timeago', 'div#commits')); + _this.commitsLoaded = true; + return _this.scrollToElement("#commits"); + }; + })(this) + }); + }; + + MergeRequestTabs.prototype.loadDiff = function(source) { + if (this.diffsLoaded) { + return; + } + + // We extract pathname for the current Changes tab anchor href + // some pages like MergeRequestsController#new has query parameters on that anchor + var url = gl.utils.parseUrl(source); + + return this._get({ + url: (url.pathname + ".json") + this._location.search, + success: (function(_this) { + return function(data) { + $('#diffs').html(data.html); + + if (typeof gl.diffNotesCompileComponents !== 'undefined') { + gl.diffNotesCompileComponents(); + } + + gl.utils.localTimeAgo($('.js-timeago', 'div#diffs')); + $('#diffs .js-syntax-highlight').syntaxHighlight(); + $('#diffs .diff-file').singleFileDiff(); + if (_this.diffViewType() === 'parallel' && (_this.isDiffAction(_this.currentAction)) ) { + _this.expandViewContainer(); + } + _this.diffsLoaded = true; + var anchoredDiff = gl.utils.getLocationHash(); + if (anchoredDiff) _this.openAnchoredDiff(anchoredDiff, function() { + _this.scrollToElement("#diffs"); + _this.highlighSelectedLine(); + }); + _this.filesCommentButton = $('.files .diff-file').filesCommentButton(); + return $(document).off('click', '.diff-line-num a').on('click', '.diff-line-num a', function(e) { + e.preventDefault(); + window.location.hash = $(e.currentTarget).attr('href'); + _this.highlighSelectedLine(); + return _this.scrollToElement("#diffs"); + }); + }; + })(this) + }); + }; + + MergeRequestTabs.prototype.openAnchoredDiff = function(anchoredDiff, cb) { + var diffTitle = $('#file-path-' + anchoredDiff); + var diffFile = diffTitle.closest('.diff-file'); + var nothingHereBlock = $('.nothing-here-block:visible', diffFile); + if (nothingHereBlock.length) { + diffFile.singleFileDiff(true, cb); + } else { + cb(); + } + }; + + MergeRequestTabs.prototype.highlighSelectedLine = function() { + var $diffLine, diffLineTop, hashClassString, locationHash, navBarHeight; + $('.hll').removeClass('hll'); + locationHash = window.location.hash; + if (locationHash !== '') { + dataLineString = '[data-line-code="' + locationHash.replace('#', '') + '"]'; + $diffLine = $(locationHash + ":not(.match)", $('#diffs')); + if (!$diffLine.is('tr')) { + $diffLine = $('#diffs').find("td" + locationHash + ", td" + dataLineString); + } else { + $diffLine = $diffLine.find('td'); + } + if ($diffLine.length) { + $diffLine.addClass('hll'); + diffLineTop = $diffLine.offset().top; + return navBarHeight = $('.navbar-gitlab').outerHeight(); + } + } + }; + + MergeRequestTabs.prototype.loadPipelines = function(source) { + if (this.pipelinesLoaded) { + return; + } + return this._get({ + url: source + ".json", + success: function(data) { + $('#pipelines').html(data.html); + gl.utils.localTimeAgo($('.js-timeago', '#pipelines')); + this.pipelinesLoaded = true; + return this.scrollToElement("#pipelines"); + }.bind(this) + }); + }; + + // Show or hide the loading spinner + // + // status - Boolean, true to show, false to hide + MergeRequestTabs.prototype.toggleLoading = function(status) { + return $('.mr-loading-status .loading').toggle(status); + }; + + MergeRequestTabs.prototype._get = function(options) { + var defaults; + defaults = { + beforeSend: (function(_this) { + return function() { + return _this.toggleLoading(true); + }; + })(this), + complete: (function(_this) { + return function() { + return _this.toggleLoading(false); + }; + })(this), + dataType: 'json', + type: 'GET' + }; + options = $.extend({}, defaults, options); + return $.ajax(options); + }; + + MergeRequestTabs.prototype.diffViewType = function() { + return $('.inline-parallel-buttons a.active').data('view-type'); + }; + + MergeRequestTabs.prototype.isDiffAction = function(action) { + return action === 'diffs' || action === 'new/diffs' + }; + + MergeRequestTabs.prototype.expandViewContainer = function() { + var $wrapper = $('.content-wrapper .container-fluid'); + if (this.fixedLayoutPref === null) { + this.fixedLayoutPref = $wrapper.hasClass('container-limited'); + } + $wrapper.removeClass('container-limited'); + }; + + MergeRequestTabs.prototype.resetViewContainer = function() { + if (this.fixedLayoutPref !== null) { + $('.content-wrapper .container-fluid') + .toggleClass('container-limited', this.fixedLayoutPref); + } + }; + + MergeRequestTabs.prototype.shrinkView = function() { + var $gutterIcon; + $gutterIcon = $('.js-sidebar-toggle i:visible'); + return setTimeout(function() { + if ($gutterIcon.is('.fa-angle-double-right')) { + return $gutterIcon.closest('a').trigger('click', [true]); + } + // Wait until listeners are set + // Only when sidebar is expanded + }, 0); + }; + + MergeRequestTabs.prototype.expandView = function() { + var $gutterIcon; + if (Cookies.get('collapsed_gutter') === 'true') { + return; + } + $gutterIcon = $('.js-sidebar-toggle i:visible'); + return setTimeout(function() { + if ($gutterIcon.is('.fa-angle-double-left')) { + return $gutterIcon.closest('a').trigger('click', [true]); + } + }, 0); + // Expand the issuable sidebar unless the user explicitly collapsed it + // Wait until listeners are set + // Only when sidebar is collapsed + }; + + MergeRequestTabs.prototype.initAffix = function () { + var $tabs = $('.js-tabs-affix'); + + // Screen space on small screens is usually very sparse + // So we dont affix the tabs on these + if (Breakpoints.get().getBreakpointSize() === 'xs' || !$tabs.length) return; + + var $diffTabs = $('#diff-notes-app'), + $fixedNav = $('.navbar-fixed-top'), + $layoutNav = $('.layout-nav'); + + $tabs.off('affix.bs.affix affix-top.bs.affix') + .affix({ + offset: { + top: function () { + var tabsTop = $diffTabs.offset().top - $tabs.height(); + tabsTop = tabsTop - ($fixedNav.height() + $layoutNav.height()); + + return tabsTop; + } + } + }).on('affix.bs.affix', function () { + $diffTabs.css({ + marginTop: $tabs.height() + }); + }).on('affix-top.bs.affix', function () { + $diffTabs.css({ + marginTop: '' + }); + }); + + // Fix bug when reloading the page already scrolling + if ($tabs.hasClass('affix')) { + $tabs.trigger('affix.bs.affix'); + } + }; + + return MergeRequestTabs; + + })(); + +}).call(this); diff --git a/app/assets/javascripts/merge_request_widget.js.es6 b/app/assets/javascripts/merge_request_widget.js.es6 index e47047c4cca..bcfcf30c451 100644 --- a/app/assets/javascripts/merge_request_widget.js.es6 +++ b/app/assets/javascripts/merge_request_widget.js.es6 @@ -45,6 +45,7 @@ $('#modal_merge_info').modal({ show: false }); + this.clearEventListeners(); this.addEventListeners(); this.getCIStatus(false); @@ -74,7 +75,7 @@ MergeRequestWidget.prototype.addEventListeners = function() { var allowedPages; - allowedPages = ['show', 'commits', 'builds', 'pipelines', 'changes']; + allowedPages = ['show', 'commits', 'pipelines', 'changes']; $(document).on('page:change.merge_request', (function(_this) { return function() { var page; @@ -173,7 +174,6 @@ message = message.replace('{{title}}', data.title); notify(title, message, _this.opts.gitlab_icon, function() { this.close(); - return Turbolinks.visit(_this.opts.builds_path); }); } } diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index f0cb5a9d4b4..7b6cdba8dc8 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -9,10 +9,10 @@ class Projects::MergeRequestsController < Projects::ApplicationController before_action :module_enabled before_action :merge_request, only: [ - :edit, :update, :show, :diffs, :commits, :conflicts, :conflict_for_path, :builds, :pipelines, :merge, :merge_check, + :edit, :update, :show, :diffs, :commits, :conflicts, :conflict_for_path, :pipelines, :merge, :merge_check, :ci_status, :ci_environments_status, :toggle_subscription, :cancel_merge_when_build_succeeds, :remove_wip, :resolve_conflicts, :assign_related_issues ] - before_action :validates_merge_request, only: [:show, :diffs, :commits, :builds, :pipelines] + before_action :validates_merge_request, only: [:show, :diffs, :commits, :pipelines] before_action :define_show_vars, only: [:show, :diffs, :commits, :conflicts, :conflict_for_path, :builds, :pipelines] before_action :define_widget_vars, only: [:merge, :cancel_merge_when_build_succeeds, :merge_check] before_action :define_commit_vars, only: [:diffs] diff --git a/app/views/projects/merge_requests/_new_submit.html.haml b/app/views/projects/merge_requests/_new_submit.html.haml index 4a08ed045f4..349181be784 100644 --- a/app/views/projects/merge_requests/_new_submit.html.haml +++ b/app/views/projects/merge_requests/_new_submit.html.haml @@ -34,11 +34,6 @@ = link_to url_for(params), data: {target: 'div#pipelines', action: 'pipelines', toggle: 'tab'} do Pipelines %span.badge= @pipelines.size - - if @pipeline.present? - %li.builds-tab - = link_to url_for(params), data: {target: 'div#builds', action: 'builds', toggle: 'tab'} do - Builds - %span.badge= @statuses_count %li.diffs-tab = link_to url_for(params.merge(action: 'new_diffs')), data: {target: 'div#diffs', action: 'new/diffs', toggle: 'tab'} do Changes @@ -49,9 +44,6 @@ = render "projects/merge_requests/show/commits" #diffs.diffs.tab-pane - # This tab is always loaded via AJAX - - if @pipeline.present? - #builds.builds.tab-pane - = render "projects/merge_requests/show/builds" - if @pipelines.any? #pipelines.pipelines.tab-pane = render "projects/merge_requests/show/pipelines" @@ -66,6 +58,5 @@ }); :javascript var merge_request = new MergeRequest({ - action: "#{(@show_changes_tab ? 'new/diffs' : 'new')}", - buildsLoaded: "#{@pipeline.present? ? 'true' : 'false'}" + action: "#{(@show_changes_tab ? 'new/diffs' : 'new')}" }); diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml index 7725558518f..d1fa51ae7ee 100644 --- a/app/views/projects/merge_requests/_show.html.haml +++ b/app/views/projects/merge_requests/_show.html.haml @@ -65,11 +65,6 @@ = link_to pipelines_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: '#pipelines', action: 'pipelines', toggle: 'tab' } do Pipelines %span.badge= @pipelines.size - - if @pipeline.present? - %li.builds-tab - = link_to builds_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: '#builds', action: 'builds', toggle: 'tab' } do - Builds - %span.badge= @statuses_count %li.diffs-tab = link_to diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: 'div#diffs', action: 'diffs', toggle: 'tab' } do Changes @@ -98,8 +93,6 @@ #commits.commits.tab-pane - # This tab is always loaded via AJAX - #builds.builds.tab-pane - - # This tab is always loaded via AJAX #pipelines.pipelines.tab-pane - # This tab is always loaded via AJAX #diffs.diffs.tab-pane diff --git a/app/views/projects/merge_requests/widget/_show.html.haml b/app/views/projects/merge_requests/widget/_show.html.haml index a8918c85dde..38328501ffd 100644 --- a/app/views/projects/merge_requests/widget/_show.html.haml +++ b/app/views/projects/merge_requests/widget/_show.html.haml @@ -24,12 +24,10 @@ preparing: "{{status}} build", normal: "Build {{status}}" }, - builds_path: "#{builds_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)}", pipelines_path: "#{pipelines_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)}" }; if (typeof merge_request_widget !== 'undefined') { - clearInterval(merge_request_widget.fetchBuildStatusInterval); merge_request_widget.cancelPolling(); merge_request_widget.clearEventListeners(); } -- cgit v1.2.1 From 9a82aa70e3f3ff679c7a27ccbb9d497576b20822 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Fri, 25 Nov 2016 18:10:32 +0000 Subject: Remove builds tab from commit Remove unused file Fix commit link --- app/assets/javascripts/dispatcher.js.es6 | 1 - app/controllers/projects/commit_controller.rb | 31 ++-------------------- .../projects/merge_requests_controller.rb | 11 -------- app/helpers/ci_status_helper.rb | 2 +- app/views/projects/_last_commit.html.haml | 3 ++- app/views/projects/builds/_header.html.haml | 2 +- app/views/projects/commit/_builds.html.haml | 2 -- app/views/projects/commit/_ci_menu.html.haml | 4 --- app/views/projects/commit/builds.html.haml | 9 ------- .../projects/merge_requests/show/_builds.html.haml | 1 - 10 files changed, 6 insertions(+), 60 deletions(-) delete mode 100644 app/views/projects/commit/_builds.html.haml delete mode 100644 app/views/projects/commit/builds.html.haml delete mode 100644 app/views/projects/merge_requests/show/_builds.html.haml (limited to 'app') diff --git a/app/assets/javascripts/dispatcher.js.es6 b/app/assets/javascripts/dispatcher.js.es6 index 752f35e6356..f45371f121e 100644 --- a/app/assets/javascripts/dispatcher.js.es6 +++ b/app/assets/javascripts/dispatcher.js.es6 @@ -138,7 +138,6 @@ new MergedButtons(); break; case 'projects:merge_requests:commits': - case 'projects:merge_requests:builds': new MergedButtons(); break; case 'projects:merge_requests:pipelines': diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb index 8197d9e4c99..3a5bf7d9ff5 100644 --- a/app/controllers/projects/commit_controller.rb +++ b/app/controllers/projects/commit_controller.rb @@ -8,13 +8,10 @@ class Projects::CommitController < Projects::ApplicationController # Authorize before_action :require_non_empty_project - before_action :authorize_download_code!, except: [:cancel_builds, :retry_builds] - before_action :authorize_update_build!, only: [:cancel_builds, :retry_builds] before_action :authorize_read_pipeline!, only: [:pipelines] - before_action :authorize_read_commit_status!, only: [:builds] before_action :commit - before_action :define_commit_vars, only: [:show, :diff_for_path, :builds, :pipelines] - before_action :define_status_vars, only: [:show, :builds, :pipelines] + before_action :define_commit_vars, only: [:show, :diff_for_path, :pipelines] + before_action :define_status_vars, only: [:show, :pipelines] before_action :define_note_vars, only: [:show, :diff_for_path] before_action :authorize_edit_tree!, only: [:revert, :cherry_pick] @@ -35,25 +32,6 @@ class Projects::CommitController < Projects::ApplicationController def pipelines end - def builds - end - - def cancel_builds - ci_builds.running_or_pending.each(&:cancel) - - redirect_back_or_default default: builds_namespace_project_commit_path(project.namespace, project, commit.sha) - end - - def retry_builds - ci_builds.latest.failed.each do |build| - if build.retryable? - Ci::Build.retry(build, current_user) - end - end - - redirect_back_or_default default: builds_namespace_project_commit_path(project.namespace, project, commit.sha) - end - def branches @branches = @project.repository.branch_names_contains(commit.id) @tags = @project.repository.tag_names_contains(commit.id) @@ -98,10 +76,6 @@ class Projects::CommitController < Projects::ApplicationController @noteable = @commit ||= @project.commit(params[:id]) end - def ci_builds - @ci_builds ||= Ci::Build.where(pipeline: pipelines) - end - def define_commit_vars return git_not_found! unless commit @@ -134,7 +108,6 @@ class Projects::CommitController < Projects::ApplicationController def define_status_vars @ci_pipelines = project.pipelines.where(sha: commit.sha) @statuses = CommitStatus.where(pipeline: @ci_pipelines).relevant - @builds = Ci::Build.where(pipeline: @ci_pipelines).relevant end def assign_change_commit_vars(mr_source_branch) diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 7b6cdba8dc8..3abebdfd032 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -201,17 +201,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController end end - def builds - respond_to do |format| - format.html do - define_discussion_vars - - render 'show' - end - format.json { render json: { html: view_to_html_string('projects/merge_requests/show/_builds') } } - end - end - def pipelines @pipelines = @merge_request.all_pipelines diff --git a/app/helpers/ci_status_helper.rb b/app/helpers/ci_status_helper.rb index d9f5e01f0dc..94e91031680 100644 --- a/app/helpers/ci_status_helper.rb +++ b/app/helpers/ci_status_helper.rb @@ -1,7 +1,7 @@ module CiStatusHelper def ci_status_path(pipeline) project = pipeline.project - builds_namespace_project_commit_path(project.namespace, project, pipeline.sha) + # builds_namespace_project_commit_path(project.namespace, project, pipeline.sha) end # Is used by Commit and Merge Request Widget diff --git a/app/views/projects/_last_commit.html.haml b/app/views/projects/_last_commit.html.haml index 7f530708947..e1fea8ccf3d 100644 --- a/app/views/projects/_last_commit.html.haml +++ b/app/views/projects/_last_commit.html.haml @@ -1,7 +1,8 @@ + - ref = local_assigns.fetch(:ref) - status = commit.status(ref) - if status - = link_to builds_namespace_project_commit_path(commit.project.namespace, commit.project, commit), class: "ci-status ci-#{status}" do + = link_to pipelines_namespace_project_commit_path(commit.project.namespace, commit.project, commit), class: "ci-status ci-#{status}" do = ci_icon_for_status(status) = ci_label_for_status(status) diff --git a/app/views/projects/builds/_header.html.haml b/app/views/projects/builds/_header.html.haml index 057a720a54a..b15be0d861d 100644 --- a/app/views/projects/builds/_header.html.haml +++ b/app/views/projects/builds/_header.html.haml @@ -7,7 +7,7 @@ = link_to pipeline_path(@build.pipeline) do %strong ##{@build.pipeline.id} for commit - = link_to ci_status_path(@build.pipeline) do + = link_to namespace_project_commit_path(@project.namespace, @project, @build.pipeline.sha) do %strong= @build.pipeline.short_sha from = link_to namespace_project_commits_path(@project.namespace, @project, @build.ref) do diff --git a/app/views/projects/commit/_builds.html.haml b/app/views/projects/commit/_builds.html.haml deleted file mode 100644 index b7087749428..00000000000 --- a/app/views/projects/commit/_builds.html.haml +++ /dev/null @@ -1,2 +0,0 @@ -- @ci_pipelines.each do |pipeline| - = render "pipeline", pipeline: pipeline, pipeline_details: true diff --git a/app/views/projects/commit/_ci_menu.html.haml b/app/views/projects/commit/_ci_menu.html.haml index cbfd99ca448..13ab2253733 100644 --- a/app/views/projects/commit/_ci_menu.html.haml +++ b/app/views/projects/commit/_ci_menu.html.haml @@ -8,7 +8,3 @@ = link_to pipelines_namespace_project_commit_path(@project.namespace, @project, @commit.id) do Pipelines %span.badge= @ci_pipelines.count - = nav_link(path: 'commit#builds') do - = link_to builds_namespace_project_commit_path(@project.namespace, @project, @commit.id) do - Builds - %span.badge= @statuses.count diff --git a/app/views/projects/commit/builds.html.haml b/app/views/projects/commit/builds.html.haml deleted file mode 100644 index 077b2d2725b..00000000000 --- a/app/views/projects/commit/builds.html.haml +++ /dev/null @@ -1,9 +0,0 @@ -- @no_container = true -- page_title "Builds", "#{@commit.title} (#{@commit.short_id})", "Commits" -= render "projects/commits/head" - -%div{ class: container_class } - = render "commit_box" - - = render "ci_menu" - = render "builds" diff --git a/app/views/projects/merge_requests/show/_builds.html.haml b/app/views/projects/merge_requests/show/_builds.html.haml deleted file mode 100644 index 808ef7fed27..00000000000 --- a/app/views/projects/merge_requests/show/_builds.html.haml +++ /dev/null @@ -1 +0,0 @@ -= render "projects/commit/pipeline", pipeline: @pipeline, link_to_commit: true -- cgit v1.2.1 From 7086dac42fff6e32bc38b389ffa104d9c21a159c Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Tue, 29 Nov 2016 13:02:28 +0000 Subject: Changes after review Fix broken test Remove spinach tests for the builds tab --- app/controllers/projects/commit_controller.rb | 2 +- app/helpers/ci_status_helper.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb index 3a5bf7d9ff5..791ed88db30 100644 --- a/app/controllers/projects/commit_controller.rb +++ b/app/controllers/projects/commit_controller.rb @@ -8,6 +8,7 @@ class Projects::CommitController < Projects::ApplicationController # Authorize before_action :require_non_empty_project + before_action :authorize_download_code! before_action :authorize_read_pipeline!, only: [:pipelines] before_action :commit before_action :define_commit_vars, only: [:show, :diff_for_path, :pipelines] @@ -107,7 +108,6 @@ class Projects::CommitController < Projects::ApplicationController def define_status_vars @ci_pipelines = project.pipelines.where(sha: commit.sha) - @statuses = CommitStatus.where(pipeline: @ci_pipelines).relevant end def assign_change_commit_vars(mr_source_branch) diff --git a/app/helpers/ci_status_helper.rb b/app/helpers/ci_status_helper.rb index 94e91031680..94f3b480178 100644 --- a/app/helpers/ci_status_helper.rb +++ b/app/helpers/ci_status_helper.rb @@ -1,7 +1,7 @@ module CiStatusHelper def ci_status_path(pipeline) project = pipeline.project - # builds_namespace_project_commit_path(project.namespace, project, pipeline.sha) + namespace_project_pipeline_path(project.namespace, project, pipeline) end # Is used by Commit and Merge Request Widget -- cgit v1.2.1 From 5463ee66c850f5a31274a06bc27669ed127df811 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Thu, 15 Dec 2016 23:26:14 +0000 Subject: Remove builds from merge request tabs file --- app/assets/javascripts/merge_request_tabs.js | 416 --------------------- app/assets/javascripts/merge_request_tabs.js.es6 | 29 +- app/assets/javascripts/merge_request_widget.js.es6 | 1 - 3 files changed, 3 insertions(+), 443 deletions(-) delete mode 100644 app/assets/javascripts/merge_request_tabs.js (limited to 'app') diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js deleted file mode 100644 index 0fc05421d75..00000000000 --- a/app/assets/javascripts/merge_request_tabs.js +++ /dev/null @@ -1,416 +0,0 @@ -/* eslint-disable max-len, func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, no-use-before-define, no-underscore-dangle, no-undef, one-var, one-var-declaration-per-line, quotes, comma-dangle, consistent-return, prefer-template, no-param-reassign, camelcase, vars-on-top, space-in-parens, curly, prefer-arrow-callback, no-unused-vars, no-return-assign, semi, object-shorthand, operator-assignment, padded-blocks, max-len */ -// MergeRequestTabs -// -// Handles persisting and restoring the current tab selection and lazily-loading -// content on the MergeRequests#show page. -// -/*= require js.cookie */ - -// -// ### Example Markup -// -// -// -//
    -//
    -// Notes Content -//
    -//
    -// Commits Content -//
    -//
    -// Diffs Content -//
    -//
    -// -//
    -//
    -// Loading Animation -//
    -//
    -// -(function() { - var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; - - this.MergeRequestTabs = (function() { - MergeRequestTabs.prototype.diffsLoaded = false; - - MergeRequestTabs.prototype.pipelinesLoaded = false; - - MergeRequestTabs.prototype.commitsLoaded = false; - - MergeRequestTabs.prototype.fixedLayoutPref = null; - - function MergeRequestTabs(opts) { - this.opts = opts != null ? opts : {}; - this.opts.setUrl = this.opts.setUrl !== undefined ? this.opts.setUrl : true; - - this.setCurrentAction = bind(this.setCurrentAction, this); - this.tabShown = bind(this.tabShown, this); - this.showTab = bind(this.showTab, this); - // Store the `location` object, allowing for easier stubbing in tests - this._location = location; - this.bindEvents(); - this.activateTab(this.opts.action); - this.initAffix(); - } - - MergeRequestTabs.prototype.bindEvents = function() { - $(document).on('shown.bs.tab', '.merge-request-tabs a[data-toggle="tab"]', this.tabShown); - $(document).on('click', '.js-show-tab', this.showTab); - }; - - MergeRequestTabs.prototype.unbindEvents = function() { - $(document).off('shown.bs.tab', '.merge-request-tabs a[data-toggle="tab"]', this.tabShown); - $(document).off('click', '.js-show-tab', this.showTab); - }; - - MergeRequestTabs.prototype.showTab = function(event) { - event.preventDefault(); - return this.activateTab($(event.target).data('action')); - }; - - MergeRequestTabs.prototype.tabShown = function(event) { - var $target, action, navBarHeight; - $target = $(event.target); - action = $target.data('action'); - if (action === 'commits') { - this.loadCommits($target.attr('href')); - this.expandView(); - this.resetViewContainer(); - } else if (this.isDiffAction(action)) { - this.loadDiff($target.attr('href')); - if ((typeof bp !== "undefined" && bp !== null) && bp.getBreakpointSize() !== 'lg') { - this.shrinkView(); - } - if (this.diffViewType() === 'parallel') { - this.expandViewContainer(); - } - navBarHeight = $('.navbar-gitlab').outerHeight(); - $.scrollTo(".merge-request-details .merge-request-tabs", { - offset: -navBarHeight - }); - } else if (action === 'pipelines') { - this.loadPipelines($target.attr('href')); - this.expandView(); - this.resetViewContainer(); - } else { - this.expandView(); - this.resetViewContainer(); - } - if (this.opts.setUrl) { - this.setCurrentAction(action); - } - }; - - MergeRequestTabs.prototype.scrollToElement = function(container) { - var $el, navBarHeight; - if (window.location.hash) { - navBarHeight = $('.navbar-gitlab').outerHeight() + $('.layout-nav').outerHeight() + document.querySelector('.js-tabs-affix').offsetHeight; - $el = $(container + " " + window.location.hash + ":not(.match)"); - if ($el.length) { - return $.scrollTo(container + " " + window.location.hash + ":not(.match)", { - offset: -navBarHeight - }); - } - } - }; - - // Activate a tab based on the current action - MergeRequestTabs.prototype.activateTab = function(action) { - if (action === 'show') { - action = 'notes'; - } - // important note: the .tab('show') method triggers 'shown.bs.tab' event itself - $(".merge-request-tabs a[data-action='" + action + "']").tab('show'); - }; - - // Replaces the current Merge Request-specific action in the URL with a new one - // - // If the action is "notes", the URL is reset to the standard - // `MergeRequests#show` route. - // - // Examples: - // - // location.pathname # => "/namespace/project/merge_requests/1" - // setCurrentAction('diffs') - // location.pathname # => "/namespace/project/merge_requests/1/diffs" - // - // location.pathname # => "/namespace/project/merge_requests/1/diffs" - // setCurrentAction('notes') - // location.pathname # => "/namespace/project/merge_requests/1" - // - // location.pathname # => "/namespace/project/merge_requests/1/diffs" - // setCurrentAction('commits') - // location.pathname # => "/namespace/project/merge_requests/1/commits" - // - // Returns the new URL String - MergeRequestTabs.prototype.setCurrentAction = function(action) { - var new_state; - // Normalize action, just to be safe - if (action === 'show') { - action = 'notes'; - } - this.currentAction = action; - // Remove a trailing '/commits' '/diffs' '/pipelines' '/new' '/new/diffs' - new_state = this._location.pathname.replace(/\/(commits|diffs|pipelines|new|new\/diffs)(\.html)?\/?$/, ''); - - // Append the new action if we're on a tab other than 'notes' - if (action !== 'notes') { - new_state += "/" + action; - } - // Ensure parameters and hash come along for the ride - new_state += this._location.search + this._location.hash; - history.replaceState({ - turbolinks: true, - url: new_state - // Replace the current history state with the new one without breaking - // Turbolinks' history. - // - // See https://github.com/rails/turbolinks/issues/363 - }, document.title, new_state); - return new_state; - }; - - MergeRequestTabs.prototype.loadCommits = function(source) { - if (this.commitsLoaded) { - return; - } - return this._get({ - url: source + ".json", - success: (function(_this) { - return function(data) { - document.querySelector("div#commits").innerHTML = data.html; - gl.utils.localTimeAgo($('.js-timeago', 'div#commits')); - _this.commitsLoaded = true; - return _this.scrollToElement("#commits"); - }; - })(this) - }); - }; - - MergeRequestTabs.prototype.loadDiff = function(source) { - if (this.diffsLoaded) { - return; - } - - // We extract pathname for the current Changes tab anchor href - // some pages like MergeRequestsController#new has query parameters on that anchor - var url = gl.utils.parseUrl(source); - - return this._get({ - url: (url.pathname + ".json") + this._location.search, - success: (function(_this) { - return function(data) { - $('#diffs').html(data.html); - - if (typeof gl.diffNotesCompileComponents !== 'undefined') { - gl.diffNotesCompileComponents(); - } - - gl.utils.localTimeAgo($('.js-timeago', 'div#diffs')); - $('#diffs .js-syntax-highlight').syntaxHighlight(); - $('#diffs .diff-file').singleFileDiff(); - if (_this.diffViewType() === 'parallel' && (_this.isDiffAction(_this.currentAction)) ) { - _this.expandViewContainer(); - } - _this.diffsLoaded = true; - var anchoredDiff = gl.utils.getLocationHash(); - if (anchoredDiff) _this.openAnchoredDiff(anchoredDiff, function() { - _this.scrollToElement("#diffs"); - _this.highlighSelectedLine(); - }); - _this.filesCommentButton = $('.files .diff-file').filesCommentButton(); - return $(document).off('click', '.diff-line-num a').on('click', '.diff-line-num a', function(e) { - e.preventDefault(); - window.location.hash = $(e.currentTarget).attr('href'); - _this.highlighSelectedLine(); - return _this.scrollToElement("#diffs"); - }); - }; - })(this) - }); - }; - - MergeRequestTabs.prototype.openAnchoredDiff = function(anchoredDiff, cb) { - var diffTitle = $('#file-path-' + anchoredDiff); - var diffFile = diffTitle.closest('.diff-file'); - var nothingHereBlock = $('.nothing-here-block:visible', diffFile); - if (nothingHereBlock.length) { - diffFile.singleFileDiff(true, cb); - } else { - cb(); - } - }; - - MergeRequestTabs.prototype.highlighSelectedLine = function() { - var $diffLine, diffLineTop, hashClassString, locationHash, navBarHeight; - $('.hll').removeClass('hll'); - locationHash = window.location.hash; - if (locationHash !== '') { - dataLineString = '[data-line-code="' + locationHash.replace('#', '') + '"]'; - $diffLine = $(locationHash + ":not(.match)", $('#diffs')); - if (!$diffLine.is('tr')) { - $diffLine = $('#diffs').find("td" + locationHash + ", td" + dataLineString); - } else { - $diffLine = $diffLine.find('td'); - } - if ($diffLine.length) { - $diffLine.addClass('hll'); - diffLineTop = $diffLine.offset().top; - return navBarHeight = $('.navbar-gitlab').outerHeight(); - } - } - }; - - MergeRequestTabs.prototype.loadPipelines = function(source) { - if (this.pipelinesLoaded) { - return; - } - return this._get({ - url: source + ".json", - success: function(data) { - $('#pipelines').html(data.html); - gl.utils.localTimeAgo($('.js-timeago', '#pipelines')); - this.pipelinesLoaded = true; - return this.scrollToElement("#pipelines"); - }.bind(this) - }); - }; - - // Show or hide the loading spinner - // - // status - Boolean, true to show, false to hide - MergeRequestTabs.prototype.toggleLoading = function(status) { - return $('.mr-loading-status .loading').toggle(status); - }; - - MergeRequestTabs.prototype._get = function(options) { - var defaults; - defaults = { - beforeSend: (function(_this) { - return function() { - return _this.toggleLoading(true); - }; - })(this), - complete: (function(_this) { - return function() { - return _this.toggleLoading(false); - }; - })(this), - dataType: 'json', - type: 'GET' - }; - options = $.extend({}, defaults, options); - return $.ajax(options); - }; - - MergeRequestTabs.prototype.diffViewType = function() { - return $('.inline-parallel-buttons a.active').data('view-type'); - }; - - MergeRequestTabs.prototype.isDiffAction = function(action) { - return action === 'diffs' || action === 'new/diffs' - }; - - MergeRequestTabs.prototype.expandViewContainer = function() { - var $wrapper = $('.content-wrapper .container-fluid'); - if (this.fixedLayoutPref === null) { - this.fixedLayoutPref = $wrapper.hasClass('container-limited'); - } - $wrapper.removeClass('container-limited'); - }; - - MergeRequestTabs.prototype.resetViewContainer = function() { - if (this.fixedLayoutPref !== null) { - $('.content-wrapper .container-fluid') - .toggleClass('container-limited', this.fixedLayoutPref); - } - }; - - MergeRequestTabs.prototype.shrinkView = function() { - var $gutterIcon; - $gutterIcon = $('.js-sidebar-toggle i:visible'); - return setTimeout(function() { - if ($gutterIcon.is('.fa-angle-double-right')) { - return $gutterIcon.closest('a').trigger('click', [true]); - } - // Wait until listeners are set - // Only when sidebar is expanded - }, 0); - }; - - MergeRequestTabs.prototype.expandView = function() { - var $gutterIcon; - if (Cookies.get('collapsed_gutter') === 'true') { - return; - } - $gutterIcon = $('.js-sidebar-toggle i:visible'); - return setTimeout(function() { - if ($gutterIcon.is('.fa-angle-double-left')) { - return $gutterIcon.closest('a').trigger('click', [true]); - } - }, 0); - // Expand the issuable sidebar unless the user explicitly collapsed it - // Wait until listeners are set - // Only when sidebar is collapsed - }; - - MergeRequestTabs.prototype.initAffix = function () { - var $tabs = $('.js-tabs-affix'); - - // Screen space on small screens is usually very sparse - // So we dont affix the tabs on these - if (Breakpoints.get().getBreakpointSize() === 'xs' || !$tabs.length) return; - - var $diffTabs = $('#diff-notes-app'), - $fixedNav = $('.navbar-fixed-top'), - $layoutNav = $('.layout-nav'); - - $tabs.off('affix.bs.affix affix-top.bs.affix') - .affix({ - offset: { - top: function () { - var tabsTop = $diffTabs.offset().top - $tabs.height(); - tabsTop = tabsTop - ($fixedNav.height() + $layoutNav.height()); - - return tabsTop; - } - } - }).on('affix.bs.affix', function () { - $diffTabs.css({ - marginTop: $tabs.height() - }); - }).on('affix-top.bs.affix', function () { - $diffTabs.css({ - marginTop: '' - }); - }); - - // Fix bug when reloading the page already scrolling - if ($tabs.hasClass('affix')) { - $tabs.trigger('affix.bs.affix'); - } - }; - - return MergeRequestTabs; - - })(); - -}).call(this); diff --git a/app/assets/javascripts/merge_request_tabs.js.es6 b/app/assets/javascripts/merge_request_tabs.js.es6 index 3ec0f1fd613..42015a02477 100644 --- a/app/assets/javascripts/merge_request_tabs.js.es6 +++ b/app/assets/javascripts/merge_request_tabs.js.es6 @@ -59,16 +59,13 @@ class MergeRequestTabs { - constructor({ action, setUrl, buildsLoaded, stubLocation } = {}) { + constructor({ action, setUrl, stubLocation } = {}) { this.diffsLoaded = false; - this.buildsLoaded = false; this.pipelinesLoaded = false; this.commitsLoaded = false; this.fixedLayoutPref = null; this.setUrl = setUrl !== undefined ? setUrl : true; - this.buildsLoaded = buildsLoaded || false; - this.setCurrentAction = this.setCurrentAction.bind(this); this.tabShown = this.tabShown.bind(this); this.showTab = this.showTab.bind(this); @@ -119,10 +116,6 @@ $.scrollTo('.merge-request-details .merge-request-tabs', { offset: -navBarHeight, }); - } else if (action === 'builds') { - this.loadBuilds($target.attr('href')); - this.expandView(); - this.resetViewContainer(); } else if (action === 'pipelines') { this.loadPipelines($target.attr('href')); this.expandView(); @@ -180,8 +173,8 @@ setCurrentAction(action) { this.currentAction = action === 'show' ? 'notes' : action; - // Remove a trailing '/commits' '/diffs' '/builds' '/pipelines' '/new' '/new/diffs' - let newState = location.pathname.replace(/\/(commits|diffs|builds|pipelines|new|new\/diffs)(\.html)?\/?$/, ''); + // Remove a trailing '/commits' '/diffs' '/pipelines' '/new' '/new/diffs' + let newState = location.pathname.replace(/\/(commits|diffs|pipelines|new|new\/diffs)(\.html)?\/?$/, ''); // Append the new action if we're on a tab other than 'notes' if (this.currentAction !== 'notes') { @@ -255,22 +248,6 @@ }); } - loadBuilds(source) { - if (this.buildsLoaded) { - return; - } - this.ajaxGet({ - url: `${source}.json`, - success: (data) => { - document.querySelector('div#builds').innerHTML = data.html; - gl.utils.localTimeAgo($('.js-timeago', 'div#builds')); - this.buildsLoaded = true; - new gl.Pipelines(); - this.scrollToElement('#builds'); - }, - }); - } - loadPipelines(source) { if (this.pipelinesLoaded) { return; diff --git a/app/assets/javascripts/merge_request_widget.js.es6 b/app/assets/javascripts/merge_request_widget.js.es6 index bcfcf30c451..0305aeb07d9 100644 --- a/app/assets/javascripts/merge_request_widget.js.es6 +++ b/app/assets/javascripts/merge_request_widget.js.es6 @@ -45,7 +45,6 @@ $('#modal_merge_info').modal({ show: false }); - this.clearEventListeners(); this.addEventListeners(); this.getCIStatus(false); -- cgit v1.2.1 From 8db9888ffcfc98a1ceb8ea2592014522df927c4d Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 21 Dec 2016 11:18:57 +0000 Subject: Remove builds tabs --- app/assets/javascripts/dispatcher.js.es6 | 4 ---- 1 file changed, 4 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/dispatcher.js.es6 b/app/assets/javascripts/dispatcher.js.es6 index f45371f121e..14b37c6e412 100644 --- a/app/assets/javascripts/dispatcher.js.es6 +++ b/app/assets/javascripts/dispatcher.js.es6 @@ -167,9 +167,6 @@ container: '.js-pipeline-table', }); break; - case 'projects:commit:builds': - new gl.Pipelines(); - break; case 'projects:commits:show': case 'projects:activity': shortcut_handler = new ShortcutsNavigation(); @@ -186,7 +183,6 @@ container: '.js-pipeline-table', }); break; - case 'projects:pipelines:builds': case 'projects:pipelines:show': const { controllerAction } = document.querySelector('.js-pipeline-container').dataset; -- cgit v1.2.1 From 80d1ead188815282928762ddcc1bd69ed78f490f Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 21 Dec 2016 11:21:11 +0000 Subject: Resolve conflicts --- app/assets/javascripts/dispatcher.js.es6 | 1 + 1 file changed, 1 insertion(+) (limited to 'app') diff --git a/app/assets/javascripts/dispatcher.js.es6 b/app/assets/javascripts/dispatcher.js.es6 index 14b37c6e412..5245c5aa494 100644 --- a/app/assets/javascripts/dispatcher.js.es6 +++ b/app/assets/javascripts/dispatcher.js.es6 @@ -183,6 +183,7 @@ container: '.js-pipeline-table', }); break; + case 'projects:pipelines:builds': case 'projects:pipelines:show': const { controllerAction } = document.querySelector('.js-pipeline-container').dataset; -- cgit v1.2.1 From 9f47d317c547eb49c59e01f9c5a887b9ffb7f500 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 21 Dec 2016 12:25:54 +0100 Subject: Fix parentheses in pipelines.scss after a merge --- app/assets/stylesheets/pages/pipelines.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index d57f32516ac..bfcdb1f2028 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -37,6 +37,7 @@ .branch-name { max-width: 195px; } + } .pipeline-date, .pipeline-status { @@ -118,7 +119,6 @@ } .branch-commit { - .branch-name { font-weight: bold; max-width: 120px; -- cgit v1.2.1 From a713a29aadd2908c0ad7079f5b24033736a96d9c Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Mon, 19 Dec 2016 15:26:10 +0000 Subject: Fixed first newline not working --- app/assets/javascripts/lib/utils/text_utility.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/lib/utils/text_utility.js b/app/assets/javascripts/lib/utils/text_utility.js index cf286dc30ee..5066e3282d7 100644 --- a/app/assets/javascripts/lib/utils/text_utility.js +++ b/app/assets/javascripts/lib/utils/text_utility.js @@ -44,8 +44,15 @@ } }; gl.text.insertText = function(textArea, text, tag, blockTag, selected, wrap) { - var insertText, inserted, selectedSplit, startChar, removedLastNewLine; + var insertText, inserted, selectedSplit, startChar, removedLastNewLine, removedFirstNewLine; removedLastNewLine = false; + removedFirstNewLine = false; + + // Remove the first newline + if (selected.indexOf('\n') === 0) { + removedFirstNewLine = true; + selected = selected.replace(/\n+/, ''); + } // Remove the last newline if (textArea.selectionEnd - textArea.selectionStart > selected.replace(/\n$/, '').length) { @@ -72,6 +79,10 @@ insertText = "" + startChar + tag + selected + (wrap ? tag : ' '); } + if (removedFirstNewLine) { + insertText = '\n' + insertText; + } + if (removedLastNewLine) { insertText += '\n'; } -- cgit v1.2.1 From cfcefa154f4b94939dba9f3b56ff0ea001eb72c3 Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Wed, 21 Dec 2016 11:35:26 +0000 Subject: Removed hack --- app/assets/javascripts/gfm_auto_complete.js.es6 | 7 ------- 1 file changed, 7 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/gfm_auto_complete.js.es6 b/app/assets/javascripts/gfm_auto_complete.js.es6 index 17d03c87bf5..64e6258c154 100644 --- a/app/assets/javascripts/gfm_auto_complete.js.es6 +++ b/app/assets/javascripts/gfm_auto_complete.js.es6 @@ -379,14 +379,7 @@ togglePreventSelection(isPrevented = !!this.setting.tabSelectsMatch) { this.setting.tabSelectsMatch = !isPrevented; this.setting.spaceSelectsMatch = !isPrevented; - const eventListenerAction = `${isPrevented ? 'add' : 'remove'}EventListener`; - this.$inputor[0][eventListenerAction]('keydown', gl.GfmAutoComplete.preventSpaceTabEnter); }, - preventSpaceTabEnter(e) { - const key = e.which || e.keyCode; - const preventables = [9, 13, 32]; - if (preventables.indexOf(key) > -1) e.preventDefault(); - } }; }).call(this); -- cgit v1.2.1 From 6023224db1b161164a0af968b7c42066c43dfaeb Mon Sep 17 00:00:00 2001 From: Pedro Moreira da Silva Date: Wed, 21 Dec 2016 11:43:38 +0000 Subject: Simplify copy in issues empty state --- app/views/shared/empty_states/_issues.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/shared/empty_states/_issues.html.haml b/app/views/shared/empty_states/_issues.html.haml index 47379cfb4f8..b3c1128782f 100644 --- a/app/views/shared/empty_states/_issues.html.haml +++ b/app/views/shared/empty_states/_issues.html.haml @@ -13,7 +13,7 @@ The Issue Tracker is the place to add things that need to be improved or solved in a project %p Issues can be bugs, tasks or ideas to be discussed. - Besides, issues are searchable and filterable. + Also, issues are searchable and filterable. - if project_select_button = render 'shared/new_project_item_select', path: 'issues/new', label: 'New issue' - else -- cgit v1.2.1 From f93b876c6d0e580a9532b76855cba23f5fd5f3e7 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 21 Dec 2016 11:40:39 +0000 Subject: Adds CSS class to status icon on MR widget to prevent non-colored icon Adds MR id to changelor --- app/views/projects/merge_requests/widget/_heading.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/projects/merge_requests/widget/_heading.html.haml b/app/views/projects/merge_requests/widget/_heading.html.haml index 9ab7971b56c..5bc417d1760 100644 --- a/app/views/projects/merge_requests/widget/_heading.html.haml +++ b/app/views/projects/merge_requests/widget/_heading.html.haml @@ -17,7 +17,7 @@ - # TODO, remove in later versions when services like Jenkins will set CI status via Commit status API .mr-widget-heading - %w[success skipped canceled failed running pending].each do |status| - .ci_widget{class: "ci-#{status}", style: "display:none"} + .ci_widget{class: "ci-#{status} ci-status-icon-#{status}", style: "display:none"} = ci_icon_for_status(status) %span CI build -- cgit v1.2.1 From 3bbe19d39bd7f2bebb1f68de99dfb791eaa7a928 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Tue, 20 Dec 2016 17:41:09 +0100 Subject: Backport moving MR widget CI JS out of script tag. --- .../merge_request_widget/ci_bundle.js.es6 | 24 ++++++++++++++++++++++ .../merge_requests/widget/open/_accept.html.haml | 21 +++---------------- 2 files changed, 27 insertions(+), 18 deletions(-) create mode 100644 app/assets/javascripts/merge_request_widget/ci_bundle.js.es6 (limited to 'app') diff --git a/app/assets/javascripts/merge_request_widget/ci_bundle.js.es6 b/app/assets/javascripts/merge_request_widget/ci_bundle.js.es6 new file mode 100644 index 00000000000..02397561657 --- /dev/null +++ b/app/assets/javascripts/merge_request_widget/ci_bundle.js.es6 @@ -0,0 +1,24 @@ +$(() => { + /* TODO: This needs a better home, or should be refactored. It was previously contained + * in a script tag in app/views/projects/merge_requests/widget/open/_accept.html.haml, + * but Vue chokes on script tags and prevents their execution. So it was moved here + * temporarily. + * */ + + $('.accept-mr-form').on('ajax:send', () => { + $('.accept-mr-form :input').disable(); + }); + + $('.accept_merge_request').on('click', () => { + $('.js-merge-button').html(' Merge in progress'); + }); + + $('.merge_when_build_succeeds').on('click', () => { + $('#merge_when_build_succeeds').val('1'); + }); + + $('.js-merge-dropdown a').on('click', (e) => { + e.preventDefault(); + $(this).closest('form').submit(); + }); +}); diff --git a/app/views/projects/merge_requests/widget/open/_accept.html.haml b/app/views/projects/merge_requests/widget/open/_accept.html.haml index d6f7f23533c..7809e9c8c72 100644 --- a/app/views/projects/merge_requests/widget/open/_accept.html.haml +++ b/app/views/projects/merge_requests/widget/open/_accept.html.haml @@ -1,3 +1,6 @@ +- content_for :page_specific_javascripts do + = page_specific_javascript_tag('merge_request_widget/ci_bundle.js') + - status_class = @pipeline ? " ci-#{@pipeline.status}" : nil = form_for [:merge, @project.namespace.becomes(Namespace), @project, @merge_request], remote: true, method: :post, html: { class: 'accept-mr-form js-quick-submit js-requires-input' } do |f| @@ -47,21 +50,3 @@ rows: 14, hint: true = hidden_field_tag :merge_when_build_succeeds, "", autocomplete: "off" - - :javascript - $('.accept-mr-form').on('ajax:send', function() { - $(".accept-mr-form :input").disable(); - }); - - $('.accept_merge_request').on('click', function() { - $('.js-merge-button').html(" Merge in progress"); - }); - - $('.merge_when_build_succeeds').on('click', function() { - $("#merge_when_build_succeeds").val("1"); - }); - - $('.js-merge-dropdown a').on('click', function(e) { - e.preventDefault(); - $(this).closest("form").submit(); - }); -- cgit v1.2.1 From 4c3ec579e5660daab23d48bd4b3e21050735f726 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 21 Dec 2016 13:29:27 +0100 Subject: added more specs --- app/controllers/groups_controller.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app') diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index b83c3a872cf..1e499199f82 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -82,6 +82,8 @@ class GroupsController < Groups::ApplicationController if Groups::UpdateService.new(@group, current_user, group_params).execute redirect_to edit_group_path(@group), notice: "Group '#{@group.name}' was successfully updated." else + @group.reload + render action: "edit" end end -- cgit v1.2.1 From a9f85d11a584a5a9ad99aaf6366f22fd6f6d0957 Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Wed, 21 Dec 2016 11:03:52 +0000 Subject: Fix space issue and add test --- app/assets/javascripts/gfm_auto_complete.js.es6 | 6 ------ 1 file changed, 6 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/gfm_auto_complete.js.es6 b/app/assets/javascripts/gfm_auto_complete.js.es6 index 17d03c87bf5..5bfeed6f231 100644 --- a/app/assets/javascripts/gfm_auto_complete.js.es6 +++ b/app/assets/javascripts/gfm_auto_complete.js.es6 @@ -112,7 +112,6 @@ return value.path != null ? this.Emoji.template : this.Loading.template; }.bind(this), insertTpl: ':${name}:', - startWithSpace: false, skipSpecialCharacterTest: true, data: this.defaultLoadingData, callbacks: { @@ -129,7 +128,6 @@ }.bind(this), insertTpl: '${atwho-at}${username}', searchKey: 'search', - startWithSpace: false, alwaysHighlightFirst: true, skipSpecialCharacterTest: true, data: this.defaultLoadingData, @@ -172,7 +170,6 @@ }.bind(this), data: this.defaultLoadingData, insertTpl: '${atwho-at}${id}', - startWithSpace: false, callbacks: { sorter: this.DefaultOptions.sorter, filter: this.DefaultOptions.filter, @@ -200,7 +197,6 @@ displayTpl: function(value) { return value.title != null ? this.Milestones.template : this.Loading.template; }.bind(this), - startWithSpace: false, data: this.defaultLoadingData, callbacks: { matcher: this.DefaultOptions.matcher, @@ -225,7 +221,6 @@ at: '!', alias: 'mergerequests', searchKey: 'search', - startWithSpace: false, displayTpl: function(value) { return value.title != null ? this.Issues.template : this.Loading.template; }.bind(this), @@ -259,7 +254,6 @@ return this.isLoading(value) ? this.Loading.template : this.Labels.template; }.bind(this), insertTpl: '${atwho-at}${title}', - startWithSpace: false, callbacks: { matcher: this.DefaultOptions.matcher, sorter: this.DefaultOptions.sorter, -- cgit v1.2.1 From 804198ab7f1bdd854c64da729a04fc65f2b6ff7d Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Thu, 15 Dec 2016 10:07:41 -0500 Subject: Maintain milestone filter option when updating filter Setup teaspoon tests for Issuable --- app/assets/javascripts/issuable.js.es6 | 14 +++++++++----- app/views/shared/issuable/_milestone_dropdown.html.haml | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/issuable.js.es6 b/app/assets/javascripts/issuable.js.es6 index 1c10a7445bb..9c3c96c20ed 100644 --- a/app/assets/javascripts/issuable.js.es6 +++ b/app/assets/javascripts/issuable.js.es6 @@ -1,13 +1,13 @@ -/* eslint-disable func-names, no-var, camelcase, no-unused-vars, object-shorthand, space-before-function-paren, no-return-assign, comma-dangle, consistent-return, one-var, one-var-declaration-per-line, quotes, prefer-template, prefer-arrow-callback, prefer-const, padded-blocks, wrap-iife, max-len */ +/* eslint-disable no-param-reassign, func-names, no-var, camelcase, no-unused-vars, object-shorthand, space-before-function-paren, no-return-assign, comma-dangle, consistent-return, one-var, one-var-declaration-per-line, quotes, prefer-template, prefer-arrow-callback, prefer-const, padded-blocks, wrap-iife, max-len */ /* global Issuable */ /* global Turbolinks */ -(function() { +((global) => { var issuable_created; issuable_created = false; - this.Issuable = { + global.Issuable = { init: function() { Issuable.initTemplates(); Issuable.initSearch(); @@ -111,7 +111,11 @@ filterResults: (function(_this) { return function(form) { var formAction, formData, issuesUrl; - formData = form.serialize(); + formData = form.serializeArray(); + formData = formData.filter(function(data) { + return data.value !== ''; + }); + formData = $.param(formData); formAction = form.attr('action'); issuesUrl = formAction; issuesUrl += "" + (formAction.indexOf('?') < 0 ? '?' : '&'); @@ -184,4 +188,4 @@ } }; -}).call(this); +})(window); diff --git a/app/views/shared/issuable/_milestone_dropdown.html.haml b/app/views/shared/issuable/_milestone_dropdown.html.haml index 40fe53e6a8d..415361f8fbf 100644 --- a/app/views/shared/issuable/_milestone_dropdown.html.haml +++ b/app/views/shared/issuable/_milestone_dropdown.html.haml @@ -3,7 +3,7 @@ - show_menu_above = show_menu_above || false - selected_text = selected.try(:title) || params[:milestone_title] - dropdown_title = local_assigns.fetch(:dropdown_title, "Filter by milestone") -- if selected.present? +- if selected.present? || params[:milestone_title].present? = hidden_field_tag(name, name == :milestone_title ? selected_text : selected.id) = dropdown_tag(milestone_dropdown_label(selected_text), options: { title: dropdown_title, toggle_class: "js-milestone-select js-filter-submit #{extra_class}", filter: true, dropdown_class: "dropdown-menu-selectable dropdown-menu-milestone", placeholder: "Search milestones", footer_content: project.present?, data: { show_no: true, show_menu_above: show_menu_above, show_any: show_any, show_upcoming: show_upcoming, field_name: name, selected: selected.try(:title), project_id: project.try(:id), milestones: milestones_filter_dropdown_path, default_label: "Milestone" } }) do -- cgit v1.2.1 From dc303e4714b080924615ab5e61661e75fa87570c Mon Sep 17 00:00:00 2001 From: dimitrieh Date: Wed, 21 Dec 2016 13:56:10 +0100 Subject: pipeline css changes --- app/assets/stylesheets/pages/pipelines.scss | 70 ++++++++++++++++++----------- app/assets/stylesheets/pages/status.scss | 2 +- 2 files changed, 46 insertions(+), 26 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 621b780ce4d..d834bc29e8f 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -80,6 +80,10 @@ td { padding: 10px 8px; } + + .commit-link { + padding: 9px 8px 10px; + } } tbody { @@ -193,7 +197,7 @@ width: 8px; position: absolute; right: -7px; - bottom: 9px; + bottom: 10px; border-bottom: 2px solid $border-color; } } @@ -499,15 +503,10 @@ > .ci-action-icon-container { position: absolute; - right: 4px; + right: 5px; top: 5px; } - .ci-status-icon { - position: relative; - top: 1px; - } - .ci-status-icon svg { height: 20px; width: 20px; @@ -614,6 +613,10 @@ a { display: inline-block; + } + + .build-content { + width: 138px; &:hover { background-color: $stage-hover-bg; @@ -623,15 +626,24 @@ ul { max-height: 245px; overflow: auto; - margin: 5px 0; + margin: 3px 0; li { padding-top: 2px; - margin: 0 5px; + margin: 4px 7px; + padding: 0 3px; padding-left: 0; padding-bottom: 0; - margin-bottom: 0; - line-height: 1.2; + line-height: 0; + + .ci-action-icon-container:hover { + background-color: transparent; + } + + .ci-status-icon { + position: relative; + top: 2px; + } } } } @@ -680,11 +692,15 @@ .dropdown-build { color: $gl-text-color-light; + .build-content { + padding: 3px 7px 6px; + } + .ci-action-icon-container { padding: 0; font-size: 11px; float: right; - margin-top: 4px; + margin-top: 3px; display: inline-block; position: relative; @@ -694,16 +710,10 @@ } } - &:hover { - background-color: $stage-hover-bg; - border-radius: 3px; - color: $gl-text-color; - } - .ci-action-icon-container { i { - width: 25px; - height: 25px; + width: 24px; + height: 24px; &::before { top: 1px; @@ -740,6 +750,10 @@ margin: 0; } + .dropdown-build .build-content { + padding: 3px 7px 7px; + } + .builds-dropdown-loading { margin: 10px auto; width: 18px; @@ -788,19 +802,25 @@ .mini-pipeline-graph-icon-container .ci-status-icon { display: inline-block; border: 1px solid; - border-radius: 20px; + border-radius: 22px; margin-right: 1px; - width: 20px; - height: 20px; + width: 22px; + height: 22px; position: relative; z-index: 2; transition: all 0.2s cubic-bezier(0.25, 0, 1, 1); svg { top: -1px; + left: -1px; } } +.stage-cell .mini-pipeline-graph-icon-container .ci-status-icon svg { + width: 22px; + height: 22px; +} + .builds-dropdown { &:focus { outline: none; @@ -851,7 +871,7 @@ .mini-pipeline-graph-icon-container { .ci-status-icon:hover, .ci-status-icon:focus { - width: 28px; + width: 32px; padding: 0 8px 0 0; + .dropdown-caret { @@ -863,7 +883,7 @@ font-size: 11px; position: relative; top: 3px; - left: -11px; + left: -14px; margin-right: -6px; display: none; z-index: 2; diff --git a/app/assets/stylesheets/pages/status.scss b/app/assets/stylesheets/pages/status.scss index a810ed32327..4acd17360c1 100644 --- a/app/assets/stylesheets/pages/status.scss +++ b/app/assets/stylesheets/pages/status.scss @@ -1,6 +1,6 @@ .container-fluid { .ci-status { - padding: 2px 7px; + padding: 2px 7px 4px; margin-right: 10px; border: 1px solid $gray-darker; white-space: nowrap; -- cgit v1.2.1 From b902784dbff64d1f746fc38249a814debb8ed325 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 21 Dec 2016 14:21:18 +0100 Subject: fix reset path --- app/controllers/groups_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 1e499199f82..efe9c001bcf 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -82,7 +82,7 @@ class GroupsController < Groups::ApplicationController if Groups::UpdateService.new(@group, current_user, group_params).execute redirect_to edit_group_path(@group), notice: "Group '#{@group.name}' was successfully updated." else - @group.reload + @group.reset_path! render action: "edit" end -- cgit v1.2.1 From c8b16068be28699da42e1d19a02dc913071919ac Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 21 Dec 2016 14:26:47 +0100 Subject: Add specs for pipeline entity and improve factory [ci skip] --- app/models/ci/pipeline.rb | 4 +++ app/serializers/pipeline_entity.rb | 48 +++++++++++++++++++++------------- app/serializers/pipeline_serializer.rb | 16 ++++++------ 3 files changed, 42 insertions(+), 26 deletions(-) (limited to 'app') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 44b737d7a69..1814469f6ce 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -290,6 +290,10 @@ module Ci end end + def has_yaml_errors? + yaml_errors.present? + end + def environments builds.where.not(environment: nil).success.pluck(:environment).uniq end diff --git a/app/serializers/pipeline_entity.rb b/app/serializers/pipeline_entity.rb index 3ede0fb0f53..42205476478 100644 --- a/app/serializers/pipeline_entity.rb +++ b/app/serializers/pipeline_entity.rb @@ -28,12 +28,10 @@ class PipelineEntity < Grape::Entity expose :flags do expose :latest?, as: :latest expose :triggered?, as: :triggered - - expose :yaml_errors?, as: :yaml_errors do |pipeline| - pipeline.yaml_errors.present? - end - expose :stuck?, as: :stuck + expose :has_yaml_errors?, as: :yaml_errors + expose :can_retry?, as: :retryable + expose :can_cancel?, as: :cancelable end expose :ref do @@ -41,31 +39,45 @@ class PipelineEntity < Grape::Entity pipeline.ref end - expose :url do |pipeline| - namespace_project_tree_url( + expose :path do |pipeline| + namespace_project_tree_path( pipeline.project.namespace, pipeline.project, id: pipeline.ref) end - expose :tag? + expose :tag?, as: :tag + expose :branch?, as: :branch end expose :commit, using: CommitEntity + expose :yaml_errors, if: ->(pipeline, _) { pipeline.has_yaml_errors? } - expose :retry_url do |pipeline| - can?(request.user, :update_pipeline, pipeline.project) && - pipeline.retryable? && - retry_namespace_project_pipeline_path(pipeline.project.namespace, - pipeline.project, pipeline.id) + expose :retry_path, if: proc { can_retry? } do |pipeline| + retry_namespace_project_pipeline_path(pipeline.project.namespace, + pipeline.project, + pipeline.id) end - expose :cancel_url do |pipeline| - can?(request.user, :update_pipeline, pipeline.project) && - pipeline.cancelable? && - cancel_namespace_project_pipeline_path(pipeline.project.namespace, - pipeline.project, pipeline.id) + expose :cancel_path, if: proc { can_cancel? } do |pipeline| + cancel_namespace_project_pipeline_path(pipeline.project.namespace, + pipeline.project, + pipeline.id) end expose :created_at, :updated_at + + private + + alias_method :pipeline, :object + + def can_retry? + pipeline.retryable? && + can?(request.user, :update_pipeline, pipeline) + end + + def can_cancel? + pipeline.cancelable? && + can?(request.user, :update_pipeline, pipeline) + end end diff --git a/app/serializers/pipeline_serializer.rb b/app/serializers/pipeline_serializer.rb index c4ca5c40dba..76c767f82c0 100644 --- a/app/serializers/pipeline_serializer.rb +++ b/app/serializers/pipeline_serializer.rb @@ -3,14 +3,6 @@ class PipelineSerializer < BaseSerializer include API::Helpers::Pagination Struct.new('Pagination', :request, :response) - def with_pagination(request, response) - tap { @pagination = Struct::Pagination.new(request, response) } - end - - def paginate? - defined?(@pagination) - end - def represent(resource, opts = {}) if paginate? super(paginate(resource), opts) @@ -19,6 +11,14 @@ class PipelineSerializer < BaseSerializer end end + def paginate? + defined?(@pagination) + end + + def with_pagination(request, response) + tap { @pagination = Struct::Pagination.new(request, response) } + end + private # Methods needed by `API::Helpers::Pagination` -- cgit v1.2.1 From d549a9655803a5e8b90849fd4e29a6805719af3e Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 21 Dec 2016 14:47:20 +0100 Subject: Add missing specs for new pipeline related entities [ci skip] --- app/serializers/pipeline_action_entity.rb | 2 +- app/serializers/pipeline_artifact_entity.rb | 2 +- app/serializers/status_entity.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/serializers/pipeline_action_entity.rb b/app/serializers/pipeline_action_entity.rb index 475b5a55316..8ed4091b139 100644 --- a/app/serializers/pipeline_action_entity.rb +++ b/app/serializers/pipeline_action_entity.rb @@ -5,7 +5,7 @@ class PipelineActionEntity < Grape::Entity build.name.humanize end - expose :url do |build| + expose :path do |build| play_namespace_project_build_path( build.project.namespace, build.project, diff --git a/app/serializers/pipeline_artifact_entity.rb b/app/serializers/pipeline_artifact_entity.rb index 9e9f245a6f9..96f90ff9042 100644 --- a/app/serializers/pipeline_artifact_entity.rb +++ b/app/serializers/pipeline_artifact_entity.rb @@ -5,7 +5,7 @@ class PipelineArtifactEntity < Grape::Entity build.name end - expose :url do |build| + expose :path do |build| download_namespace_project_build_artifacts_path( build.project.namespace, build.project, diff --git a/app/serializers/status_entity.rb b/app/serializers/status_entity.rb index 261faa67527..47066bebfb1 100644 --- a/app/serializers/status_entity.rb +++ b/app/serializers/status_entity.rb @@ -1,7 +1,7 @@ class StatusEntity < Grape::Entity include RequestAwareEntity - expose :icon, :text, :label + expose :icon, :text, :label, :group expose :has_details?, as: :has_details expose :details_path -- cgit v1.2.1 From 02c7dcf6b2db4aca152b24a1997ceb6ec8b53e15 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 21 Dec 2016 14:51:53 +0100 Subject: Rename some pipeline and build related entities [ci skip] --- app/serializers/build_action_entity.rb | 14 ++++++++++++++ app/serializers/build_artifact_entity.rb | 14 ++++++++++++++ app/serializers/pipeline_action_entity.rb | 14 -------------- app/serializers/pipeline_artifact_entity.rb | 14 -------------- app/serializers/pipeline_entity.rb | 6 +++--- app/serializers/pipeline_stage_entity.rb | 18 ------------------ app/serializers/stage_entity.rb | 18 ++++++++++++++++++ 7 files changed, 49 insertions(+), 49 deletions(-) create mode 100644 app/serializers/build_action_entity.rb create mode 100644 app/serializers/build_artifact_entity.rb delete mode 100644 app/serializers/pipeline_action_entity.rb delete mode 100644 app/serializers/pipeline_artifact_entity.rb delete mode 100644 app/serializers/pipeline_stage_entity.rb create mode 100644 app/serializers/stage_entity.rb (limited to 'app') diff --git a/app/serializers/build_action_entity.rb b/app/serializers/build_action_entity.rb new file mode 100644 index 00000000000..3e72892d584 --- /dev/null +++ b/app/serializers/build_action_entity.rb @@ -0,0 +1,14 @@ +class BuildActionEntity < Grape::Entity + include RequestAwareEntity + + expose :name do |build| + build.name.humanize + end + + expose :path do |build| + play_namespace_project_build_path( + build.project.namespace, + build.project, + build) + end +end diff --git a/app/serializers/build_artifact_entity.rb b/app/serializers/build_artifact_entity.rb new file mode 100644 index 00000000000..8b643d8e783 --- /dev/null +++ b/app/serializers/build_artifact_entity.rb @@ -0,0 +1,14 @@ +class BuildArtifactEntity < Grape::Entity + include RequestAwareEntity + + expose :name do |build| + build.name + end + + expose :path do |build| + download_namespace_project_build_artifacts_path( + build.project.namespace, + build.project, + build) + end +end diff --git a/app/serializers/pipeline_action_entity.rb b/app/serializers/pipeline_action_entity.rb deleted file mode 100644 index 8ed4091b139..00000000000 --- a/app/serializers/pipeline_action_entity.rb +++ /dev/null @@ -1,14 +0,0 @@ -class PipelineActionEntity < Grape::Entity - include RequestAwareEntity - - expose :name do |build| - build.name.humanize - end - - expose :path do |build| - play_namespace_project_build_path( - build.project.namespace, - build.project, - build) - end -end diff --git a/app/serializers/pipeline_artifact_entity.rb b/app/serializers/pipeline_artifact_entity.rb deleted file mode 100644 index 96f90ff9042..00000000000 --- a/app/serializers/pipeline_artifact_entity.rb +++ /dev/null @@ -1,14 +0,0 @@ -class PipelineArtifactEntity < Grape::Entity - include RequestAwareEntity - - expose :name do |build| - build.name - end - - expose :path do |build| - download_namespace_project_build_artifacts_path( - build.project.namespace, - build.project, - build) - end -end diff --git a/app/serializers/pipeline_entity.rb b/app/serializers/pipeline_entity.rb index 42205476478..d04a4990cb0 100644 --- a/app/serializers/pipeline_entity.rb +++ b/app/serializers/pipeline_entity.rb @@ -20,9 +20,9 @@ class PipelineEntity < Grape::Entity expose :duration expose :finished_at - expose :stages, using: PipelineStageEntity - expose :artifacts, using: PipelineArtifactEntity - expose :manual_actions, using: PipelineActionEntity + expose :stages, using: StageEntity + expose :artifacts, using: BuildArtifactEntity + expose :manual_actions, using: BuildActionEntity end expose :flags do diff --git a/app/serializers/pipeline_stage_entity.rb b/app/serializers/pipeline_stage_entity.rb deleted file mode 100644 index 5ef39bafdc1..00000000000 --- a/app/serializers/pipeline_stage_entity.rb +++ /dev/null @@ -1,18 +0,0 @@ -class PipelineStageEntity < Grape::Entity - include RequestAwareEntity - - expose :name - expose :status do |stage, options| - StatusEntity.represent( - stage.detailed_status(request.user), - options) - end - - expose :path do |stage| - namespace_project_pipeline_path( - stage.pipeline.project.namespace, - stage.pipeline.project, - stage.pipeline.id, - anchor: stage.name) - end -end diff --git a/app/serializers/stage_entity.rb b/app/serializers/stage_entity.rb new file mode 100644 index 00000000000..31116988320 --- /dev/null +++ b/app/serializers/stage_entity.rb @@ -0,0 +1,18 @@ +class StageEntity < Grape::Entity + include RequestAwareEntity + + expose :name + expose :status do |stage, options| + StatusEntity.represent( + stage.detailed_status(request.user), + options) + end + + expose :path do |stage| + namespace_project_pipeline_path( + stage.pipeline.project.namespace, + stage.pipeline.project, + stage.pipeline.id, + anchor: stage.name) + end +end -- cgit v1.2.1 From e072a2740e4b4112830f16f061704a88d5a9cabb Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 21 Dec 2016 15:31:49 +0100 Subject: Add missing specs for request aware entity module [ci skip] --- app/serializers/request_aware_entity.rb | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'app') diff --git a/app/serializers/request_aware_entity.rb b/app/serializers/request_aware_entity.rb index e159d750cb7..3039014aaaa 100644 --- a/app/serializers/request_aware_entity.rb +++ b/app/serializers/request_aware_entity.rb @@ -2,14 +2,11 @@ module RequestAwareEntity extend ActiveSupport::Concern included do - include Gitlab::Routing.url_helpers + include Gitlab::Routing + include Gitlab::Allowable end def request - @options.fetch(:request) - end - - def can?(object, action, subject) - Ability.allowed?(object, action, subject) + options.fetch(:request) end end -- cgit v1.2.1 From 5a4b3e8e302eaa263203d84e93862a89b5e90d90 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Wed, 21 Dec 2016 08:25:59 -0600 Subject: Increase code line height and decrease empty diff font size --- app/assets/stylesheets/framework/blocks.scss | 2 +- app/assets/stylesheets/framework/variables.scss | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/blocks.scss b/app/assets/stylesheets/framework/blocks.scss index 9f02749f5ab..e9aadffc73c 100644 --- a/app/assets/stylesheets/framework/blocks.scss +++ b/app/assets/stylesheets/framework/blocks.scss @@ -9,7 +9,7 @@ padding: 20px; color: $gl-gray; font-weight: normal; - font-size: 16px; + font-size: 14px; line-height: 36px; &.diff-collapsed { diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index d85d3f968d3..fcf7b8c2d36 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -134,7 +134,7 @@ $md-area-border: #ddd; * Code */ $code_font_size: 12px; -$code_line_height: 1.5; +$code_line_height: 1.6; /* * Padding -- cgit v1.2.1 From 2bb49182fe5037f262ff26251461be5d5fed6441 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 21 Dec 2016 15:47:03 +0100 Subject: Add missing specs for CI pipeline stage entity [ci skip] --- app/serializers/stage_entity.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'app') diff --git a/app/serializers/stage_entity.rb b/app/serializers/stage_entity.rb index 31116988320..b57202a6267 100644 --- a/app/serializers/stage_entity.rb +++ b/app/serializers/stage_entity.rb @@ -2,6 +2,7 @@ class StageEntity < Grape::Entity include RequestAwareEntity expose :name + expose :status do |stage, options| StatusEntity.represent( stage.detailed_status(request.user), -- cgit v1.2.1 From e1bf40e293409d974a8013685ec544c0f633ef16 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 21 Dec 2016 16:43:27 +0200 Subject: Whitelist next project names: help, ci, admin, search Signed-off-by: Dmitriy Zaporozhets --- app/validators/project_path_validator.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/validators/project_path_validator.rb b/app/validators/project_path_validator.rb index d9ab8f167d8..79b2c99fd70 100644 --- a/app/validators/project_path_validator.rb +++ b/app/validators/project_path_validator.rb @@ -15,7 +15,7 @@ class ProjectPathValidator < ActiveModel::EachValidator # 'tree' as project name and 'deploy_keys' as route. # RESERVED = (NamespaceValidator::RESERVED - - %w[dashboard] + + %w[dashboard help ci admin search] + %w[tree commits wikis new edit create update logs_tree preview blob blame raw files create_dir find_file]).freeze -- cgit v1.2.1 From 9809a9af8a3980f8a65262295cfd9701e793ac11 Mon Sep 17 00:00:00 2001 From: Adam Niedzielski Date: Wed, 21 Dec 2016 16:21:55 +0100 Subject: Introduce "Set up autodeploy" button to help configure GitLab CI for deployment The button allows to choose a ".gitlab-ci.yml" template that automatically sets up the deployment of an application. The currently supported template is Kubernetes template. --- app/helpers/blob_helper.rb | 2 +- app/helpers/projects_helper.rb | 6 ++++-- app/views/projects/show.html.haml | 4 ++++ 3 files changed, 9 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb index f31d4fb897d..c3508443d8a 100644 --- a/app/helpers/blob_helper.rb +++ b/app/helpers/blob_helper.rb @@ -188,7 +188,7 @@ module BlobHelper end def gitlab_ci_ymls - @gitlab_ci_ymls ||= Gitlab::Template::GitlabCiYmlTemplate.dropdown_names + @gitlab_ci_ymls ||= Gitlab::Template::GitlabCiYmlTemplate.dropdown_names(params[:context]) end def dockerfile_names diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index d2177f683a1..7445f3c113c 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -280,13 +280,15 @@ module ProjectsHelper end end - def add_special_file_path(project, file_name:, commit_message: nil) + def add_special_file_path(project, file_name:, commit_message: nil, target_branch: nil, context: nil) namespace_project_new_blob_path( project.namespace, project, project.default_branch || 'master', file_name: file_name, - commit_message: commit_message || "Add #{file_name.downcase}" + commit_message: commit_message || "Add #{file_name.downcase}", + target_branch: target_branch, + context: context ) end diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index 8a214e1de58..a915c159cb4 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -68,6 +68,10 @@ - if koding_enabled? && @repository.koding_yml.blank? %li.missing = link_to 'Set up Koding', add_koding_stack_path(@project) + - if @repository.gitlab_ci_yml.blank? && @project.deployment_service.present? + %li.missing + = link_to add_special_file_path(@project, file_name: '.gitlab-ci.yml', commit_message: 'Set up autodeploy', target_branch: 'autodeploy', context: 'autodeploy') do + Set up autodeploy - if @repository.commit .project-last-commit{ class: container_class } -- cgit v1.2.1 From b8d8fd70d53a90fba6631d9cce573fcfdc24a270 Mon Sep 17 00:00:00 2001 From: Markus Koller Date: Sat, 3 Dec 2016 16:59:24 +0100 Subject: Remove unused ProjectsHelper#round_commit_count --- app/helpers/projects_helper.rb | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'app') diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index d2177f683a1..9c9e38c4ed7 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -396,20 +396,6 @@ module ProjectsHelper [@project.path_with_namespace, sha, "readme"].join('-') end - def round_commit_count(project) - count = project.commit_count - - if count > 10000 - '10000+' - elsif count > 5000 - '5000+' - elsif count > 1000 - '1000+' - else - count - end - end - def current_ref @ref || @repository.try(:root_ref) end -- cgit v1.2.1 From 3ef4f74b1acc9399db320b53dffc592542de0126 Mon Sep 17 00:00:00 2001 From: Markus Koller Date: Tue, 22 Nov 2016 17:58:10 +0100 Subject: Add more storage statistics This adds counters for build artifacts and LFS objects, and moves the preexisting repository_size and commit_count from the projects table into a new project_statistics table. The counters are displayed in the administration area for projects and groups, and also available through the API for admins (on */all) and normal users (on */owned) The statistics are updated through ProjectCacheWorker, which can now do more granular updates with the new :statistics argument. --- app/controllers/admin/groups_controller.rb | 7 +++-- app/controllers/admin/projects_controller.rb | 2 +- app/controllers/groups_controller.rb | 2 +- app/helpers/projects_helper.rb | 5 ---- app/helpers/sorting_helper.rb | 11 ++++++- app/helpers/storage_helper.rb | 7 +++++ app/models/ci/build.rb | 6 ++++ app/models/group.rb | 8 +++++- app/models/lfs_objects_project.rb | 9 ++++++ app/models/namespace.rb | 13 +++++++++ app/models/project.rb | 22 +++++++------- app/models/project_statistics.rb | 43 ++++++++++++++++++++++++++++ app/services/git_push_service.rb | 2 +- app/services/git_tag_push_service.rb | 2 +- app/views/admin/groups/_group.html.haml | 3 ++ app/views/admin/groups/index.html.haml | 2 ++ app/views/admin/groups/show.html.haml | 20 ++++++++++--- app/views/admin/projects/index.html.haml | 4 +-- app/views/admin/projects/show.html.haml | 13 +++++++-- app/views/groups/projects.html.haml | 4 +-- app/views/projects/show.html.haml | 4 +-- app/workers/project_cache_worker.rb | 23 ++++++++------- 22 files changed, 164 insertions(+), 48 deletions(-) create mode 100644 app/helpers/storage_helper.rb create mode 100644 app/models/project_statistics.rb (limited to 'app') diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb index 1e3d194e9f9..61a3a03182a 100644 --- a/app/controllers/admin/groups_controller.rb +++ b/app/controllers/admin/groups_controller.rb @@ -1,17 +1,18 @@ class Admin::GroupsController < Admin::ApplicationController - before_action :group, only: [:edit, :show, :update, :destroy, :project_update, :members_update] + before_action :group, only: [:edit, :update, :destroy, :project_update, :members_update] def index - @groups = Group.all + @groups = Group.with_statistics @groups = @groups.sort(@sort = params[:sort]) @groups = @groups.search(params[:name]) if params[:name].present? @groups = @groups.page(params[:page]) end def show + @group = Group.with_statistics.find_by_full_path(params[:id]) @members = @group.members.order("access_level DESC").page(params[:members_page]) @requesters = AccessRequestsFinder.new(@group).execute(current_user) - @projects = @group.projects.page(params[:projects_page]) + @projects = @group.projects.with_statistics.page(params[:projects_page]) end def new diff --git a/app/controllers/admin/projects_controller.rb b/app/controllers/admin/projects_controller.rb index 1d963bdf7d5..b09ae423096 100644 --- a/app/controllers/admin/projects_controller.rb +++ b/app/controllers/admin/projects_controller.rb @@ -3,7 +3,7 @@ class Admin::ProjectsController < Admin::ApplicationController before_action :group, only: [:show, :transfer] def index - @projects = Project.all + @projects = Project.with_statistics @projects = @projects.in_namespace(params[:namespace_id]) if params[:namespace_id].present? @projects = @projects.where(visibility_level: params[:visibility_level]) if params[:visibility_level].present? @projects = @projects.with_push if params[:with_push].present? diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index efe9c001bcf..01c8fa2739f 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -75,7 +75,7 @@ class GroupsController < Groups::ApplicationController end def projects - @projects = @group.projects.page(params[:page]) + @projects = @group.projects.with_statistics.page(params[:page]) end def update diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 9c9e38c4ed7..fc9eccd2942 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -246,11 +246,6 @@ module ProjectsHelper end end - def repository_size(project = @project) - size_in_bytes = project.repository_size * 1.megabyte - number_to_human_size(size_in_bytes, delimiter: ',', precision: 2) - end - def default_url_to_repo(project = @project) case default_clone_protocol when 'ssh' diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb index f03c4627050..ff787fb4131 100644 --- a/app/helpers/sorting_helper.rb +++ b/app/helpers/sorting_helper.rb @@ -11,6 +11,7 @@ module SortingHelper sort_value_due_date_soon => sort_title_due_date_soon, sort_value_due_date_later => sort_title_due_date_later, sort_value_largest_repo => sort_title_largest_repo, + sort_value_largest_group => sort_title_largest_group, sort_value_recently_signin => sort_title_recently_signin, sort_value_oldest_signin => sort_title_oldest_signin, sort_value_downvotes => sort_title_downvotes, @@ -92,6 +93,10 @@ module SortingHelper 'Largest repository' end + def sort_title_largest_group + 'Largest group' + end + def sort_title_recently_signin 'Recent sign in' end @@ -193,7 +198,11 @@ module SortingHelper end def sort_value_largest_repo - 'repository_size_desc' + 'storage_size_desc' + end + + def sort_value_largest_group + 'storage_size_desc' end def sort_value_recently_signin diff --git a/app/helpers/storage_helper.rb b/app/helpers/storage_helper.rb new file mode 100644 index 00000000000..e19c67a37ca --- /dev/null +++ b/app/helpers/storage_helper.rb @@ -0,0 +1,7 @@ +module StorageHelper + def storage_counter(size_in_bytes) + precision = size_in_bytes < 1.megabyte ? 0 : 1 + + number_to_human_size(size_in_bytes, delimiter: ',', precision: precision, significant: false) + end +end diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index cb76cdf5981..27042798741 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -43,6 +43,8 @@ module Ci before_destroy { project } after_create :execute_hooks + after_save :update_project_statistics, if: :artifacts_size_changed? + after_destroy :update_project_statistics class << self def first_pending @@ -584,5 +586,9 @@ module Ci Ci::MaskSecret.mask!(trace, token) trace end + + def update_project_statistics + ProjectCacheWorker.perform_async(project_id, [], [:build_artifacts_size]) + end end end diff --git a/app/models/group.rb b/app/models/group.rb index ac8a82c8c1e..85696ad9747 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -48,7 +48,13 @@ class Group < Namespace end def sort(method) - order_by(method) + if method == 'storage_size_desc' + # storage_size is a virtual column so we need to + # pass a string to avoid AR adding the table name + reorder('storage_size DESC, namespaces.id DESC') + else + order_by(method) + end end def reference_prefix diff --git a/app/models/lfs_objects_project.rb b/app/models/lfs_objects_project.rb index 0fd5f089db9..007eed5600a 100644 --- a/app/models/lfs_objects_project.rb +++ b/app/models/lfs_objects_project.rb @@ -5,4 +5,13 @@ class LfsObjectsProject < ActiveRecord::Base validates :lfs_object_id, presence: true validates :lfs_object_id, uniqueness: { scope: [:project_id], message: "already exists in project" } validates :project_id, presence: true + + after_create :update_project_statistics + after_destroy :update_project_statistics + + private + + def update_project_statistics + ProjectCacheWorker.perform_async(project_id, [], [:lfs_objects_size]) + end end diff --git a/app/models/namespace.rb b/app/models/namespace.rb index b52f08c7081..d41833de66f 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -9,6 +9,7 @@ class Namespace < ActiveRecord::Base cache_markdown_field :description, pipeline: :description has_many :projects, dependent: :destroy + has_many :project_statistics belongs_to :owner, class_name: "User" belongs_to :parent, class_name: "Namespace" @@ -38,6 +39,18 @@ class Namespace < ActiveRecord::Base scope :root, -> { where('type IS NULL') } + scope :with_statistics, -> do + joins('LEFT JOIN project_statistics ps ON ps.namespace_id = namespaces.id') + .group('namespaces.id') + .select( + 'namespaces.*', + 'COALESCE(SUM(ps.storage_size), 0) AS storage_size', + 'COALESCE(SUM(ps.repository_size), 0) AS repository_size', + 'COALESCE(SUM(ps.lfs_objects_size), 0) AS lfs_objects_size', + 'COALESCE(SUM(ps.build_artifacts_size), 0) AS build_artifacts_size', + ) + end + class << self def by_path(path) find_by('lower(path) = :value', value: path.downcase) diff --git a/app/models/project.rb b/app/models/project.rb index 26fa20f856d..19bbe65b01d 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -44,6 +44,7 @@ class Project < ActiveRecord::Base after_create :ensure_dir_exist after_create :create_project_feature, unless: :project_feature after_save :ensure_dir_exist, if: :namespace_id_changed? + after_save :update_project_statistics, if: :namespace_id_changed? # set last_activity_at to the same as created_at after_create :set_last_activity_at @@ -151,6 +152,7 @@ class Project < ActiveRecord::Base has_one :import_data, dependent: :destroy, class_name: "ProjectImportData" has_one :project_feature, dependent: :destroy + has_one :statistics, class_name: 'ProjectStatistics', dependent: :delete has_many :commit_statuses, dependent: :destroy, foreign_key: :gl_project_id has_many :pipelines, dependent: :destroy, class_name: 'Ci::Pipeline', foreign_key: :gl_project_id @@ -220,6 +222,7 @@ class Project < ActiveRecord::Base scope :with_push, -> { joins(:events).where('events.action = ?', Event::PUSHED) } scope :with_project_feature, -> { joins('LEFT JOIN project_features ON projects.id = project_features.project_id') } + scope :with_statistics, -> { includes(:statistics) } # "enabled" here means "not disabled". It includes private features! scope :with_feature_enabled, ->(feature) { @@ -332,8 +335,10 @@ class Project < ActiveRecord::Base end def sort(method) - if method == 'repository_size_desc' - reorder(repository_size: :desc, id: :desc) + if method == 'storage_size_desc' + # storage_size is a joined column so we need to + # pass a string to avoid AR adding the table name + reorder('project_statistics.storage_size DESC, projects.id DESC') else order_by(method) end @@ -1036,14 +1041,6 @@ class Project < ActiveRecord::Base forked? && project == forked_from_project end - def update_repository_size - update_attribute(:repository_size, repository.size) - end - - def update_commit_count - update_attribute(:commit_count, repository.commit_count) - end - def forks_count forks.count end @@ -1322,4 +1319,9 @@ class Project < ActiveRecord::Base def full_path_changed? path_changed? || namespace_id_changed? end + + def update_project_statistics + stats = statistics || build_statistics + stats.update(namespace_id: namespace_id) + end end diff --git a/app/models/project_statistics.rb b/app/models/project_statistics.rb new file mode 100644 index 00000000000..2270ac75071 --- /dev/null +++ b/app/models/project_statistics.rb @@ -0,0 +1,43 @@ +class ProjectStatistics < ActiveRecord::Base + belongs_to :project + belongs_to :namespace + + before_save :update_storage_size + + STORAGE_COLUMNS = [:repository_size, :lfs_objects_size, :build_artifacts_size] + STATISTICS_COLUMNS = [:commit_count] + STORAGE_COLUMNS + + def total_repository_size + repository_size + lfs_objects_size + end + + def refresh!(only: nil) + STATISTICS_COLUMNS.each do |column, generator| + if only.blank? || only.include?(column) + public_send("update_#{column}") + end + end + + save! + end + + def update_commit_count + self.commit_count = project.repository.commit_count + end + + def update_repository_size + self.repository_size = project.repository.size + end + + def update_lfs_objects_size + self.lfs_objects_size = project.lfs_objects.sum(:size) + end + + def update_build_artifacts_size + self.build_artifacts_size = project.builds.sum(:artifacts_size) + end + + def update_storage_size + self.storage_size = STORAGE_COLUMNS.sum(&method(:read_attribute)) + end +end diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb index 185556c12cc..f603036cf03 100644 --- a/app/services/git_push_service.rb +++ b/app/services/git_push_service.rb @@ -74,7 +74,7 @@ class GitPushService < BaseService types = [] end - ProjectCacheWorker.perform_async(@project.id, types) + ProjectCacheWorker.perform_async(@project.id, types, [:commit_count, :repository_size]) end protected diff --git a/app/services/git_tag_push_service.rb b/app/services/git_tag_push_service.rb index 20a4445bddf..96432837481 100644 --- a/app/services/git_tag_push_service.rb +++ b/app/services/git_tag_push_service.rb @@ -12,7 +12,7 @@ class GitTagPushService < BaseService project.execute_hooks(@push_data.dup, :tag_push_hooks) project.execute_services(@push_data.dup, :tag_push_hooks) Ci::CreatePipelineService.new(project, current_user, @push_data).execute - ProjectCacheWorker.perform_async(project.id) + ProjectCacheWorker.perform_async(project.id, [], [:commit_count, :repository_size]) true end diff --git a/app/views/admin/groups/_group.html.haml b/app/views/admin/groups/_group.html.haml index cf28f92853e..6fc212119c4 100644 --- a/app/views/admin/groups/_group.html.haml +++ b/app/views/admin/groups/_group.html.haml @@ -5,6 +5,9 @@ = link_to 'Edit', admin_group_edit_path(group), id: "edit_#{dom_id(group)}", class: 'btn' = link_to 'Delete', [:admin, group], data: { confirm: "Are you sure you want to remove #{group.name}?" }, method: :delete, class: 'btn btn-remove' .stats + %span.badge + = storage_counter(group.storage_size) + %span = icon('bookmark') = number_with_delimiter(group.projects.count) diff --git a/app/views/admin/groups/index.html.haml b/app/views/admin/groups/index.html.haml index 794f910a61f..07775247cfd 100644 --- a/app/views/admin/groups/index.html.haml +++ b/app/views/admin/groups/index.html.haml @@ -27,6 +27,8 @@ = sort_title_recently_updated = link_to admin_groups_path(sort: sort_value_oldest_updated, name: project_name) do = sort_title_oldest_updated + = link_to admin_groups_path(sort: sort_value_largest_group, name: project_name) do + = sort_title_largest_group = link_to new_admin_group_path, class: "btn btn-new" do New Group %ul.content-list diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml index 7b0175af214..ab9c79f6add 100644 --- a/app/views/admin/groups/show.html.haml +++ b/app/views/admin/groups/show.html.haml @@ -38,6 +38,18 @@ %strong = @group.created_at.to_s(:medium) + %li + %span.light Storage: + %strong= storage_counter(@group.storage_size) + ( + = storage_counter(@group.repository_size) + repositories, + = storage_counter(@group.build_artifacts_size) + build artifacts, + = storage_counter(@group.lfs_objects_size) + LFS + ) + %li %span.light Group Git LFS status: %strong @@ -55,8 +67,8 @@ %li %strong = link_to project.name_with_namespace, [:admin, project.namespace.becomes(Namespace), project] - %span.label.label-gray - = repository_size(project) + %span.badge + = storage_counter(project.statistics.storage_size) %span.pull-right.light %span.monospace= project.path_with_namespace + ".git" .panel-footer @@ -73,8 +85,8 @@ %li %strong = link_to project.name_with_namespace, [:admin, project.namespace.becomes(Namespace), project] - %span.label.label-gray - = repository_size(project) + %span.badge + = storage_counter(project.statistics.storage_size) %span.pull-right.light %span.monospace= project.path_with_namespace + ".git" diff --git a/app/views/admin/projects/index.html.haml b/app/views/admin/projects/index.html.haml index 8bc7dc7dd51..2e6f03fcde0 100644 --- a/app/views/admin/projects/index.html.haml +++ b/app/views/admin/projects/index.html.haml @@ -69,8 +69,8 @@ .controls - if project.archived %span.label.label-warning archived - %span.label.label-gray - = repository_size(project) + %span.badge + = storage_counter(project.statistics.storage_size) = link_to 'Edit', edit_namespace_project_path(project.namespace, project), id: "edit_#{dom_id(project)}", class: "btn" = link_to 'Delete', [project.namespace.becomes(Namespace), project], data: { confirm: remove_project_message(project) }, method: :delete, class: "btn btn-remove" .title diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml index 6c7c3c48604..2967da6e692 100644 --- a/app/views/admin/projects/show.html.haml +++ b/app/views/admin/projects/show.html.haml @@ -65,9 +65,16 @@ = @project.repository.path_to_repo %li - %span.light Size - %strong - = repository_size(@project) + %span.light Storage: + %strong= storage_counter(@project.statistics.storage_size) + ( + = storage_counter(@project.statistics.repository_size) + repository, + = storage_counter(@project.statistics.build_artifacts_size) + build artifacts, + = storage_counter(@project.statistics.lfs_objects_size) + LFS + ) %li %span.light last commit: diff --git a/app/views/groups/projects.html.haml b/app/views/groups/projects.html.haml index 33fee334d93..2e7e5e5c309 100644 --- a/app/views/groups/projects.html.haml +++ b/app/views/groups/projects.html.haml @@ -18,8 +18,8 @@ .pull-right - if project.archived %span.label.label-warning archived - %span.label.label-gray - = repository_size(project) + %span.badge + = storage_counter(project.statistics.storage_size) = link_to 'Members', namespace_project_project_members_path(project.namespace, project), id: "edit_#{dom_id(project)}", class: "btn btn-sm" = link_to 'Edit', edit_namespace_project_path(project.namespace, project), id: "edit_#{dom_id(project)}", class: "btn btn-sm" = link_to 'Remove', project, data: { confirm: remove_project_message(project)}, method: :delete, class: "btn btn-sm btn-remove" diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index 8a214e1de58..eb31fe430b6 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -17,10 +17,10 @@ %ul.nav %li = link_to project_files_path(@project) do - Files (#{repository_size}) + Files (#{storage_counter(@project.statistics.total_repository_size)}) %li = link_to namespace_project_commits_path(@project.namespace, @project, current_ref) do - #{'Commit'.pluralize(@project.commit_count)} (#{number_with_delimiter(@project.commit_count)}) + #{'Commit'.pluralize(@project.statistics.commit_count)} (#{number_with_delimiter(@project.statistics.commit_count)}) %li = link_to namespace_project_branches_path(@project.namespace, @project) do #{'Branch'.pluralize(@repository.branch_count)} (#{number_with_delimiter(@repository.branch_count)}) diff --git a/app/workers/project_cache_worker.rb b/app/workers/project_cache_worker.rb index 27d7e652721..8ff9d07860f 100644 --- a/app/workers/project_cache_worker.rb +++ b/app/workers/project_cache_worker.rb @@ -6,26 +6,27 @@ class ProjectCacheWorker LEASE_TIMEOUT = 15.minutes.to_i # project_id - The ID of the project for which to flush the cache. - # refresh - An Array containing extra types of data to refresh such as - # `:readme` to flush the README and `:changelog` to flush the - # CHANGELOG. - def perform(project_id, refresh = []) + # files - An Array containing extra types of files to refresh such as + # `:readme` to flush the README and `:changelog` to flush the + # CHANGELOG. + # statistics - An Array containing columns from ProjectStatistics to + # refresh, if empty all columns will be refreshed + def perform(project_id, files = [], statistics = []) project = Project.find_by(id: project_id) return unless project && project.repository.exists? - update_repository_size(project) - project.update_commit_count + update_statistics(project, statistics.map(&:to_sym)) - project.repository.refresh_method_caches(refresh.map(&:to_sym)) + project.repository.refresh_method_caches(files.map(&:to_sym)) end - def update_repository_size(project) - return unless try_obtain_lease_for(project.id, :update_repository_size) + def update_statistics(project, statistics = []) + return unless try_obtain_lease_for(project.id, :update_statistics) - Rails.logger.info("Updating repository size for project #{project.id}") + Rails.logger.info("Updating statistics for project #{project.id}") - project.update_repository_size + project.statistics.refresh!(only: statistics) end private -- cgit v1.2.1 From d8740cfe19ea033a119cb4530aeb41fcec4bafca Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Wed, 21 Dec 2016 17:30:29 +0100 Subject: Move javascript for widget check to ci_bundle. --- .../merge_request_widget/ci_bundle.js.es6 | 56 ++++++++++++++-------- .../merge_requests/widget/open/_check.html.haml | 9 ++-- 2 files changed, 40 insertions(+), 25 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/merge_request_widget/ci_bundle.js.es6 b/app/assets/javascripts/merge_request_widget/ci_bundle.js.es6 index 02397561657..2b074994b4a 100644 --- a/app/assets/javascripts/merge_request_widget/ci_bundle.js.es6 +++ b/app/assets/javascripts/merge_request_widget/ci_bundle.js.es6 @@ -1,24 +1,42 @@ -$(() => { - /* TODO: This needs a better home, or should be refactored. It was previously contained - * in a script tag in app/views/projects/merge_requests/widget/open/_accept.html.haml, - * but Vue chokes on script tags and prevents their execution. So it was moved here - * temporarily. - * */ +/* global merge_request_widget */ - $('.accept-mr-form').on('ajax:send', () => { - $('.accept-mr-form :input').disable(); - }); +(() => { + $(() => { + /* TODO: This needs a better home, or should be refactored. It was previously contained + * in a script tag in app/views/projects/merge_requests/widget/open/_accept.html.haml, + * but Vue chokes on script tags and prevents their execution. So it was moved here + * temporarily. + * */ - $('.accept_merge_request').on('click', () => { - $('.js-merge-button').html(' Merge in progress'); - }); + if ($('.accept-mr-form').length) { + $('.accept-mr-form').on('ajax:send', () => { + $('.accept-mr-form :input').disable(); + }); - $('.merge_when_build_succeeds').on('click', () => { - $('#merge_when_build_succeeds').val('1'); - }); + $('.accept_merge_request').on('click', () => { + $('.js-merge-button').html(' Merge in progress'); + }); + + $('.merge_when_build_succeeds').on('click', () => { + $('#merge_when_build_succeeds').val('1'); + }); + + $('.js-merge-dropdown a').on('click', (e) => { + e.preventDefault(); + $(this).closest('form').submit(); + }); + } else if ($('.rebase-in-progress').length) { + merge_request_widget.rebaseInProgress(); + } else if ($('.rebase-mr-form').length) { + $('.rebase-mr-form').on('ajax:send', () => { + $('.rebase-mr-form :input').disable(); + }); - $('.js-merge-dropdown a').on('click', (e) => { - e.preventDefault(); - $(this).closest('form').submit(); + $('.js-rebase-button').on('click', () => { + $('.js-rebase-button').html(" Rebase in progress"); + }); + } else { + merge_request_widget.getMergeStatus(); + } }); -}); +})(); diff --git a/app/views/projects/merge_requests/widget/open/_check.html.haml b/app/views/projects/merge_requests/widget/open/_check.html.haml index e16878ba513..50086767446 100644 --- a/app/views/projects/merge_requests/widget/open/_check.html.haml +++ b/app/views/projects/merge_requests/widget/open/_check.html.haml @@ -1,9 +1,6 @@ +- content_for :page_specific_javascripts do + = page_specific_javascript_tag('merge_request_widget/ci_bundle.js') + %strong = icon("spinner spin") Checking ability to merge automatically… - -:javascript - $(function() { - merge_request_widget.getMergeStatus(); - }); - -- cgit v1.2.1 From 3d0074a6edc22eb6840bad639c8f4fde6be89293 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 21 Dec 2016 12:20:18 +0000 Subject: Adds background color for disabled state to merge when succeeds dropdown Adds MR id to changelog entry Fix caret color Remove duplicated semicolon --- app/assets/stylesheets/pages/merge_requests.scss | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'app') diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index e779e65eca3..394980704ae 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -21,6 +21,14 @@ display: inline-block; float: left; + .btn-success.dropdown-toggle .fa { + color: inherit; + } + + .btn-success.dropdown-toggle:disabled { + background-color: $gl-success; + } + .accept_merge_request { &.ci-pending, &.ci-running { -- cgit v1.2.1 From fd4e9c53ddc5c1c1ae98794937d479407511b0a3 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 21 Dec 2016 17:41:41 +0000 Subject: Use same font size for all items in issue title --- app/assets/stylesheets/pages/issuable.scss | 1 + 1 file changed, 1 insertion(+) (limited to 'app') diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 4fac0cfb0ba..eeb5b590625 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -434,6 +434,7 @@ .issuable-meta { display: inline-block; line-height: 18px; + font-size: 14px; } .js-issuable-selector-wrap { -- cgit v1.2.1 From 52f255eb8fdee19239f8cb84affb911a6e784a91 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 21 Dec 2016 17:57:56 +0000 Subject: Reduce MR widget title by one pixel --- app/assets/stylesheets/pages/merge_requests.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index e779e65eca3..dd938f88dae 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -96,7 +96,7 @@ .mr-widget-body { h4 { font-weight: 600; - font-size: 17px; + font-size: 16px; margin: 5px 0; color: $gl-gray-dark; -- cgit v1.2.1 From d0c5222de2c435f74ac7dfd99194afbd292f2dd2 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 21 Dec 2016 18:35:16 +0000 Subject: Put back progress bar CSS Add changelog entry --- app/assets/stylesheets/framework/tw_bootstrap.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/tw_bootstrap.scss b/app/assets/stylesheets/framework/tw_bootstrap.scss index 718dbbfea27..55bc325b858 100644 --- a/app/assets/stylesheets/framework/tw_bootstrap.scss +++ b/app/assets/stylesheets/framework/tw_bootstrap.scss @@ -33,7 +33,7 @@ @import "bootstrap/labels"; @import "bootstrap/badges"; @import "bootstrap/alerts"; -// @import "bootstrap/progress-bars"; +@import "bootstrap/progress-bars"; @import "bootstrap/list-group"; @import "bootstrap/wells"; @import "bootstrap/close"; -- cgit v1.2.1 From 1c2d9015da095a9c4148cd5455e9ae4e8f854674 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 21 Dec 2016 21:08:55 +0200 Subject: Whitelist next project names: notes, services Signed-off-by: Dmitriy Zaporozhets --- app/validators/project_path_validator.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/validators/project_path_validator.rb b/app/validators/project_path_validator.rb index 79b2c99fd70..aec0d0ce44e 100644 --- a/app/validators/project_path_validator.rb +++ b/app/validators/project_path_validator.rb @@ -15,7 +15,7 @@ class ProjectPathValidator < ActiveModel::EachValidator # 'tree' as project name and 'deploy_keys' as route. # RESERVED = (NamespaceValidator::RESERVED - - %w[dashboard help ci admin search] + + %w[dashboard help ci admin search notes services] + %w[tree commits wikis new edit create update logs_tree preview blob blame raw files create_dir find_file]).freeze -- cgit v1.2.1 From 12a088a15a88d2b2493847d9d33f6999f366b928 Mon Sep 17 00:00:00 2001 From: dimitrieh Date: Thu, 22 Dec 2016 00:33:38 +0100 Subject: fixed minor animation glitch in mini pipeline graph animation --- app/assets/stylesheets/pages/pipelines.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index f6164c8907e..697887dcbe5 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -827,7 +827,7 @@ margin-right: -8px; .ci-status-icon { - width: 28px; + width: 32px; padding: 0 8px 0 0; transition: width 0.2s cubic-bezier(0.25, 0, 1, 1); @@ -909,4 +909,4 @@ min-height: 450px; } } -} \ No newline at end of file +} -- cgit v1.2.1 From 9b66aa6e04ab66af7ce11e26076ebf431ca938c5 Mon Sep 17 00:00:00 2001 From: Tiago Botelho Date: Mon, 19 Dec 2016 10:26:12 +0000 Subject: Prevent empty pagination when list is not empty --- app/controllers/concerns/kaminari_pagination.rb | 8 ++++++++ app/controllers/dashboard/todos_controller.rb | 4 +++- app/controllers/projects/issues_controller.rb | 3 ++- app/controllers/projects/merge_requests_controller.rb | 3 ++- app/controllers/projects/snippets_controller.rb | 3 ++- 5 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 app/controllers/concerns/kaminari_pagination.rb (limited to 'app') diff --git a/app/controllers/concerns/kaminari_pagination.rb b/app/controllers/concerns/kaminari_pagination.rb new file mode 100644 index 00000000000..b69340cac0e --- /dev/null +++ b/app/controllers/concerns/kaminari_pagination.rb @@ -0,0 +1,8 @@ +module KaminariPagination + extend ActiveSupport::Concern + + def bounded_pagination(items, page_number) + items = items.page(page_number) + items.to_a.empty? ? items.page(items.total_pages) : items + end +end diff --git a/app/controllers/dashboard/todos_controller.rb b/app/controllers/dashboard/todos_controller.rb index d425d0f9014..b2333a02392 100644 --- a/app/controllers/dashboard/todos_controller.rb +++ b/app/controllers/dashboard/todos_controller.rb @@ -1,9 +1,11 @@ class Dashboard::TodosController < Dashboard::ApplicationController + include KaminariPagination + before_action :find_todos, only: [:index, :destroy_all] def index @sort = params[:sort] - @todos = @todos.page(params[:page]) + @todos = bounded_pagination(@todos, params[:page]) end def destroy diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 4f66e01e0f7..ec09a5297fc 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -5,6 +5,7 @@ class Projects::IssuesController < Projects::ApplicationController include ToggleAwardEmoji include IssuableCollections include SpammableActions + include KaminariPagination before_action :redirect_to_external_issue_tracker, only: [:index, :new] before_action :module_enabled @@ -24,7 +25,7 @@ class Projects::IssuesController < Projects::ApplicationController def index @issues = issues_collection - @issues = @issues.page(params[:page]) + @issues = bounded_pagination(@issues, params[:page]) if params[:label_name].present? @labels = LabelsFinder.new(current_user, project_id: @project.id, title: params[:label_name]).execute diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 3abebdfd032..e25eea52723 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -6,6 +6,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController include NotesHelper include ToggleAwardEmoji include IssuableCollections + include KaminariPagination before_action :module_enabled before_action :merge_request, only: [ @@ -37,7 +38,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController def index @merge_requests = merge_requests_collection - @merge_requests = @merge_requests.page(params[:page]) + @merge_requests = bounded_pagination(@merge_requests, params[:page]) if params[:label_name].present? labels_params = { project_id: @project.id, title: params[:label_name] } diff --git a/app/controllers/projects/snippets_controller.rb b/app/controllers/projects/snippets_controller.rb index 0720be2e55d..7083b29b6a3 100644 --- a/app/controllers/projects/snippets_controller.rb +++ b/app/controllers/projects/snippets_controller.rb @@ -1,5 +1,6 @@ class Projects::SnippetsController < Projects::ApplicationController include ToggleAwardEmoji + include KaminariPagination before_action :module_enabled before_action :snippet, only: [:show, :edit, :destroy, :update, :raw, :toggle_award_emoji] @@ -25,7 +26,7 @@ class Projects::SnippetsController < Projects::ApplicationController project: @project, scope: params[:scope] ) - @snippets = @snippets.page(params[:page]) + @snippets = bounded_pagination(@snippets, params[:page]) end def new -- cgit v1.2.1 From 805bbe889328bff55b49290294721405148cc980 Mon Sep 17 00:00:00 2001 From: Tiago Botelho Date: Tue, 20 Dec 2016 18:52:09 +0000 Subject: adds specs for respective behaviour --- app/controllers/concerns/kaminari_pagination.rb | 8 -------- app/controllers/dashboard/todos_controller.rb | 7 ++++--- app/controllers/projects/issues_controller.rb | 6 ++++-- app/controllers/projects/merge_requests_controller.rb | 6 ++++-- app/controllers/projects/snippets_controller.rb | 6 ++++-- 5 files changed, 16 insertions(+), 17 deletions(-) delete mode 100644 app/controllers/concerns/kaminari_pagination.rb (limited to 'app') diff --git a/app/controllers/concerns/kaminari_pagination.rb b/app/controllers/concerns/kaminari_pagination.rb deleted file mode 100644 index b69340cac0e..00000000000 --- a/app/controllers/concerns/kaminari_pagination.rb +++ /dev/null @@ -1,8 +0,0 @@ -module KaminariPagination - extend ActiveSupport::Concern - - def bounded_pagination(items, page_number) - items = items.page(page_number) - items.to_a.empty? ? items.page(items.total_pages) : items - end -end diff --git a/app/controllers/dashboard/todos_controller.rb b/app/controllers/dashboard/todos_controller.rb index b2333a02392..40652129f4c 100644 --- a/app/controllers/dashboard/todos_controller.rb +++ b/app/controllers/dashboard/todos_controller.rb @@ -1,11 +1,12 @@ class Dashboard::TodosController < Dashboard::ApplicationController - include KaminariPagination - before_action :find_todos, only: [:index, :destroy_all] def index @sort = params[:sort] - @todos = bounded_pagination(@todos, params[:page]) + @todos = @todos.page(params[:page]) + if @todos.out_of_range? && @todos.total_pages != 0 + redirect_to dashboard_todos_path(page: @todos.total_pages) + end end def destroy diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index ec09a5297fc..0efeec98570 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -5,7 +5,6 @@ class Projects::IssuesController < Projects::ApplicationController include ToggleAwardEmoji include IssuableCollections include SpammableActions - include KaminariPagination before_action :redirect_to_external_issue_tracker, only: [:index, :new] before_action :module_enabled @@ -25,7 +24,10 @@ class Projects::IssuesController < Projects::ApplicationController def index @issues = issues_collection - @issues = bounded_pagination(@issues, params[:page]) + @issues = @issues.page(params[:page]) + if @issues.out_of_range? && @issues.total_pages != 0 + return redirect_to namespace_project_issues_path(page: @issues.total_pages) + end if params[:label_name].present? @labels = LabelsFinder.new(current_user, project_id: @project.id, title: params[:label_name]).execute diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index e25eea52723..050d0ca77ae 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -6,7 +6,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController include NotesHelper include ToggleAwardEmoji include IssuableCollections - include KaminariPagination before_action :module_enabled before_action :merge_request, only: [ @@ -38,7 +37,10 @@ class Projects::MergeRequestsController < Projects::ApplicationController def index @merge_requests = merge_requests_collection - @merge_requests = bounded_pagination(@merge_requests, params[:page]) + @merge_requests = @merge_requests.page(params[:page]) + if @merge_requests.out_of_range? && @merge_requests.total_pages != 0 + return redirect_to namespace_project_merge_requests_path(page: @merge_requests.total_pages) + end if params[:label_name].present? labels_params = { project_id: @project.id, title: params[:label_name] } diff --git a/app/controllers/projects/snippets_controller.rb b/app/controllers/projects/snippets_controller.rb index 7083b29b6a3..02a97c1c574 100644 --- a/app/controllers/projects/snippets_controller.rb +++ b/app/controllers/projects/snippets_controller.rb @@ -1,6 +1,5 @@ class Projects::SnippetsController < Projects::ApplicationController include ToggleAwardEmoji - include KaminariPagination before_action :module_enabled before_action :snippet, only: [:show, :edit, :destroy, :update, :raw, :toggle_award_emoji] @@ -26,7 +25,10 @@ class Projects::SnippetsController < Projects::ApplicationController project: @project, scope: params[:scope] ) - @snippets = bounded_pagination(@snippets, params[:page]) + @snippets = @snippets.page(params[:page]) + if @snippets.out_of_range? && @snippets.total_pages != 0 + redirect_to namespace_project_snippets_path(page: @snippets.total_pages) + end end def new -- cgit v1.2.1 From 28d32033629d6262013a84d74f781280b1988a7a Mon Sep 17 00:00:00 2001 From: Regis Date: Wed, 21 Dec 2016 17:23:31 -0700 Subject: change retry and canel '_url' to '_path' --- .../javascripts/vue_pipelines_index/pipeline_actions.js.es6 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 index b568d3a75a2..65aa3ff07d2 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 @@ -71,22 +71,22 @@
    -- cgit v1.2.1 From 6a7af99a42a13d87cd4c8c2ea757464d2b0f9ce4 Mon Sep 17 00:00:00 2001 From: Regis Date: Wed, 21 Dec 2016 17:30:27 -0700 Subject: changed label to group for css --- app/assets/javascripts/vue_pipelines_index/stage.js.es6 | 2 +- app/assets/javascripts/vue_pipelines_index/status.js.es6 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 index 7fcf575b17f..d214092f412 100644 --- a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 @@ -9,7 +9,7 @@ return `Build: ${this.stage.status.label}`; }, tooltip() { - return `has-tooltip ci-status-icon-${this.stage.status.label}`; + return `has-tooltip ci-status-icon-${this.stage.status.group}`; }, svg() { return this.svgs[this.match(this.stage.status.icon)]; diff --git a/app/assets/javascripts/vue_pipelines_index/status.js.es6 b/app/assets/javascripts/vue_pipelines_index/status.js.es6 index fd145f5e066..55efb8ebae4 100644 --- a/app/assets/javascripts/vue_pipelines_index/status.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/status.js.es6 @@ -10,7 +10,7 @@ cssClasses() { const cssObject = {}; cssObject['ci-status'] = true; - cssObject[`ci-${this.pipeline.details.status.text}`] = true; + cssObject[`ci-${this.pipeline.details.status.group}`] = true; return cssObject; }, svg() { -- cgit v1.2.1 From 2d1218991c1cd5b7b56e15ccc8d7c47d4b8e6cd0 Mon Sep 17 00:00:00 2001 From: Regis Date: Wed, 21 Dec 2016 18:06:23 -0700 Subject: use path instead of url for commit ref and pipeline url --- app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 | 2 +- app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 index 96baef32a9f..92c343e33da 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 @@ -13,7 +13,7 @@ }, template: ` - + #{{pipeline.id}} by diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 index b82d8f1a0db..a16c1e5bef9 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 @@ -52,7 +52,7 @@ }, ref(pipeline) { const { ref } = pipeline; - return ({ name: ref.name, tag: ref['tag?'], ref_url: ref.url }); + return ({ name: ref.name, tag: ref.tag, ref_url: ref.path }); }, commitTitle(pipeline) { return pipeline.commit ? pipeline.commit.title : ''; @@ -61,7 +61,7 @@ return pipeline.commit ? pipeline.commit.short_id : ''; }, commitUrl(pipeline) { - return pipeline.commit ? pipeline.commit.commit_url : ''; + return pipeline.commit ? pipeline.commit.commit_path : ''; }, match(string) { return string.replace(/_([a-z])/g, (m, w) => w.toUpperCase()); -- cgit v1.2.1 From a548b70851813f71c57da59769fade9495a0d2a9 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 22 Dec 2016 10:03:30 +0000 Subject: Fixed discussion note resolve button SVG color --- app/assets/stylesheets/pages/notes.scss | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss index 6ac4ec6ea0d..c3edf8a65b5 100644 --- a/app/assets/stylesheets/pages/notes.scss +++ b/app/assets/stylesheets/pages/notes.scss @@ -566,18 +566,14 @@ ul.notes { &.is-active { color: $gl-text-green; - svg path { + svg { fill: $gl-text-green; } } svg { position: relative; - color: $gray-darkest; - - path { - fill: $gray-darkest; - } + fill: $gray-darkest; } } -- cgit v1.2.1 From e008e14c7b2d3d5596d767dfb51a693f0746dfbb Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 22 Dec 2016 11:59:41 +0100 Subject: Fix single team selection --- app/views/projects/mattermosts/_team_selection.html.haml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/projects/mattermosts/_team_selection.html.haml b/app/views/projects/mattermosts/_team_selection.html.haml index 7980f7c9a72..24e86b8497f 100644 --- a/app/views/projects/mattermosts/_team_selection.html.haml +++ b/app/views/projects/mattermosts/_team_selection.html.haml @@ -8,7 +8,9 @@ = @teams.one? ? 'The team' : 'Select the team' where the slash commands will be used in - selected_id = @teams.keys.first if @teams.one? - = f.select(:team_id, mattermost_teams_options(@teams), {}, { class: 'form-control', selected: "#{selected_id}", disabled: @teams.one? }) + - options = mattermost_teams_options(@teams) + - options = options_for_select(options, selected_id) + = f.select(:team_id, options, {}, { class: 'form-control', selected: "#{selected_id}" }) .help-block - if @teams.one? This is the only team where you are an administrator. -- cgit v1.2.1 From 4e0db4e9542d68dee3ce19a5cf5fb3c206e7b2ba Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Thu, 22 Dec 2016 11:23:29 +0000 Subject: Fix broken dropdown --- app/views/projects/stage/_in_stage_group.html.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/views/projects/stage/_in_stage_group.html.haml b/app/views/projects/stage/_in_stage_group.html.haml index b15f7eaeab2..65e5f31e86c 100644 --- a/app/views/projects/stage/_in_stage_group.html.haml +++ b/app/views/projects/stage/_in_stage_group.html.haml @@ -1,8 +1,8 @@ - group_status = CommitStatus.where(id: subject).status -%button.dropdown-menu-toggle.build-content.has-tooltip{ type: 'button', data: { toggle: 'dropdown'} } +%button.dropdown-menu-toggle.build-content.has-tooltip{ type: 'button', data: { toggle: 'dropdown', title: "#{name} - #{group_status}" } } %span{class: "ci-status-icon ci-status-icon-#{group_status}"} = ci_icon_for_status(group_status) - %span.ci-status-text{ 'data-toggle' => 'tooltip', 'data-title' => "#{name} - #{group_status}" } + %span.ci-status-text = name %span.dropdown-counter-badge= subject.size .dropdown-menu.grouped-pipeline-dropdown -- cgit v1.2.1 From 87b89c05bcd569a39b31f47180542522d44610b6 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Thu, 22 Dec 2016 11:23:42 +0000 Subject: Fix hover in dropdowns, make closer to the mockups --- app/assets/stylesheets/pages/pipelines.scss | 61 +++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 12 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 697887dcbe5..7de6a21c07b 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -593,6 +593,27 @@ } } } + + .grouped-pipeline-dropdown { + .dropdown-build { + .build-content { + width: 100%; + + &:hover { + background-color: $stage-hover-bg; + color: $gl-text-color; + } + } + + .ci-action-icon-container { + padding: 0; + font-size: 11px; + position: absolute; + top: 1px; + right: 8px; + } + } + } } .dropdown-counter-badge { @@ -603,9 +624,11 @@ margin-right: 2px; } + .grouped-pipeline-dropdown { padding: 0; width: 191px; + min-width: 191px; left: auto; right: -195px; top: -4px; @@ -615,11 +638,22 @@ display: inline-block; } - .build-content { - width: 138px; + .dropdown-build { + .build-content { + width: 100%; - &:hover { - background-color: $stage-hover-bg; + &:hover { + background-color: $stage-hover-bg; + color: $gl-text-color; + } + } + + .ci-action-icon-container { + padding: 0; + font-size: 11px; + position: absolute; + margin-top: 3px; + right: 7px; } } @@ -629,12 +663,10 @@ margin: 3px 0; li { - padding-top: 2px; - margin: 4px 7px; - padding: 0 3px; - padding-left: 0; - padding-bottom: 0; - line-height: 0; + margin: 4px 8px 4px 9px; + padding: 0; + line-height: 1.1; + position: relative; .ci-action-icon-container:hover { background-color: transparent; @@ -648,6 +680,11 @@ } } +.pipeline-graph .dropdown-build .ci-status-icon svg { + width: 18px; + height: 18px; +} + .ci-status-text { max-width: 110px; white-space: nowrap; @@ -656,7 +693,7 @@ vertical-align: bottom; display: inline-block; position: relative; - font-weight: 100; + font-weight: 200; } // Action Icons @@ -693,7 +730,7 @@ color: $gl-text-color-light; .build-content { - padding: 3px 7px 6px; + padding: 4px 7px 8px; } .ci-action-icon-container { -- cgit v1.2.1 From fab2f071abc80ee777fea6968147dfb735f2551c Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Thu, 22 Dec 2016 12:17:28 +0000 Subject: Fix dropdown content non appearing in MR view Add MR ID to Changelog entry --- app/assets/javascripts/dispatcher.js.es6 | 5 ----- app/assets/javascripts/merge_request_tabs.js.es6 | 4 ++++ app/assets/stylesheets/pages/pipelines.scss | 4 ++++ 3 files changed, 8 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/dispatcher.js.es6 b/app/assets/javascripts/dispatcher.js.es6 index 5245c5aa494..78f68a247a2 100644 --- a/app/assets/javascripts/dispatcher.js.es6 +++ b/app/assets/javascripts/dispatcher.js.es6 @@ -140,11 +140,6 @@ case 'projects:merge_requests:commits': new MergedButtons(); break; - case 'projects:merge_requests:pipelines': - new gl.MiniPipelineGraph({ - container: '.js-pipeline-table', - }); - break; case "projects:merge_requests:diffs": new gl.Diff(); new ZenMode(); diff --git a/app/assets/javascripts/merge_request_tabs.js.es6 b/app/assets/javascripts/merge_request_tabs.js.es6 index 42015a02477..860e7e066a0 100644 --- a/app/assets/javascripts/merge_request_tabs.js.es6 +++ b/app/assets/javascripts/merge_request_tabs.js.es6 @@ -259,6 +259,10 @@ gl.utils.localTimeAgo($('.js-timeago', '#pipelines')); this.pipelinesLoaded = true; this.scrollToElement('#pipelines'); + + new gl.MiniPipelineGraph({ + container: '.js-pipeline-table', + }); }, }); } diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 697887dcbe5..241bf02bafd 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -52,6 +52,10 @@ } } +.content-list.pipelines .table-holder { + min-height: 300px; +} + .pipeline-holder { width: 100%; overflow: auto; -- cgit v1.2.1 From b552f2b02039de374c9eca229ec2b220b1577c08 Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Thu, 22 Dec 2016 12:31:25 +0000 Subject: Removed color-label overwrites --- app/assets/stylesheets/pages/milestone.scss | 6 ------ 1 file changed, 6 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/milestone.scss b/app/assets/stylesheets/pages/milestone.scss index 77c523d7310..f47ae9c6157 100644 --- a/app/assets/stylesheets/pages/milestone.scss +++ b/app/assets/stylesheets/pages/milestone.scss @@ -25,12 +25,6 @@ } .issuable-row { - .color-label { - border-radius: 2px; - padding: 3px !important; - margin-right: 7px; - } - span a { color: $gl-text-color; word-wrap: break-word; -- cgit v1.2.1 From f6fceb653958f0f1b0c832a3e642ea7cea1fab24 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 22 Dec 2016 13:43:20 +0100 Subject: Fix Mattermost command creation by specifying username --- app/models/project_services/mattermost_slash_commands_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/models/project_services/mattermost_slash_commands_service.rb b/app/models/project_services/mattermost_slash_commands_service.rb index 6c78c0af71c..2cb481182d7 100644 --- a/app/models/project_services/mattermost_slash_commands_service.rb +++ b/app/models/project_services/mattermost_slash_commands_service.rb @@ -46,6 +46,6 @@ class MattermostSlashCommandsService < ChatSlashCommandsService description: "Perform common operations on: #{pretty_project_name}", display_name: "GitLab / #{pretty_project_name}", method: 'P', - user_name: 'GitLab') + username: 'GitLab') end end -- cgit v1.2.1 From 0ad88cb8d35201260da2986782f10956abe4fc3a Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Thu, 22 Dec 2016 12:48:14 +0000 Subject: Increase left padding of filter row labels --- app/assets/stylesheets/pages/labels.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/labels.scss b/app/assets/stylesheets/pages/labels.scss index d129eb12a45..237869aa544 100644 --- a/app/assets/stylesheets/pages/labels.scss +++ b/app/assets/stylesheets/pages/labels.scss @@ -98,7 +98,7 @@ } .label { - padding: 8px 9px 9px; + padding: 8px 9px 9px $gl-padding; font-size: 14px; } } -- cgit v1.2.1 From daff64452ff79b95eda5eb33c5aea8aface98f2b Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 22 Dec 2016 14:02:45 +0100 Subject: Do not show retried builds in pipeline stage dropdown --- app/views/projects/pipelines/_stage.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/projects/pipelines/_stage.html.haml b/app/views/projects/pipelines/_stage.html.haml index 20456e792e7..cf1b366bf2c 100644 --- a/app/views/projects/pipelines/_stage.html.haml +++ b/app/views/projects/pipelines/_stage.html.haml @@ -1,4 +1,4 @@ %ul - - @stage.statuses.each do |status| + - @stage.statuses.latest.each do |status| %li.dropdown-build = render 'ci/status/graph_badge', subject: status -- cgit v1.2.1 From 4b7395e0fab8e35436957e41929b44f948a1c41a Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Thu, 22 Dec 2016 10:54:35 +0100 Subject: Fix format of Slack when result is nil --- app/models/project_services/slack_slash_commands_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/models/project_services/slack_slash_commands_service.rb b/app/models/project_services/slack_slash_commands_service.rb index cb19ebf4cad..5a7cc0fb329 100644 --- a/app/models/project_services/slack_slash_commands_service.rb +++ b/app/models/project_services/slack_slash_commands_service.rb @@ -16,7 +16,7 @@ class SlackSlashCommandsService < ChatSlashCommandsService def trigger(params) # Format messages to be Slack-compatible super.tap do |result| - result[:text] = format(result[:text]) + result[:text] = format(result[:text]) if result.is_a?(Hash) end end -- cgit v1.2.1 From 22bbb24f28718849934693b8163155ccae4c4b5e Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Thu, 22 Dec 2016 13:27:39 +0000 Subject: Fix viewing "build failed" TODOs --- app/helpers/todos_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb index 09c69786791..74de25acf9d 100644 --- a/app/helpers/todos_helper.rb +++ b/app/helpers/todos_helper.rb @@ -35,7 +35,7 @@ module TodosHelper else path = [todo.project.namespace.becomes(Namespace), todo.project, todo.target] - path.unshift(:builds) if todo.build_failed? + path.unshift(:pipelines) if todo.build_failed? polymorphic_path(path, anchor: anchor) end -- cgit v1.2.1 From 7241246a04773805397c0eefd44a6fba20f04a1a Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 22 Dec 2016 16:00:49 +0000 Subject: Stops GFM special characters interfering with markdown tags --- app/assets/javascripts/gfm_auto_complete.js.es6 | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/gfm_auto_complete.js.es6 b/app/assets/javascripts/gfm_auto_complete.js.es6 index cbd8ac4eddd..12875eaa1c3 100644 --- a/app/assets/javascripts/gfm_auto_complete.js.es6 +++ b/app/assets/javascripts/gfm_auto_complete.js.es6 @@ -74,15 +74,16 @@ // The below is taken from At.js source // Tweaked to commands to start without a space only if char before is a non-word character // https://github.com/ichord/At.js - var _a, _y, regexp, match, atSymbols; - atSymbols = Object.keys(this.app.controllers).join('|'); + var _a, _y, regexp, match, atSymbolsWithBar, atSymbolsWithoutBar; + atSymbolsWithBar = Object.keys(this.app.controllers).join('|'); + atSymbolsWithoutBar = Object.keys(this.app.controllers).join(''); subtext = subtext.split(' ').pop(); flag = flag.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); _a = decodeURI("%C3%80"); _y = decodeURI("%C3%BF"); - regexp = new RegExp("(?:\\B|\\W|\\s)" + flag + "(?![" + atSymbols + "])([A-Za-z" + _a + "-" + _y + "0-9_\'\.\+\-]*)$", 'gi'); + regexp = new RegExp("^(?:\\B|[^a-zA-Z0-9_" + atSymbolsWithoutBar + "]|\\s)" + flag + "(?![" + atSymbolsWithBar + "])([A-Za-z" + _a + "-" + _y + "0-9_\'\.\+\-]*)$", 'gi'); match = regexp.exec(subtext); -- cgit v1.2.1 From 6dc3efdd9896156b5b08c735f1639437ff874fc0 Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Thu, 22 Dec 2016 16:12:35 -0200 Subject: Do not override incoming webhook channel for mattermost and slack --- app/models/project_services/chat_notification_service.rb | 10 ++++++---- app/models/project_services/mattermost_service.rb | 2 +- app/models/project_services/slack_service.rb | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) (limited to 'app') diff --git a/app/models/project_services/chat_notification_service.rb b/app/models/project_services/chat_notification_service.rb index b0556987721..475344d80ce 100644 --- a/app/models/project_services/chat_notification_service.rb +++ b/app/models/project_services/chat_notification_service.rb @@ -49,10 +49,12 @@ class ChatNotificationService < Service return false unless message - opt = {} + channel_name = get_channel_field(object_kind).presence || channel - opt[:channel] = get_channel_field(object_kind).presence || channel || default_channel + opt = {} + opt[:channel] = channel_name if channel_name opt[:username] = username if username + notifier = Slack::Notifier.new(webhook, opt) notifier.ping(message.pretext, attachments: message.attachments, fallback: message.fallback) @@ -71,7 +73,7 @@ class ChatNotificationService < Service fields.reject { |field| field[:name].end_with?('channel') } end - def default_channel + def default_channel_placeholder raise NotImplementedError end @@ -103,7 +105,7 @@ class ChatNotificationService < Service def build_event_channels supported_events.reduce([]) do |channels, event| - channels << { type: 'text', name: event_channel_name(event), placeholder: default_channel } + channels << { type: 'text', name: event_channel_name(event), placeholder: default_channel_placeholder } end end diff --git a/app/models/project_services/mattermost_service.rb b/app/models/project_services/mattermost_service.rb index 0650f930402..ee8a0b55275 100644 --- a/app/models/project_services/mattermost_service.rb +++ b/app/models/project_services/mattermost_service.rb @@ -35,7 +35,7 @@ class MattermostService < ChatNotificationService ] end - def default_channel + def default_channel_placeholder "#town-square" end end diff --git a/app/models/project_services/slack_service.rb b/app/models/project_services/slack_service.rb index 0583470d3b5..76d233a3cca 100644 --- a/app/models/project_services/slack_service.rb +++ b/app/models/project_services/slack_service.rb @@ -34,7 +34,7 @@ class SlackService < ChatNotificationService ] end - def default_channel + def default_channel_placeholder "#general" end end -- cgit v1.2.1 From 0b21d6748be2438c5016299025bd99500409d094 Mon Sep 17 00:00:00 2001 From: Nur Rony Date: Fri, 23 Dec 2016 00:24:51 +0600 Subject: fixes timestamp text alignemnt in mr-list and issue-list --- app/assets/stylesheets/framework/lists.scss | 1 - 1 file changed, 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss index e96cd671e34..28a0f9871a2 100644 --- a/app/assets/stylesheets/framework/lists.scss +++ b/app/assets/stylesheets/framework/lists.scss @@ -239,7 +239,6 @@ ul.content-list { } ul.controls { - padding-top: 1px; float: right; list-style: none; -- cgit v1.2.1 From 7d7ba0b441bf600f3c047afdb1f7355ae690cd8a Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Thu, 22 Dec 2016 18:38:44 +0000 Subject: Fix text overflow Fix text overflow in comments in MR Adds MR ID to CHANGELOG entry --- app/assets/stylesheets/pages/notes.scss | 29 ++++++++++++++++++----------- app/views/projects/notes/_note.html.haml | 2 +- 2 files changed, 19 insertions(+), 12 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss index 6ac4ec6ea0d..b512da0939f 100644 --- a/app/assets/stylesheets/pages/notes.scss +++ b/app/assets/stylesheets/pages/notes.scss @@ -43,7 +43,7 @@ ul.notes { } .system-note-message { - display: inline; + display: inline-block; &::first-letter { text-transform: lowercase; @@ -55,7 +55,7 @@ ul.notes { } p { - display: inline; + display: inline-block; margin: 0; &::first-letter { @@ -151,10 +151,6 @@ ul.notes { } } } - - .note-headline-light { - display: inline; - } } .discussion-body { @@ -452,11 +448,6 @@ ul.notes { border-radius: $border-radius-base; } -.diff-file .note .note-actions { - right: 0; - top: 0; -} - /** * Line note button on the side of diffs @@ -590,3 +581,19 @@ ul.notes { } } } + +// Merge request notes in diffs +.diff-file { + + // Diff is side by side + .notes_content.parallel .note-header .note-headline-light { + display: block; + position: relative; + } + + // Diff is inline + .notes_content .note-header .note-headline-light { + display: inline-block; + position: relative; + } +} diff --git a/app/views/projects/notes/_note.html.haml b/app/views/projects/notes/_note.html.haml index 778a32e6345..399cf85cd0f 100644 --- a/app/views/projects/notes/_note.html.haml +++ b/app/views/projects/notes/_note.html.haml @@ -10,7 +10,7 @@ .timeline-content .note-header = link_to_member(note.project, note.author, avatar: false) - .inline.note-headline-light + .note-headline-light = note.author.to_reference - unless note.system commented -- cgit v1.2.1 From c60585a185d9e8ed0c4148a0a319e8672414c36f Mon Sep 17 00:00:00 2001 From: dimitrieh Date: Thu, 22 Dec 2016 20:54:54 +0100 Subject: Change earlier to task_status_short to avoid titlebar line wraps --- app/helpers/issuables_helper.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb index 8231f8fa334..1c213983a5b 100644 --- a/app/helpers/issuables_helper.rb +++ b/app/helpers/issuables_helper.rb @@ -96,8 +96,8 @@ module IssuablesHelper if issuable.tasks? output << " ".html_safe - output << content_tag(:span, issuable.task_status, id: "task_status", class: "hidden-xs") - output << content_tag(:span, issuable.task_status_short, id: "task_status_short", class: "hidden-sm hidden-md hidden-lg") + output << content_tag(:span, issuable.task_status, id: "task_status", class: "hidden-xs hidden-sm") + output << content_tag(:span, issuable.task_status_short, id: "task_status_short", class: "hidden-md hidden-lg") end output -- cgit v1.2.1 From 63d4db847eec79ee964ec58fb906e558d2019ff9 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Thu, 22 Dec 2016 23:25:05 +0000 Subject: Fix hover not working on firefox --- app/assets/stylesheets/pages/pipelines.scss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 93c8b6c9a1e..8056e0701ef 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -863,7 +863,8 @@ } .builds-dropdown { - &:focus { + &:focus, + &:hover { outline: none; margin-right: -8px; -- cgit v1.2.1 From 19e6f22a0aa7834876dd1ebfa59e1a873e4e7e96 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Thu, 22 Dec 2016 23:31:52 +0000 Subject: Fix caret position in Safari --- app/assets/stylesheets/pages/pipelines.scss | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 8056e0701ef..00ddfc16b29 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -923,9 +923,9 @@ .dropdown-caret { font-size: 11px; - position: relative; - top: 3px; - left: -14px; + position: absolute;; + top: 5px; + left: 20px; margin-right: -6px; display: none; z-index: 2; -- cgit v1.2.1 From 716549e96b6537103c2cdeb124330325f96ff458 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Fri, 23 Dec 2016 00:18:57 +0000 Subject: Fix animation glitch in the caret --- app/assets/stylesheets/pages/pipelines.scss | 134 +++++++++++++--------------- 1 file changed, 63 insertions(+), 71 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 00ddfc16b29..d75a5f42c2f 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -789,6 +789,68 @@ color: $gl-text-color-light; border: none; margin: 0; + + &:focus, + &:hover { + outline: none; + margin-right: -8px; + + .ci-status-icon { + width: 32px; + padding: 0 8px 0 0; + transition: width 0.1s cubic-bezier(0.25, 0, 1, 1); + + + .dropdown-caret { + visibility: visible; + opacity: 1 + } + } + } + + &:focus, + &:active { + .ci-status-icon-success { + background-color: rgba($gl-success, .1); + } + + .ci-status-icon-failed { + background-color: rgba($gl-danger, .1); + } + + .ci-status-icon-pending, + .ci-status-icon-success_with_warnings { + background-color: rgba($gl-warning, .1); + } + + .ci-status-icon-running { + background-color: rgba($blue-normal, .1); + } + + .ci-status-icon-canceled, + .ci-status-icon-disabled, + .ci-status-icon-not-found { + background-color: rgba($gl-gray, .1); + } + + .ci-status-icon-created, + .ci-status-icon-skipped { + background-color: rgba($gray-darkest, .1); + } + } + + .mini-pipeline-graph-icon-container { + .dropdown-caret { + font-size: 11px; + position: absolute; + top: 5px; + left: 20px; + margin-right: -6px; + z-index: 2; + visibility: hidden; + opacity: 0; + transition: visibility 0.1s, opacity 0.3s linear + } + } } .dropdown-build .build-content { @@ -849,7 +911,7 @@ height: 22px; position: relative; z-index: 2; - transition: all 0.2s cubic-bezier(0.25, 0, 1, 1); + transition: all 0.1s cubic-bezier(0.25, 0, 1, 1); svg { top: -1px; @@ -862,76 +924,6 @@ height: 22px; } -.builds-dropdown { - &:focus, - &:hover { - outline: none; - margin-right: -8px; - - .ci-status-icon { - width: 32px; - padding: 0 8px 0 0; - transition: width 0.2s cubic-bezier(0.25, 0, 1, 1); - - + .dropdown-caret { - display: inline-block; - } - } - } - - &:focus, - &:active { - .ci-status-icon-success { - background-color: rgba($gl-success, .1); - } - - .ci-status-icon-failed { - background-color: rgba($gl-danger, .1); - } - - .ci-status-icon-pending, - .ci-status-icon-success_with_warnings { - background-color: rgba($gl-warning, .1); - } - - .ci-status-icon-running { - background-color: rgba($blue-normal, .1); - } - - .ci-status-icon-canceled, - .ci-status-icon-disabled, - .ci-status-icon-not-found { - background-color: rgba($gl-gray, .1); - } - - .ci-status-icon-created, - .ci-status-icon-skipped { - background-color: rgba($gray-darkest, .1); - } - } - - .mini-pipeline-graph-icon-container { - .ci-status-icon:hover, - .ci-status-icon:focus { - width: 32px; - padding: 0 8px 0 0; - - + .dropdown-caret { - display: inline-block; - } - } - - .dropdown-caret { - font-size: 11px; - position: absolute;; - top: 5px; - left: 20px; - margin-right: -6px; - display: none; - z-index: 2; - } - } -} .terminal-icon { margin-left: 3px; -- cgit v1.2.1 From c95137fce3ecbb6c6d4d7a6425736c365f5e5c2c Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Fri, 23 Dec 2016 00:36:55 +0000 Subject: Fix alignment in Safari --- app/assets/stylesheets/pages/pipelines.scss | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index d75a5f42c2f..1f3fb002074 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -201,7 +201,7 @@ width: 8px; position: absolute; right: -7px; - bottom: 10px; + top: 10px; border-bottom: 2px solid $border-color; } } @@ -784,7 +784,6 @@ .mini-pipeline-graph { .builds-dropdown { background-color: transparent; - border: none; padding: 0; color: $gl-text-color-light; border: none; -- cgit v1.2.1 From b63f2794f076a7394c8a000829a632bcffef2b00 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 23 Dec 2016 16:53:56 +0800 Subject: Ci::Pipeline.latest order by id DESC The name latest implies that it's reverse chronological, and we did expect it that way. https://gitlab.com/gitlab-org/gitlab-ce/issues/25993#note_20429761 >>> ok, I think markglenfletchera is correct in https://gitlab.com/gitlab-com/support-forum/issues/1394#note_20399939 that `Project#latest_successful_builds_for` is giving oldest pipeline rather than latest pipeline. This is a ~regression introduced by !7333 where `order(id: :desc)` was removed causing this. The offending change was: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7333/diffs#b22732e5f39e176c7c719fe485847d0fb0564275_92_108 The confusion was caused by the `latest` name implication, which actually didn't order anything, and I think we should add `order(id: :desc)` to `Ci::Pipeline.latest` otherwise it's confusing that it's not actually ordered. >>> Closes #25993 --- app/models/ci/pipeline.rb | 12 +++++++----- app/models/project.rb | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'app') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index f2f6453b3b9..5494a8da0d9 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -93,11 +93,13 @@ module Ci .select("max(#{quoted_table_name}.id)") .group(:ref, :sha) - if ref - where(id: max_id, ref: ref) - else - where(id: max_id) - end + query = if ref + where(id: max_id, ref: ref) + else + where(id: max_id) + end + + query.order(id: :desc) end def self.latest_status(ref = nil) diff --git a/app/models/project.rb b/app/models/project.rb index 26fa20f856d..72fdd4514c4 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -418,7 +418,7 @@ class Project < ActiveRecord::Base repository.commit(ref) end - # ref can't be HEAD, can only be branch/tag name or SHA + # ref can't be HEAD or SHA, can only be branch/tag name def latest_successful_builds_for(ref = default_branch) latest_pipeline = pipelines.latest_successful_for(ref) -- cgit v1.2.1 From c46022413585e14013da4575b05dd094439c4cd7 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 23 Dec 2016 09:05:01 +0000 Subject: Fixed error with GFM autocomplete when no data exists --- app/assets/javascripts/gfm_auto_complete.js.es6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/gfm_auto_complete.js.es6 b/app/assets/javascripts/gfm_auto_complete.js.es6 index 12875eaa1c3..3857bbb743b 100644 --- a/app/assets/javascripts/gfm_auto_complete.js.es6 +++ b/app/assets/javascripts/gfm_auto_complete.js.es6 @@ -367,7 +367,7 @@ return $input.trigger('keyup'); }, isLoading(data) { - if (!data) return false; + if (!data || !data.length) return false; if (Array.isArray(data)) data = data[0]; return data === this.defaultLoadingData[0] || data.name === this.defaultLoadingData[0]; }, -- cgit v1.2.1 From db8ee6672cf49a2eed4e244080246f21a9e14dd9 Mon Sep 17 00:00:00 2001 From: Adam Niedzielski Date: Fri, 23 Dec 2016 11:08:09 +0100 Subject: Rename "autodeploy" to "auto deploy" --- app/views/projects/show.html.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index a915c159cb4..f9776628c77 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -70,8 +70,8 @@ = link_to 'Set up Koding', add_koding_stack_path(@project) - if @repository.gitlab_ci_yml.blank? && @project.deployment_service.present? %li.missing - = link_to add_special_file_path(@project, file_name: '.gitlab-ci.yml', commit_message: 'Set up autodeploy', target_branch: 'autodeploy', context: 'autodeploy') do - Set up autodeploy + = link_to add_special_file_path(@project, file_name: '.gitlab-ci.yml', commit_message: 'Set up auto deploy', target_branch: 'auto-deploy', context: 'autodeploy') do + Set up auto deploy - if @repository.commit .project-last-commit{ class: container_class } -- cgit v1.2.1 From 13d009ce545271c6d0422a8df61c74028439d8bd Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 23 Dec 2016 18:17:25 +0800 Subject: Prefer oneline and Rubocop prefers ternary operator Feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8286/diffs#note_20433402 --- app/models/ci/pipeline.rb | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'app') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 5494a8da0d9..6894a5763ff 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -93,13 +93,8 @@ module Ci .select("max(#{quoted_table_name}.id)") .group(:ref, :sha) - query = if ref - where(id: max_id, ref: ref) - else - where(id: max_id) - end - - query.order(id: :desc) + relation = ref ? where(ref: ref) : self + relation.where(id: max_id).order(id: :desc) end def self.latest_status(ref = nil) -- cgit v1.2.1 From 8f490cbe0e4f316ab2496fb253cd7bf90856e31d Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Fri, 23 Dec 2016 12:06:45 +0000 Subject: Fix eslint errors --- app/assets/stylesheets/pages/pipelines.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 1f3fb002074..a8392154a44 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -801,7 +801,7 @@ + .dropdown-caret { visibility: visible; - opacity: 1 + opacity: 1; } } } @@ -847,7 +847,7 @@ z-index: 2; visibility: hidden; opacity: 0; - transition: visibility 0.1s, opacity 0.3s linear + transition: visibility 0.1s, opacity 0.3s linear; } } } -- cgit v1.2.1 From 5507c7c66bd76030494d3fc5cc449cd9dc487077 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Fri, 23 Dec 2016 12:36:26 +0000 Subject: Fix line breaking in nodes of the pipeline graph in firefox Adds MR ID to CHANGELOG entry --- app/assets/stylesheets/pages/pipelines.scss | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 93c8b6c9a1e..799dfe908e0 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -335,7 +335,6 @@ width: 100%; background-color: $gray-light; padding: $gl-padding; - overflow: auto; white-space: nowrap; transition: max-height 0.3s, padding 0.3s; @@ -621,14 +620,14 @@ } .dropdown-counter-badge { - float: right; color: $border-color; font-weight: 100; font-size: 15px; - margin-right: 2px; + position: absolute; + right: 5px; + top: 8px; } - .grouped-pipeline-dropdown { padding: 0; width: 191px; -- cgit v1.2.1 From 3f6edaeae892d38df22f397c7079c09c4b279f5c Mon Sep 17 00:00:00 2001 From: Nur Rony Date: Fri, 23 Dec 2016 19:04:00 +0600 Subject: fixes confedential warning alignment on comment box --- app/assets/stylesheets/pages/note_form.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss index 074abec7692..e54e12be82f 100644 --- a/app/assets/stylesheets/pages/note_form.scss +++ b/app/assets/stylesheets/pages/note_form.scss @@ -109,7 +109,7 @@ margin: auto; margin-top: 0; text-align: center; - font-size: 13px; + font-size: 12px; @media (max-width: $screen-sm-max) { // On smaller devices the warning becomes the fourth item in the list, -- cgit v1.2.1 From 89d3ef38ccc7be722a0906d08b51a48b1c8ff681 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Wed, 21 Dec 2016 16:26:35 +0100 Subject: Schedule at most 100 commits When processing push payloads we now schedule at most the 100 most recent commits, instead of all commits that were in a payload. This prevents one from overloading the system by pushing thousands if not millions of commits in a single go. Fixes https://gitlab.com/gitlab-org/gitlab-ce/issues/25827 --- app/services/git_push_service.rb | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'app') diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb index 185556c12cc..6bbc3a9d9ff 100644 --- a/app/services/git_push_service.rb +++ b/app/services/git_push_service.rb @@ -3,6 +3,9 @@ class GitPushService < BaseService include Gitlab::CurrentSettings include Gitlab::Access + # The N most recent commits to process in a single push payload. + PROCESS_COMMIT_LIMIT = 100 + # This method will be called after each git update # and only if the provided user and project are present in GitLab. # @@ -77,6 +80,16 @@ class GitPushService < BaseService ProjectCacheWorker.perform_async(@project.id, types) end + # Schedules processing of commit messages. + def process_commit_messages + default = is_default_branch? + + push_commits.last(PROCESS_COMMIT_LIMIT).each do |commit| + ProcessCommitWorker. + perform_async(project.id, current_user.id, commit.to_hash, default) + end + end + protected def execute_related_hooks @@ -128,17 +141,6 @@ class GitPushService < BaseService end end - # Extract any GFM references from the pushed commit messages. If the configured issue-closing regex is matched, - # close the referenced Issue. Create cross-reference Notes corresponding to any other referenced Mentionables. - def process_commit_messages - default = is_default_branch? - - @push_commits.each do |commit| - ProcessCommitWorker. - perform_async(project.id, current_user.id, commit.to_hash, default) - end - end - def build_push_data @push_data ||= Gitlab::DataBuilder::Push.build( @project, -- cgit v1.2.1 From c21df973b0ffc1559ddef37fe63f41b80ca90788 Mon Sep 17 00:00:00 2001 From: Kushal Pandya Date: Fri, 23 Dec 2016 18:55:49 +0530 Subject: Hide Scroll Top for failed build --- app/assets/javascripts/build.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index 5e449170cd3..bc13c46443a 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -92,8 +92,8 @@ success: function(buildData) { $('.js-build-output').html(buildData.trace_html); if (removeRefreshStatuses.indexOf(buildData.status) >= 0) { - this.initScrollMonitor(); - return this.$buildRefreshAnimation.remove(); + this.$buildRefreshAnimation.remove(); + return this.initScrollMonitor(); } }.bind(this) }); -- cgit v1.2.1 From d7a2e92ca0ae7fba4898f2f8ab722033b0721ec9 Mon Sep 17 00:00:00 2001 From: Tiago Botelho Date: Wed, 21 Dec 2016 15:02:05 +0000 Subject: applies url_for so that we dont lose filters when redirecting --- app/controllers/dashboard/todos_controller.rb | 2 +- app/controllers/projects/issues_controller.rb | 2 +- app/controllers/projects/merge_requests_controller.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/controllers/dashboard/todos_controller.rb b/app/controllers/dashboard/todos_controller.rb index 40652129f4c..e3933e3d7b1 100644 --- a/app/controllers/dashboard/todos_controller.rb +++ b/app/controllers/dashboard/todos_controller.rb @@ -5,7 +5,7 @@ class Dashboard::TodosController < Dashboard::ApplicationController @sort = params[:sort] @todos = @todos.page(params[:page]) if @todos.out_of_range? && @todos.total_pages != 0 - redirect_to dashboard_todos_path(page: @todos.total_pages) + redirect_to url_for(params.merge(page: @todos.total_pages)) end end diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 0efeec98570..2beb0df8a07 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -26,7 +26,7 @@ class Projects::IssuesController < Projects::ApplicationController @issues = issues_collection @issues = @issues.page(params[:page]) if @issues.out_of_range? && @issues.total_pages != 0 - return redirect_to namespace_project_issues_path(page: @issues.total_pages) + return redirect_to url_for(params.merge(page: @issues.total_pages)) end if params[:label_name].present? diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 050d0ca77ae..fc8a289d49d 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -39,7 +39,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController @merge_requests = merge_requests_collection @merge_requests = @merge_requests.page(params[:page]) if @merge_requests.out_of_range? && @merge_requests.total_pages != 0 - return redirect_to namespace_project_merge_requests_path(page: @merge_requests.total_pages) + return redirect_to url_for(params.merge(page: @merge_requests.total_pages)) end if params[:label_name].present? -- cgit v1.2.1 From dfef28c920363036584d12cd030e021a789f522e Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Fri, 23 Dec 2016 15:19:16 -0200 Subject: Rename `opt` to `opts` on ChatNotificationService#execute --- app/models/project_services/chat_notification_service.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/models/project_services/chat_notification_service.rb b/app/models/project_services/chat_notification_service.rb index 475344d80ce..de815ff2bfe 100644 --- a/app/models/project_services/chat_notification_service.rb +++ b/app/models/project_services/chat_notification_service.rb @@ -51,11 +51,11 @@ class ChatNotificationService < Service channel_name = get_channel_field(object_kind).presence || channel - opt = {} - opt[:channel] = channel_name if channel_name - opt[:username] = username if username + opts = {} + opts[:channel] = channel_name if channel_name + opts[:username] = username if username - notifier = Slack::Notifier.new(webhook, opt) + notifier = Slack::Notifier.new(webhook, opts) notifier.ping(message.pretext, attachments: message.attachments, fallback: message.fallback) true -- cgit v1.2.1 From d54d5465967f9473c31a2e9572a4262b671ec6a7 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Fri, 23 Dec 2016 15:55:13 -0200 Subject: Fix rubucop offenses --- app/models/project_services/chat_notification_service.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/models/project_services/chat_notification_service.rb b/app/models/project_services/chat_notification_service.rb index de815ff2bfe..b7ef44c3054 100644 --- a/app/models/project_services/chat_notification_service.rb +++ b/app/models/project_services/chat_notification_service.rb @@ -49,10 +49,10 @@ class ChatNotificationService < Service return false unless message - channel_name = get_channel_field(object_kind).presence || channel + channel_name = get_channel_field(object_kind).presence || channel opts = {} - opts[:channel] = channel_name if channel_name + opts[:channel] = channel_name if channel_name opts[:username] = username if username notifier = Slack::Notifier.new(webhook, opts) -- cgit v1.2.1 From eb25f232fdd6947189d3ae024f2548178c876154 Mon Sep 17 00:00:00 2001 From: dimitrieh Date: Fri, 23 Dec 2016 19:32:15 +0100 Subject: minor css edits, quicker fade animation for caret, and positioned it slightly down by 1 px --- app/assets/stylesheets/pages/pipelines.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index a8392154a44..5f8874289cc 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -841,13 +841,13 @@ .dropdown-caret { font-size: 11px; position: absolute; - top: 5px; + top: 6px; left: 20px; margin-right: -6px; z-index: 2; visibility: hidden; opacity: 0; - transition: visibility 0.1s, opacity 0.3s linear; + transition: visibility 0.1s, opacity 0.1s linear; } } } -- cgit v1.2.1 From c0e5e69f9dc778bfe60e8362b72866413672c06f Mon Sep 17 00:00:00 2001 From: Regis Date: Fri, 23 Dec 2016 16:23:19 -0700 Subject: fix manual build tests --- app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 index 65aa3ff07d2..f658cfd077c 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 @@ -37,7 +37,7 @@ @@ -60,7 +60,7 @@
  • {{download(artifact.name)}} -- cgit v1.2.1 From 115536fbfa9904cef459bb735d29f20756887ebe Mon Sep 17 00:00:00 2001 From: Regis Date: Fri, 23 Dec 2016 16:28:37 -0700 Subject: use flags for retry and cancel logic --- app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 index f658cfd077c..ad5cb30cc42 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 @@ -71,7 +71,7 @@
  • Date: Fri, 23 Dec 2016 18:38:46 -0500 Subject: Fix dismiss icon position --- app/assets/stylesheets/pages/cycle_analytics.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/cycle_analytics.scss b/app/assets/stylesheets/pages/cycle_analytics.scss index 5aef31724e1..c453a57bd95 100644 --- a/app/assets/stylesheets/pages/cycle_analytics.scss +++ b/app/assets/stylesheets/pages/cycle_analytics.scss @@ -141,7 +141,7 @@ .dismiss-icon { position: absolute; - right: $cycle-analytics-dismiss-icon-color; + right: $cycle-analytics-box-padding; cursor: pointer; color: $cycle-analytics-dismiss-icon-color; } -- cgit v1.2.1 From 1255aa7355e0a570a69d5f1bf5bab1804667392a Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Fri, 23 Dec 2016 18:40:50 -0500 Subject: Fix column widths Fixes text splitting into two lines --- app/assets/stylesheets/pages/cycle_analytics.scss | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/cycle_analytics.scss b/app/assets/stylesheets/pages/cycle_analytics.scss index c453a57bd95..0f9b715b7a7 100644 --- a/app/assets/stylesheets/pages/cycle_analytics.scss +++ b/app/assets/stylesheets/pages/cycle_analytics.scss @@ -23,12 +23,12 @@ } .stage-header { - width: 28%; + width: 26%; padding-left: $gl-padding; } .median-header { - width: 12%; + width: 14%; } .event-header { @@ -247,11 +247,11 @@ float: left; &.stage-name { - width: 70%; + width: 65%; } &.stage-median { - width: 30%; + width: 35%; } } -- cgit v1.2.1 From 64086f6a76bdc5bad205fb516339ea4145cc526b Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Fri, 23 Dec 2016 18:41:08 -0500 Subject: Remove unnecesary css property --- app/assets/stylesheets/pages/cycle_analytics.scss | 1 - 1 file changed, 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/cycle_analytics.scss b/app/assets/stylesheets/pages/cycle_analytics.scss index 0f9b715b7a7..9ce261eafef 100644 --- a/app/assets/stylesheets/pages/cycle_analytics.scss +++ b/app/assets/stylesheets/pages/cycle_analytics.scss @@ -215,7 +215,6 @@ border-bottom: 1px solid transparent; border-right: 1px solid $border-color; background-color: $gray-light; - cursor: default; &.active { background-color: transparent; -- cgit v1.2.1 From ce22604eb9b7e7ad015f11ec0aca8ba87f8b30c4 Mon Sep 17 00:00:00 2001 From: Regis Date: Fri, 23 Dec 2016 16:54:03 -0700 Subject: get rid of nested spans in status component --- app/assets/javascripts/vue_pipelines_index/status.js.es6 | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/status.js.es6 b/app/assets/javascripts/vue_pipelines_index/status.js.es6 index 55efb8ebae4..f8decb17ca8 100644 --- a/app/assets/javascripts/vue_pipelines_index/status.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/status.js.es6 @@ -19,11 +19,8 @@ }, template: ` - - - -  {{pipeline.details.status.text}} - + + `, -- cgit v1.2.1 From 52a259dd84031819bc24638963ea1a12fe56fd30 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Sat, 24 Dec 2016 07:16:30 +0000 Subject: Revert "Merge branch 'fix-latest-pipeine-ordering' into 'master'" This reverts merge request !8286 --- app/models/ci/pipeline.rb | 7 +++++-- app/models/project.rb | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 6894a5763ff..f2f6453b3b9 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -93,8 +93,11 @@ module Ci .select("max(#{quoted_table_name}.id)") .group(:ref, :sha) - relation = ref ? where(ref: ref) : self - relation.where(id: max_id).order(id: :desc) + if ref + where(id: max_id, ref: ref) + else + where(id: max_id) + end end def self.latest_status(ref = nil) diff --git a/app/models/project.rb b/app/models/project.rb index 72fdd4514c4..26fa20f856d 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -418,7 +418,7 @@ class Project < ActiveRecord::Base repository.commit(ref) end - # ref can't be HEAD or SHA, can only be branch/tag name + # ref can't be HEAD, can only be branch/tag name or SHA def latest_successful_builds_for(ref = default_branch) latest_pipeline = pipelines.latest_successful_for(ref) -- cgit v1.2.1 From d72b40423c6736fd24ef4371604897871a1b3acc Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 21 Dec 2016 19:31:30 +0200 Subject: Rename projects with reserved path names We cant have project with name 'project' or 'tree' anymore. This merge request containts a migration that will find and rename all projects using reserved names by adding N digit to the end of the name. Signed-off-by: Dmitriy Zaporozhets --- app/models/project.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/models/project.rb b/app/models/project.rb index 26fa20f856d..5fd6c86fd70 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -921,7 +921,7 @@ class Project < ActiveRecord::Base Rails.logger.error "Project #{old_path_with_namespace} cannot be renamed because container registry tags are present" # we currently doesn't support renaming repository if it contains tags in container registry - raise Exception.new('Project cannot be renamed, because tags are present in its container registry') + raise StandardError.new('Project cannot be renamed, because tags are present in its container registry') end if gitlab_shell.mv_repository(repository_storage_path, old_path_with_namespace, new_path_with_namespace) @@ -948,7 +948,7 @@ class Project < ActiveRecord::Base # if we cannot move namespace directory we should rollback # db changes in order to prevent out of sync between db and fs - raise Exception.new('repository cannot be renamed') + raise StandardError.new('repository cannot be renamed') end Gitlab::AppLogger.info "Project was renamed: #{old_path_with_namespace} -> #{new_path_with_namespace}" -- cgit v1.2.1 From e56254d38ab4a3c3deeacadbc2388b76d932805d Mon Sep 17 00:00:00 2001 From: Regis Date: Sat, 24 Dec 2016 14:04:17 -0700 Subject: remove use of span for svg and status text --- app/assets/javascripts/vue_pipelines_index/status.js.es6 | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/status.js.es6 b/app/assets/javascripts/vue_pipelines_index/status.js.es6 index f8decb17ca8..edb24ced080 100644 --- a/app/assets/javascripts/vue_pipelines_index/status.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/status.js.es6 @@ -18,9 +18,12 @@ }, }, template: ` - - - + + `, -- cgit v1.2.1 From 655289dd337588ad55f41a156cdc2ac318227979 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Sat, 24 Dec 2016 12:24:00 +0800 Subject: Order only for latest_successful_for Feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8286#note_20461082 --- app/models/ci/pipeline.rb | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'app') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index f2f6453b3b9..abbbddaa4f6 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -93,11 +93,8 @@ module Ci .select("max(#{quoted_table_name}.id)") .group(:ref, :sha) - if ref - where(id: max_id, ref: ref) - else - where(id: max_id) - end + relation = ref ? where(ref: ref) : self + relation.where(id: max_id) end def self.latest_status(ref = nil) @@ -105,7 +102,7 @@ module Ci end def self.latest_successful_for(ref) - success.latest(ref).first + success.latest(ref).order(id: :desc).first end def self.truncate_sha(sha) -- cgit v1.2.1 From 7b4b3d5f268534c028f55ef1014a84fe6a916cb0 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 13 Dec 2016 20:59:39 +0200 Subject: Include group parents into read access for project and group Signed-off-by: Dmitriy Zaporozhets --- app/models/group.rb | 18 ++++++++++++++---- app/policies/group_policy.rb | 2 +- app/policies/project_policy.rb | 2 +- 3 files changed, 16 insertions(+), 6 deletions(-) (limited to 'app') diff --git a/app/models/group.rb b/app/models/group.rb index ac8a82c8c1e..50c949d84aa 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -155,15 +155,17 @@ class Group < Namespace end def has_owner?(user) - owners.include?(user) + members_with_parents.owners.where(user_id: user).any? end def has_master?(user) - members.masters.where(user_id: user).any? + members_with_parents.masters.where(user_id: user).any? end + # Check if user is a last owner of the group. + # Parent owners are ignored for nested groups. def last_owner?(user) - has_owner?(user) && owners.size == 1 + owners.include?(user) && owners.size == 1 end def avatar_type @@ -189,6 +191,14 @@ class Group < Namespace end def refresh_members_authorized_projects - UserProjectAccessChangedService.new(users.pluck(:id)).execute + UserProjectAccessChangedService.new(users_with_parents.pluck(:id)).execute + end + + def members_with_parents + GroupMember.where(requested_at: nil, source_id: parents.map(&:id).push(id)) + end + + def users_with_parents + User.where(id: members_with_parents.pluck(:user_id)) end end diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb index 6f943feb2a7..0be6e113655 100644 --- a/app/policies/group_policy.rb +++ b/app/policies/group_policy.rb @@ -4,7 +4,7 @@ class GroupPolicy < BasePolicy return unless @user globally_viewable = @subject.public? || (@subject.internal? && !@user.external?) - member = @subject.users.include?(@user) + member = @subject.users_with_parents.include?(@user) owner = @user.admin? || @subject.has_owner?(@user) master = owner || @subject.has_master?(@user) diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb index b5db9c12622..eaf3035dfe1 100644 --- a/app/policies/project_policy.rb +++ b/app/policies/project_policy.rb @@ -245,7 +245,7 @@ class ProjectPolicy < BasePolicy def project_group_member?(user) project.group && ( - project.group.members.exists?(user_id: user.id) || + project.group.members_with_parents.exists?(user_id: user.id) || project.group.requesters.exists?(user_id: user.id) ) end -- cgit v1.2.1 From 9410f215eab0ba49051d2a00f0b4174f5dc13a6f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Dec 2016 11:56:19 +0200 Subject: Add nested groups support to the Groups::CreateService Signed-off-by: Dmitriy Zaporozhets --- app/services/groups/create_service.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'app') diff --git a/app/services/groups/create_service.rb b/app/services/groups/create_service.rb index 2bccd584dde..9a630aee626 100644 --- a/app/services/groups/create_service.rb +++ b/app/services/groups/create_service.rb @@ -12,6 +12,19 @@ module Groups return @group end + parent_id = params[:parent_id] + + if parent_id + parent = Group.find(parent_id) + + unless can?(current_user, :admin_group, parent) + @group.parent_id = nil + @group.errors.add(:parent_id, 'manage access required to create subgroup') + + return @group + end + end + @group.name ||= @group.path.dup @group.save @group.add_owner(current_user) -- cgit v1.2.1 From 10de4e3bb612a529480c93da53849d95e98a8633 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Dec 2016 12:51:48 +0200 Subject: Show nested groups tab on group page Signed-off-by: Dmitriy Zaporozhets --- app/controllers/groups_controller.rb | 2 ++ app/views/groups/show.html.haml | 10 ++++++++++ 2 files changed, 12 insertions(+) (limited to 'app') diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index efe9c001bcf..e061df2f819 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -42,6 +42,8 @@ class GroupsController < Groups::ApplicationController @notification_setting = current_user.notification_settings_for(group) end + @nested_groups = group.children + setup_projects respond_to do |format| diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml index 52ce26a20b1..a3cd333373e 100644 --- a/app/views/groups/show.html.haml +++ b/app/views/groups/show.html.haml @@ -32,6 +32,10 @@ %li = link_to "#shared", 'data-toggle' => 'tab' do Shared Projects + - if @nested_groups.present? + %li + = link_to "#groups", 'data-toggle' => 'tab' do + Nested Groups .nav-controls = form_tag request.path, method: :get, class: 'project-filter-form', id: 'project-filter-form' do |f| = search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control', spellcheck: false @@ -47,3 +51,9 @@ - if @shared_projects.present? .tab-pane#shared = render "shared_projects", projects: @shared_projects + + - if @nested_groups.present? + .tab-pane#groups + %ul.content-list + - @nested_groups.each do |group| + = render 'shared/groups/group', group: group -- cgit v1.2.1 From dd178bbe6ab851da9dceb2acf2f0336166f08b48 Mon Sep 17 00:00:00 2001 From: victorwu Date: Fri, 9 Dec 2016 22:37:28 -0600 Subject: In issue view, remove checking branches and new branch unavailable states --- app/assets/javascripts/issue.js | 3 --- app/views/projects/issues/_new_branch.html.haml | 3 --- 2 files changed, 6 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/issue.js b/app/assets/javascripts/issue.js index 63b70d4be17..61e8531153b 100644 --- a/app/assets/javascripts/issue.js +++ b/app/assets/javascripts/issue.js @@ -139,15 +139,12 @@ return; } return $.getJSON($container.data('path')).error(function() { - $container.find('.checking').hide(); $container.find('.unavailable').show(); return new Flash('Failed to check if a new branch can be created.', 'alert'); }).success(function(data) { if (data.can_create_branch) { - $container.find('.checking').hide(); $container.find('.available').show(); } else { - $container.find('.checking').hide(); return $container.find('.unavailable').show(); } }); diff --git a/app/views/projects/issues/_new_branch.html.haml b/app/views/projects/issues/_new_branch.html.haml index c56b6cc11f5..4589e112279 100644 --- a/app/views/projects/issues/_new_branch.html.haml +++ b/app/views/projects/issues/_new_branch.html.haml @@ -1,9 +1,6 @@ - if can?(current_user, :push_code, @project) .pull-right #new-branch.new-branch{'data-path' => can_create_branch_namespace_project_issue_path(@project.namespace, @project, @issue)} - = link_to '#', class: 'checking btn btn-grouped', disabled: 'disabled' do - = icon('spinner spin') - Checking branches = link_to namespace_project_branches_path(@project.namespace, @project, branch_name: @issue.to_branch_name, issue_iid: @issue.iid), method: :post, class: 'btn btn-new btn-inverted btn-grouped has-tooltip available hide', title: @issue.to_branch_name do New branch -- cgit v1.2.1 From 8cc5333420230d6a6f0a2c9844af9a1f1dc955ec Mon Sep 17 00:00:00 2001 From: victorwu Date: Thu, 15 Dec 2016 13:54:43 -0600 Subject: Replace wording for slash command confirmation message --- app/services/notes/create_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/services/notes/create_service.rb b/app/services/notes/create_service.rb index d75592e31f3..1beca9f4109 100644 --- a/app/services/notes/create_service.rb +++ b/app/services/notes/create_service.rb @@ -41,7 +41,7 @@ module Notes # We must add the error after we call #save because errors are reset # when #save is called if only_commands - note.errors.add(:commands_only, 'Your commands have been executed!') + note.errors.add(:commands_only, 'Commands applied') end note.commands_changes = command_params.keys -- cgit v1.2.1 From ed6900caf107ad0fc4580ad7dc000284d91683d4 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Mon, 26 Dec 2016 14:27:20 +0000 Subject: Use raw_diffs to calculate MR files changed We don't need to create the intermediate FileCollection object with its associated highlighting in order to count how many files changed. Both the compare object and the MR diff object have a raw_diffs method that is perfectly fine for this case. --- app/models/merge_request.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 5ce20cc43d6..22490d121c7 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -198,7 +198,9 @@ class MergeRequest < ActiveRecord::Base end def diff_size - diffs(diff_options).size + opts = diff_options || {} + + raw_diffs(opts).size end def diff_base_commit -- cgit v1.2.1 From 725ba04e0376c8909e75448f4407eca0fba6c807 Mon Sep 17 00:00:00 2001 From: Regis Date: Mon, 26 Dec 2016 14:24:15 -0700 Subject: wip --- .../javascripts/vue_pipelines_index/stage.js.es6 | 56 +++++++++++++++++++--- 1 file changed, 49 insertions(+), 7 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 index d214092f412..42d237cb2cc 100644 --- a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 @@ -3,6 +3,12 @@ ((gl) => { gl.VueStage = Vue.extend({ + data() { + return { + request: false, + builds: '
      ', + }; + }, props: ['stage', 'svgs', 'match'], computed: { buildStatus() { @@ -14,15 +20,51 @@ svg() { return this.svgs[this.match(this.stage.status.icon)]; }, + spanClass() { + return `ci-status-icon ci-status-icon-${this.stage.status.group}`; + }, }, template: ` - - +
      + +
      `, }); })(window.gl || (window.gl = {})); -- cgit v1.2.1 From 9b5bbf0a343d7730f08b61112d73579025f2208b Mon Sep 17 00:00:00 2001 From: Regis Date: Mon, 26 Dec 2016 14:34:03 -0700 Subject: add api call - get mock url next --- app/assets/javascripts/vue_pipelines_index/stage.js.es6 | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 index 42d237cb2cc..d5f7194979b 100644 --- a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 @@ -1,4 +1,4 @@ -/* global Vue, gl */ +/* global Vue, Flash, gl */ /* eslint-disable no-param-reassign */ ((gl) => { @@ -23,6 +23,17 @@ spanClass() { return `ci-status-icon ci-status-icon-${this.stage.status.group}`; }, + methods: { + fetchBuilds() { + this.$http.get(this.stage.status.endpoint) + .then((response) => { + Vue.set(this, 'builds', response.html); + Vue.set(this, 'response', true); + }, () => new Flash( + 'Something went wrong on our end.', + )); + }, + }, }, template: `
      -- cgit v1.2.1 From 8a7f58d21337b8858ae8e3e57f052eed1026687f Mon Sep 17 00:00:00 2001 From: Regis Date: Mon, 26 Dec 2016 14:59:48 -0700 Subject: mini-graph shows up from API call - need to fix state bugs --- .../javascripts/vue_pipelines_index/stage.js.es6 | 36 ++++++++++++++-------- 1 file changed, 24 insertions(+), 12 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 index d5f7194979b..944f84f7880 100644 --- a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 @@ -10,7 +10,28 @@ }; }, props: ['stage', 'svgs', 'match'], + methods: { + fetchBuilds() { + this.$http.get(this.endpoint) + .then((response) => { + this.builds = JSON.parse(response.body).html; + this.request = true; + }, () => new Flash( + 'Something went wrong on our end.', + )); + }, + clearState() { + this.response = false; + this.builds = '
        '; + }, + }, computed: { + endpoint() { + return '/gitlab-org/gitlab-shell/pipelines/121/stage?stage=deploy'; + }, + stageTitle() { + return 'deploy: running'; + }, buildStatus() { return `Build: ${this.stage.status.label}`; }, @@ -23,26 +44,17 @@ spanClass() { return `ci-status-icon ci-status-icon-${this.stage.status.group}`; }, - methods: { - fetchBuilds() { - this.$http.get(this.stage.status.endpoint) - .then((response) => { - Vue.set(this, 'builds', response.html); - Vue.set(this, 'response', true); - }, () => new Flash( - 'Something went wrong on our end.', - )); - }, - }, }, template: `
        -- cgit v1.2.1 From c9fad91d042453530bdb886f6df5ed3b7a2b7f8f Mon Sep 17 00:00:00 2001 From: Regis Date: Mon, 26 Dec 2016 15:29:03 -0700 Subject: remove v-if to let spinner show --- app/assets/javascripts/vue_pipelines_index/stage.js.es6 | 1 - 1 file changed, 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 index 5fcfae2375c..fe8e94ac7a7 100644 --- a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 @@ -84,7 +84,6 @@
        -- cgit v1.2.1 From e077cebe5003ff93671a147aad8266e5b0dbd04d Mon Sep 17 00:00:00 2001 From: Regis Date: Mon, 26 Dec 2016 16:09:27 -0700 Subject: add borderless svgs --- app/assets/javascripts/vue_pipelines_index/stage.js.es6 | 15 ++++++++------- app/views/projects/pipelines/index.html.haml | 8 ++++++++ 2 files changed, 16 insertions(+), 7 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 index fe8e94ac7a7..b7da52ad01b 100644 --- a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 @@ -16,9 +16,7 @@ this.$http.get(this.endpoint) .then((response) => { this.request = true; - setTimeout(() => { - this.builds = JSON.parse(response.body).html; - }, 100); + this.builds = JSON.parse(response.body).html; }, () => new Flash( 'Something went wrong on our end.', )); @@ -30,8 +28,7 @@ }, computed: { buildsOrSpinner() { - if (this.request) return this.builds; - return this.spinner; + return this.request ? this.builds : this.spinner; }, dropdownClass() { if (this.request) return 'js-builds-dropdown-container'; @@ -50,7 +47,9 @@ return `has-tooltip ci-status-icon-${this.stage.status.group}`; }, svg() { - return this.svgs[this.match(this.stage.status.icon)]; + const icon = this.stage.status.icon; + icon.replace('icon', 'stageIcon'); + return this.svgs[this.match(icon)]; }, spanClass() { return `ci-status-icon ci-status-icon-${this.stage.status.group}`; @@ -58,10 +57,10 @@ }, template: `
        + +
        `, }); diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index 5d7ffce78df..64d3665594e 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -49,6 +49,14 @@ "icon_status_success" => custom_icon("icon_status_success"), "icon_status_failed" => custom_icon("icon_status_failed"), "icon_status_warning" => custom_icon("icon_status_warning"), + "stage_icon_status_canceled" => custom_icon("icon_status_canceled_borderless"), + "stage_icon_status_running" => custom_icon("icon_status_running_borderless"), + "stage_icon_status_skipped" => custom_icon("icon_status_skipped_borderless"), + "stage_icon_status_created" => custom_icon("icon_status_created_borderless"), + "stage_icon_status_pending" => custom_icon("icon_status_pending_borderless"), + "stage_icon_status_success" => custom_icon("icon_status_success_borderless"), + "stage_icon_status_failed" => custom_icon("icon_status_failed_borderless"), + "stage_icon_status_warning" => custom_icon("icon_status_warning_borderless"), "icon_play" => custom_icon("icon_play"), "icon_timer" => custom_icon("icon_timer"), } } -- cgit v1.2.1 From b5f3c85458bc49522405e3cc19618df1ab6e6546 Mon Sep 17 00:00:00 2001 From: Victor Wu Date: Mon, 26 Dec 2016 23:15:10 +0000 Subject: Rename filename to file path in tooltip of file header in merge request diff --- app/views/projects/diffs/_file_header.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/projects/diffs/_file_header.html.haml b/app/views/projects/diffs/_file_header.html.haml index d3ed8e1bf38..90c9a0c6c2b 100644 --- a/app/views/projects/diffs/_file_header.html.haml +++ b/app/views/projects/diffs/_file_header.html.haml @@ -21,7 +21,7 @@ - if diff_file.deleted_file deleted - = clipboard_button(clipboard_text: diff_file.new_path, class: 'btn-clipboard btn-transparent prepend-left-5', title: 'Copy filename to clipboard') + = clipboard_button(clipboard_text: diff_file.new_path, class: 'btn-clipboard btn-transparent prepend-left-5', title: 'Copy file path to clipboard') - if diff_file.mode_changed? %small -- cgit v1.2.1 From 71d50042f45e9f04e80d1b54d310f0f8fb03bda4 Mon Sep 17 00:00:00 2001 From: Regis Date: Mon, 26 Dec 2016 16:50:57 -0700 Subject: add manual icon to svgs --- app/views/projects/pipelines/index.html.haml | 1 + 1 file changed, 1 insertion(+) (limited to 'app') diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index 64d3665594e..e423fc8c471 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -59,6 +59,7 @@ "stage_icon_status_warning" => custom_icon("icon_status_warning_borderless"), "icon_play" => custom_icon("icon_play"), "icon_timer" => custom_icon("icon_timer"), + "icon_status_manual" => custom_icon("icon_status_manual"), } } .vue-pipelines-index -- cgit v1.2.1 From b285abeccc3c466b8501d1333f7391be5d6f4334 Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Sat, 24 Dec 2016 16:53:13 +0000 Subject: Improved the u2f flow Added tests --- app/assets/javascripts/dispatcher.js.es6 | 11 +++ app/assets/javascripts/u2f/authenticate.js | 113 ----------------------- app/assets/javascripts/u2f/authenticate.js.es6 | 120 +++++++++++++++++++++++++ app/views/devise/sessions/two_factor.html.haml | 2 +- app/views/u2f/_authenticate.html.haml | 17 +--- 5 files changed, 136 insertions(+), 127 deletions(-) delete mode 100644 app/assets/javascripts/u2f/authenticate.js create mode 100644 app/assets/javascripts/u2f/authenticate.js.es6 (limited to 'app') diff --git a/app/assets/javascripts/dispatcher.js.es6 b/app/assets/javascripts/dispatcher.js.es6 index 78f68a247a2..1c1b6cd2dad 100644 --- a/app/assets/javascripts/dispatcher.js.es6 +++ b/app/assets/javascripts/dispatcher.js.es6 @@ -64,6 +64,17 @@ new UsernameValidator(); new ActiveTabMemoizer(); break; + case 'sessions:create': + if (!gon.u2f) break; + window.gl.u2fAuthenticate = new gl.U2FAuthenticate( + $("#js-authenticate-u2f"), + '#js-login-u2f-form', + gon.u2f, + document.querySelector('#js-login-2fa-device'), + document.querySelector('.js-2fa-form'), + ); + window.gl.u2fAuthenticate.start(); + break; case 'projects:boards:show': case 'projects:boards:index': shortcut_handler = new ShortcutsNavigation(); diff --git a/app/assets/javascripts/u2f/authenticate.js b/app/assets/javascripts/u2f/authenticate.js deleted file mode 100644 index e407b856e10..00000000000 --- a/app/assets/javascripts/u2f/authenticate.js +++ /dev/null @@ -1,113 +0,0 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, prefer-arrow-callback, no-else-return, quotes, quote-props, comma-dangle, one-var, one-var-declaration-per-line, padded-blocks, max-len */ -/* global u2f */ -/* global U2FError */ -/* global U2FUtil */ - -// Authenticate U2F (universal 2nd factor) devices for users to authenticate with. -// -// State Flow #1: setup -> in_progress -> authenticated -> POST to server -// State Flow #2: setup -> in_progress -> error -> setup -(function() { - var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; - - this.U2FAuthenticate = (function() { - function U2FAuthenticate(container, u2fParams) { - this.container = container; - this.renderNotSupported = bind(this.renderNotSupported, this); - this.renderAuthenticated = bind(this.renderAuthenticated, this); - this.renderError = bind(this.renderError, this); - this.renderInProgress = bind(this.renderInProgress, this); - this.renderSetup = bind(this.renderSetup, this); - this.renderTemplate = bind(this.renderTemplate, this); - this.authenticate = bind(this.authenticate, this); - this.start = bind(this.start, this); - this.appId = u2fParams.app_id; - this.challenge = u2fParams.challenge; - this.signRequests = u2fParams.sign_requests.map(function(request) { - // The U2F Javascript API v1.1 requires a single challenge, with - // _no challenges per-request_. The U2F Javascript API v1.0 requires a - // challenge per-request, which is done by copying the single challenge - // into every request. - // - // In either case, we don't need the per-request challenges that the server - // has generated, so we can remove them. - // - // Note: The server library fixes this behaviour in (unreleased) version 1.0.0. - // This can be removed once we upgrade. - // https://github.com/castle/ruby-u2f/commit/103f428071a81cd3d5f80c2e77d522d5029946a4 - return _(request).omit('challenge'); - }); - } - - U2FAuthenticate.prototype.start = function() { - if (U2FUtil.isU2FSupported()) { - return this.renderSetup(); - } else { - return this.renderNotSupported(); - } - }; - - U2FAuthenticate.prototype.authenticate = function() { - return u2f.sign(this.appId, this.challenge, this.signRequests, (function(_this) { - return function(response) { - var error; - if (response.errorCode) { - error = new U2FError(response.errorCode); - return _this.renderError(error); - } else { - return _this.renderAuthenticated(JSON.stringify(response)); - } - }; - })(this), 10); - }; - - // Rendering # - U2FAuthenticate.prototype.templates = { - "notSupported": "#js-authenticate-u2f-not-supported", - "setup": '#js-authenticate-u2f-setup', - "inProgress": '#js-authenticate-u2f-in-progress', - "error": '#js-authenticate-u2f-error', - "authenticated": '#js-authenticate-u2f-authenticated' - }; - - U2FAuthenticate.prototype.renderTemplate = function(name, params) { - var template, templateString; - templateString = $(this.templates[name]).html(); - template = _.template(templateString); - return this.container.html(template(params)); - }; - - U2FAuthenticate.prototype.renderSetup = function() { - this.renderTemplate('setup'); - return this.container.find('#js-login-u2f-device').on('click', this.renderInProgress); - }; - - U2FAuthenticate.prototype.renderInProgress = function() { - this.renderTemplate('inProgress'); - return this.authenticate(); - }; - - U2FAuthenticate.prototype.renderError = function(error) { - this.renderTemplate('error', { - error_message: error.message(), - error_code: error.errorCode - }); - return this.container.find('#js-u2f-try-again').on('click', this.renderSetup); - }; - - U2FAuthenticate.prototype.renderAuthenticated = function(deviceResponse) { - this.renderTemplate('authenticated'); - // Prefer to do this instead of interpolating using Underscore templates - // because of JSON escaping issues. - return this.container.find("#js-device-response").val(deviceResponse); - }; - - U2FAuthenticate.prototype.renderNotSupported = function() { - return this.renderTemplate('notSupported'); - }; - - return U2FAuthenticate; - - })(); - -}).call(this); diff --git a/app/assets/javascripts/u2f/authenticate.js.es6 b/app/assets/javascripts/u2f/authenticate.js.es6 new file mode 100644 index 00000000000..2b992109a8c --- /dev/null +++ b/app/assets/javascripts/u2f/authenticate.js.es6 @@ -0,0 +1,120 @@ +/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, prefer-arrow-callback, no-else-return, quotes, quote-props, comma-dangle, one-var, one-var-declaration-per-line, padded-blocks, max-len */ +/* global u2f */ +/* global U2FError */ +/* global U2FUtil */ + +// Authenticate U2F (universal 2nd factor) devices for users to authenticate with. +// +// State Flow #1: setup -> in_progress -> authenticated -> POST to server +// State Flow #2: setup -> in_progress -> error -> setup +(function() { + const global = window.gl || (window.gl = {}); + + var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + + global.U2FAuthenticate = (function() { + function U2FAuthenticate(container, form, u2fParams, fallbackButton, fallbackUI) { + this.container = container; + this.renderNotSupported = bind(this.renderNotSupported, this); + this.renderAuthenticated = bind(this.renderAuthenticated, this); + this.renderError = bind(this.renderError, this); + this.renderInProgress = bind(this.renderInProgress, this); + this.renderTemplate = bind(this.renderTemplate, this); + this.authenticate = bind(this.authenticate, this); + this.start = bind(this.start, this); + this.appId = u2fParams.app_id; + this.challenge = u2fParams.challenge; + this.form = form; + this.fallbackButton = fallbackButton; + this.fallbackUI = fallbackUI; + if (this.fallbackButton) this.fallbackButton.addEventListener('click', this.switchToFallbackUI.bind(this)); + this.signRequests = u2fParams.sign_requests.map(function(request) { + // The U2F Javascript API v1.1 requires a single challenge, with + // _no challenges per-request_. The U2F Javascript API v1.0 requires a + // challenge per-request, which is done by copying the single challenge + // into every request. + // + // In either case, we don't need the per-request challenges that the server + // has generated, so we can remove them. + // + // Note: The server library fixes this behaviour in (unreleased) version 1.0.0. + // This can be removed once we upgrade. + // https://github.com/castle/ruby-u2f/commit/103f428071a81cd3d5f80c2e77d522d5029946a4 + return _(request).omit('challenge'); + }); + } + + U2FAuthenticate.prototype.start = function() { + if (U2FUtil.isU2FSupported()) { + return this.renderInProgress(); + } else { + return this.renderNotSupported(); + } + }; + + U2FAuthenticate.prototype.authenticate = function() { + return u2f.sign(this.appId, this.challenge, this.signRequests, (function(_this) { + return function(response) { + var error; + if (response.errorCode) { + error = new U2FError(response.errorCode); + return _this.renderError(error); + } else { + return _this.renderAuthenticated(JSON.stringify(response)); + } + }; + })(this), 10); + }; + + // Rendering # + U2FAuthenticate.prototype.templates = { + "notSupported": "#js-authenticate-u2f-not-supported", + "setup": '#js-authenticate-u2f-setup', + "inProgress": '#js-authenticate-u2f-in-progress', + "error": '#js-authenticate-u2f-error', + "authenticated": '#js-authenticate-u2f-authenticated' + }; + + U2FAuthenticate.prototype.renderTemplate = function(name, params) { + var template, templateString; + templateString = $(this.templates[name]).html(); + template = _.template(templateString); + return this.container.html(template(params)); + }; + + U2FAuthenticate.prototype.renderInProgress = function() { + this.renderTemplate('inProgress'); + return this.authenticate(); + }; + + U2FAuthenticate.prototype.renderError = function(error) { + this.renderTemplate('error', { + error_message: error.message(), + error_code: error.errorCode + }); + return this.container.find('#js-u2f-try-again').on('click', this.renderInProgress); + }; + + U2FAuthenticate.prototype.renderAuthenticated = function(deviceResponse) { + this.renderTemplate('authenticated'); + const container = this.container[0]; + container.querySelector('#js-device-response').value = deviceResponse; + container.querySelector(this.form).submit(); + this.fallbackButton.classList.add('hidden'); + }; + + U2FAuthenticate.prototype.renderNotSupported = function() { + return this.renderTemplate('notSupported'); + }; + + U2FAuthenticate.prototype.switchToFallbackUI = function() { + this.fallbackButton.classList.add('hidden'); + this.container[0].classList.add('hidden'); + this.fallbackUI.classList.remove('hidden'); + }; + + return U2FAuthenticate; + + })(); + +})(); diff --git a/app/views/devise/sessions/two_factor.html.haml b/app/views/devise/sessions/two_factor.html.haml index 2cadc424668..951f03083bf 100644 --- a/app/views/devise/sessions/two_factor.html.haml +++ b/app/views/devise/sessions/two_factor.html.haml @@ -7,7 +7,7 @@ .login-box .login-body - if @user.two_factor_otp_enabled? - = form_for(resource, as: resource_name, url: session_path(resource_name), method: :post, html: { class: 'edit_user gl-show-field-errors' }) do |f| + = form_for(resource, as: resource_name, url: session_path(resource_name), method: :post, html: { class: "edit_user gl-show-field-errors js-2fa-form #{'hidden' if @user.two_factor_u2f_enabled?}" }) do |f| - resource_params = params[resource_name].presence || params = f.hidden_field :remember_me, value: resource_params.fetch(:remember_me, 0) %div diff --git a/app/views/u2f/_authenticate.html.haml b/app/views/u2f/_authenticate.html.haml index fa998c91f72..f878bece2fa 100644 --- a/app/views/u2f/_authenticate.html.haml +++ b/app/views/u2f/_authenticate.html.haml @@ -1,30 +1,21 @@ #js-authenticate-u2f +%a.btn.btn-block.btn-info#js-login-2fa-device{ href: '#' } Sign in via 2FA code %script#js-authenticate-u2f-not-supported{ type: "text/template" } %p Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer). -%script#js-authenticate-u2f-setup{ type: "text/template" } - %div - %p Insert your security key (if you haven't already), and press the button below. - %a.btn.btn-info#js-login-u2f-device{ href: 'javascript:void(0)' } Sign in via U2F device - %script#js-authenticate-u2f-in-progress{ type: "text/template" } %p Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now. %script#js-authenticate-u2f-error{ type: "text/template" } %div %p <%= error_message %> (error code: <%= error_code %>) - %a.btn.btn-warning#js-u2f-try-again Try again? + %a.btn.btn-block.btn-warning#js-u2f-try-again Try again? %script#js-authenticate-u2f-authenticated{ type: "text/template" } %div - %p We heard back from your U2F device. Click this button to authenticate with the GitLab server. - = form_tag(new_user_session_path, method: :post) do |f| + %p We heard back from your U2F device. You have been authenticated. + = form_tag(new_user_session_path, method: :post, id: 'js-login-u2f-form') do |f| - resource_params = params[resource_name].presence || params = hidden_field_tag 'user[remember_me]', resource_params.fetch(:remember_me, 0) = hidden_field_tag 'user[device_response]', nil, class: 'form-control', required: true, id: "js-device-response" - = submit_tag "Authenticate via U2F Device", class: "btn btn-success" - -:javascript - var u2fAuthenticate = new U2FAuthenticate($("#js-authenticate-u2f"), gon.u2f); - u2fAuthenticate.start(); -- cgit v1.2.1 From 1b14182f21a60384234e79b3a0f02c81d016192d Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 27 Dec 2016 12:48:01 +0100 Subject: Expose stage dropdown path and title in stage entity --- app/serializers/stage_entity.rb | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/serializers/stage_entity.rb b/app/serializers/stage_entity.rb index b57202a6267..1aebba3a2d1 100644 --- a/app/serializers/stage_entity.rb +++ b/app/serializers/stage_entity.rb @@ -3,17 +3,35 @@ class StageEntity < Grape::Entity expose :name - expose :status do |stage, options| - StatusEntity.represent( - stage.detailed_status(request.user), - options) + expose :title do |stage| + "#{stage.name}: #{detailed_status.label}" end + expose :detailed_status, as: :status, + with: StatusEntity + expose :path do |stage| namespace_project_pipeline_path( stage.pipeline.project.namespace, stage.pipeline.project, - stage.pipeline.id, + stage.pipeline, anchor: stage.name) end + + expose :dropdown_path do |stage| + stage_namespace_project_pipeline_path( + stage.pipeline.project.namespace, + stage.pipeline.project, + stage.pipeline, + stage: stage.name, + format: :json) + end + + private + + alias_method :stage, :object + + def detailed_status + stage.detailed_status(request.user) + end end -- cgit v1.2.1 From 589fd93d489cfa9e40ee265be69ab1ad95deb6e1 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 27 Dec 2016 14:37:17 +0100 Subject: Fix Rubocop offenses in serializer entities --- app/serializers/stage_entity.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/serializers/stage_entity.rb b/app/serializers/stage_entity.rb index 1aebba3a2d1..7a047bdc712 100644 --- a/app/serializers/stage_entity.rb +++ b/app/serializers/stage_entity.rb @@ -7,7 +7,8 @@ class StageEntity < Grape::Entity "#{stage.name}: #{detailed_status.label}" end - expose :detailed_status, as: :status, + expose :detailed_status, + as: :status, with: StatusEntity expose :path do |stage| -- cgit v1.2.1 From 6c953fe12c7b2fcabbef83850aeccb6cc94d6fed Mon Sep 17 00:00:00 2001 From: Jose Ivan Vargas Date: Thu, 22 Dec 2016 13:22:57 -0600 Subject: Changed the label font size from 13px to 12px odd sizes don't mix well with windows and some linux system fonts --- app/assets/stylesheets/framework/tw_bootstrap.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/tw_bootstrap.scss b/app/assets/stylesheets/framework/tw_bootstrap.scss index 55bc325b858..28cbae9a449 100644 --- a/app/assets/stylesheets/framework/tw_bootstrap.scss +++ b/app/assets/stylesheets/framework/tw_bootstrap.scss @@ -91,7 +91,7 @@ // Labels .label { padding: 4px 5px; - font-size: 13px; + font-size: 12px; font-style: normal; font-weight: normal; display: inline-block; -- cgit v1.2.1 From dca0a42a95d4757f6caeb1fc8866c7ebc570744b Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Tue, 20 Dec 2016 17:58:04 -0500 Subject: Truncate tag description and fix mobile for inidividual tag --- app/assets/stylesheets/framework/common.scss | 16 ++++++++++ app/assets/stylesheets/framework/lists.scss | 5 +++ app/assets/stylesheets/framework/nav.scss | 47 +++++++++++++++++++++------- app/views/projects/tags/_tag.html.haml | 41 ++++++++++++------------ app/views/projects/tags/index.html.haml | 6 ++-- app/views/projects/tags/show.html.haml | 16 +++++----- 6 files changed, 90 insertions(+), 41 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss index 251e43d2edd..5e3a91af86e 100644 --- a/app/assets/stylesheets/framework/common.scss +++ b/app/assets/stylesheets/framework/common.scss @@ -57,6 +57,11 @@ pre { border-radius: 0; color: $well-pre-color; } + + &.wrap { + word-break: break-word; + white-space: pre-wrap; + } } hr { @@ -67,6 +72,17 @@ hr { @include str-truncated; } +.block-truncated { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + + > div, + .str-truncated { + display: inline; + } +} + .item-title { font-weight: 600; } /** FLASH message **/ diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss index e96cd671e34..edc0c4ff094 100644 --- a/app/assets/stylesheets/framework/lists.scss +++ b/app/assets/stylesheets/framework/lists.scss @@ -208,6 +208,11 @@ ul.content-list { padding-right: 8px; } + .row-fixed-content { + flex: 0 0 auto; + margin-left: auto; + } + .row-title { font-weight: 600; } diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index bbf9de06630..4f84bc37f90 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -165,6 +165,8 @@ padding: 11px 0; margin-bottom: 0; + > .btn, + > .btn-container, > .dropdown { margin-right: $gl-padding-top; display: inline-block; @@ -172,16 +174,7 @@ &:last-child { margin-right: 0; - } - } - - > .btn { - margin-right: $gl-padding-top; - display: inline-block; - vertical-align: top; - - &:last-child { - margin-right: 0; + float: right; } } @@ -427,4 +420,36 @@ border-bottom: none; } } -} \ No newline at end of file +} + +@media (max-width: $screen-xs-max) { + .top-area .nav-controls { + $controls-margin: $btn-xs-side-margin - 2px; + + &.controls-flex { + display: flex; + flex-flow: row wrap; + align-items: center; + justify-content: center; + padding: 0 0 $gl-padding-top; + } + + .controls-item, + .controls-item:last-child { + flex: 1 1 35%; + display: block; + width: 100%; + margin: $controls-margin; + + .btn, + .dropdown { + margin: 0; + } + } + + .controls-item-full { + @extend .controls-item; + flex: 1 1 100%; + } + } +} diff --git a/app/views/projects/tags/_tag.html.haml b/app/views/projects/tags/_tag.html.haml index c42641afea0..8ef069b9e05 100644 --- a/app/views/projects/tags/_tag.html.haml +++ b/app/views/projects/tags/_tag.html.haml @@ -1,7 +1,7 @@ - commit = @repository.commit(tag.dereferenced_target) - release = @releases.find { |release| release.tag == tag.name } -%li - %div +%li.flex-row + .row-main-content.str-truncated = link_to namespace_project_tag_path(@project.namespace, @project, tag.name) do %span.item-title = icon('tag') @@ -10,24 +10,25 @@   = strip_gpg_signature(tag.message) - .controls - = render 'projects/buttons/download', project: @project, ref: tag.name + - if commit + .block-truncated + = render 'projects/branches/commit', commit: commit, project: @project + - else + %p + Cant find HEAD commit for this tag + - if release && release.description.present? + .description.prepend-top-default + .wiki + = preserve do + = markdown_field(release, :description) - - if can?(current_user, :push_code, @project) - = link_to edit_namespace_project_tag_release_path(@project.namespace, @project, tag.name), class: 'btn has-tooltip', title: "Edit release notes", data: { container: "body" } do - = icon("pencil") + .row-fixed-content.controls + = render 'projects/buttons/download', project: @project, ref: tag.name - - if can?(current_user, :admin_project, @project) - = link_to namespace_project_tag_path(@project.namespace, @project, tag.name), class: 'btn btn-remove remove-row has-tooltip', title: "Delete tag", method: :delete, data: { confirm: "Deleting the '#{tag.name}' tag cannot be undone. Are you sure?", container: 'body' }, remote: true do - = icon("trash-o") + - if can?(current_user, :push_code, @project) + = link_to edit_namespace_project_tag_release_path(@project.namespace, @project, tag.name), class: 'btn has-tooltip', title: "Edit release notes", data: { container: "body" } do + = icon("pencil") - - if commit - = render 'projects/branches/commit', commit: commit, project: @project - - else - %p - Cant find HEAD commit for this tag - - if release && release.description.present? - .description.prepend-top-default - .wiki - = preserve do - = markdown_field(release, :description) + - if can?(current_user, :admin_project, @project) + = link_to namespace_project_tag_path(@project.namespace, @project, tag.name), class: 'btn btn-remove remove-row has-tooltip', title: "Delete tag", method: :delete, data: { confirm: "Deleting the '#{tag.name}' tag cannot be undone. Are you sure?", container: 'body' }, remote: true do + = icon("trash-o") diff --git a/app/views/projects/tags/index.html.haml b/app/views/projects/tags/index.html.haml index 1d39f3a7534..d52162a5de8 100644 --- a/app/views/projects/tags/index.html.haml +++ b/app/views/projects/tags/index.html.haml @@ -11,8 +11,8 @@ = form_tag(filter_tags_path, method: :get) do = search_field_tag :search, params[:search], { placeholder: 'Filter by tag name', id: 'tag-search', class: 'form-control search-text-input input-short', spellcheck: false } - .dropdown.inline - %button.dropdown-toggle{ type: 'button', data: { toggle: 'dropdown'} } + .dropdown + %button.dropdown-toggle.btn{ type: 'button', data: { toggle: 'dropdown'} } %span.light = projects_sort_options_hash[@sort] = icon('chevron-down') @@ -30,7 +30,7 @@ .tags - if @tags.any? - %ul.content-list + %ul.flex-list.content-list = render partial: 'tag', collection: @tags = paginate @tags, theme: 'gitlab' diff --git a/app/views/projects/tags/show.html.haml b/app/views/projects/tags/show.html.haml index 12facb6eb73..a8d462132c6 100644 --- a/app/views/projects/tags/show.html.haml +++ b/app/views/projects/tags/show.html.haml @@ -12,21 +12,23 @@ - else Cant find HEAD commit for this tag - .nav-controls + .nav-controls.controls-flex - if can?(current_user, :push_code, @project) - = link_to edit_namespace_project_tag_release_path(@project.namespace, @project, @tag.name), class: 'btn has-tooltip', title: 'Edit release notes' do + = link_to edit_namespace_project_tag_release_path(@project.namespace, @project, @tag.name), class: 'btn controls-item has-tooltip', title: 'Edit release notes' do = icon("pencil") - = link_to namespace_project_tree_path(@project.namespace, @project, @tag.name), class: 'btn has-tooltip', title: 'Browse files' do + = link_to namespace_project_tree_path(@project.namespace, @project, @tag.name), class: 'btn controls-item has-tooltip', title: 'Browse files' do = icon('files-o') - = link_to namespace_project_commits_path(@project.namespace, @project, @tag.name), class: 'btn has-tooltip', title: 'Browse commits' do + = link_to namespace_project_commits_path(@project.namespace, @project, @tag.name), class: 'btn controls-item has-tooltip', title: 'Browse commits' do = icon('history') - = render 'projects/buttons/download', project: @project, ref: @tag.name + .btn-container.controls-item + = render 'projects/buttons/download', project: @project, ref: @tag.name - if can?(current_user, :admin_project, @project) - .pull-right + .btn-container.controls-item-full = link_to namespace_project_tag_path(@project.namespace, @project, @tag.name), class: 'btn btn-remove remove-row has-tooltip', title: "Delete tag", method: :delete, data: { confirm: "Deleting the '#{@tag.name}' tag cannot be undone. Are you sure?" } do %i.fa.fa-trash-o + - if @tag.message.present? - %pre.body + %pre.wrap = strip_gpg_signature(@tag.message) .append-bottom-default.prepend-top-default -- cgit v1.2.1 From 6328ec3ab2595722afb780a9b60b44ef4c0bcac2 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Tue, 27 Dec 2016 11:26:25 -0600 Subject: Only limit container width on issues & MRs within fixed-width container --- app/assets/stylesheets/pages/issuable.scss | 60 +++++++++++++++--------------- 1 file changed, 31 insertions(+), 29 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index eeb5b590625..9478b66f536 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -1,48 +1,50 @@ // Limit MR description for side-by-side diff view -.limit-container-width { - .detail-page-header { - max-width: calc(#{$limited-layout-width} - (#{$gl-padding} * 2)); - margin-left: auto; - margin-right: auto; - } - - .issuable-details { - .detail-page-description, - .mr-source-target, - .mr-state-widget, - .merge-manually { +.container-limited { + &.limit-container-width { + .detail-page-header { max-width: calc(#{$limited-layout-width} - (#{$gl-padding} * 2)); margin-left: auto; margin-right: auto; } - .merge-request-tabs-holder { - &.affix { - border-bottom: 1px solid $border-color; + .issuable-details { + .detail-page-description, + .mr-source-target, + .mr-state-widget, + .merge-manually { + max-width: calc(#{$limited-layout-width} - (#{$gl-padding} * 2)); + margin-left: auto; + margin-right: auto; + } + + .merge-request-tabs-holder { + &.affix { + border-bottom: 1px solid $border-color; + + .nav-links { + border: 0; + } + } - .nav-links { - border: 0; + .container-fluid { + padding-left: 0; + padding-right: 0; + max-width: calc(#{$limited-layout-width} - (#{$gl-padding} * 2)); + margin-left: auto; + margin-right: auto; } } + } - .container-fluid { - padding-left: 0; - padding-right: 0; + .diffs { + .mr-version-controls, + .files-changed { max-width: calc(#{$limited-layout-width} - (#{$gl-padding} * 2)); margin-left: auto; margin-right: auto; } } } - - .diffs { - .mr-version-controls, - .files-changed { - max-width: calc(#{$limited-layout-width} - (#{$gl-padding} * 2)); - margin-left: auto; - margin-right: auto; - } - } } .issuable-details { -- cgit v1.2.1 From 6a110c00b52b0e312f06249c5fd597f39ababe87 Mon Sep 17 00:00:00 2001 From: Regis Date: Tue, 27 Dec 2016 11:15:19 -0700 Subject: hook up new API key values to stage dropdown mini graph in vue --- app/assets/javascripts/vue_pipelines_index/stage.js.es6 | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 index b7da52ad01b..026fba80ca2 100644 --- a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 @@ -13,7 +13,7 @@ props: ['stage', 'svgs', 'match'], methods: { fetchBuilds() { - this.$http.get(this.endpoint) + this.$http.get(this.stage.dropdown_path) .then((response) => { this.request = true; this.builds = JSON.parse(response.body).html; @@ -34,12 +34,6 @@ if (this.request) return 'js-builds-dropdown-container'; return 'js-builds-dropdown-loading builds-dropdown-loading'; }, - endpoint() { - return '/gitlab-org/gitlab-shell/pipelines/121/stage?stage=deploy'; - }, - stageTitle() { - return 'deploy: running'; - }, buildStatus() { return `Build: ${this.stage.status.label}`; }, @@ -63,7 +57,7 @@ @click='fetchBuilds' class="has-tooltip builds-dropdown js-builds-dropdown-button" data-placement="top" - :title='stageTitle' + :title='stage.title' data-toggle="dropdown" type="button" > -- cgit v1.2.1 From 5e558af7a0cb77f58271b02039966ecf6c8df84c Mon Sep 17 00:00:00 2001 From: Regis Date: Tue, 27 Dec 2016 11:42:55 -0700 Subject: remove mini-graph js from dispatcher for pipelines:index --- app/assets/javascripts/dispatcher.js.es6 | 5 ----- 1 file changed, 5 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/dispatcher.js.es6 b/app/assets/javascripts/dispatcher.js.es6 index a118003617d..6a84f52d8df 100644 --- a/app/assets/javascripts/dispatcher.js.es6 +++ b/app/assets/javascripts/dispatcher.js.es6 @@ -173,11 +173,6 @@ new TreeView(); } break; - case 'projects:pipelines:index': - // new gl.MiniPipelineGraph({ - // container: '.js-pipeline-table', - // }); - break; case 'projects:pipelines:builds': case 'projects:pipelines:show': const { controllerAction } = document.querySelector('.js-pipeline-container').dataset; -- cgit v1.2.1 From 75bddd01d0b611fcd45e8a9789e7f8e650e5850b Mon Sep 17 00:00:00 2001 From: Regis Date: Tue, 27 Dec 2016 12:24:11 -0700 Subject: avoid making multiple calls on blur on collapse click events --- app/assets/javascripts/vue_pipelines_index/stage.js.es6 | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 index 026fba80ca2..920ae5dac9a 100644 --- a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/stage.js.es6 @@ -13,7 +13,13 @@ props: ['stage', 'svgs', 'match'], methods: { fetchBuilds() { - this.$http.get(this.stage.dropdown_path) + if (this.request) { + this.request = false; + this.builds = ''; + return null; + } + + return this.$http.get(this.stage.dropdown_path) .then((response) => { this.request = true; this.builds = JSON.parse(response.body).html; @@ -55,6 +61,7 @@