From 36fdbc6edb1c0884f68c1267902b33a78d7be6ae Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Tue, 26 Apr 2016 13:21:48 +0100 Subject: Updated contrib map away from cal heat map --- app/assets/javascripts/calendar.js.coffee | 106 ++++++++++++++++++++----- app/assets/stylesheets/framework/calendar.scss | 30 +++++++ app/views/users/calendar.html.haml | 2 - 3 files changed, 114 insertions(+), 24 deletions(-) diff --git a/app/assets/javascripts/calendar.js.coffee b/app/assets/javascripts/calendar.js.coffee index d80e0e716ce..ec153f61c2a 100644 --- a/app/assets/javascripts/calendar.js.coffee +++ b/app/assets/javascripts/calendar.js.coffee @@ -1,27 +1,75 @@ class @Calendar constructor: (timestamps, starting_year, starting_month, calendar_activities_path) -> - cal = new CalHeatMap() - cal.init - itemName: ["contribution"] - data: timestamps - start: new Date(starting_year, starting_month) - domainLabelFormat: "%b" - id: "cal-heatmap" - domain: "month" - subDomain: "day" - range: 12 - tooltip: true - label: - position: "top" - legend: [ - 0 - 10 - 20 - 30 - ] - legendCellPadding: 3 - cellSize: $('.user-calendar').width() / 73 - onClick: (date, count) -> + # Get the highest value from the timestampes + highestValue = 0 + _.each timestamps, (count) -> + if count > highestValue + highestValue = count + + timestamps = _.chain(timestamps) + .map (stamp, key) -> + { + count: stamp + date: key + } + .groupBy (stamp, i) -> + Math.floor i / 7 + .toArray() + .value() + + monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] + months = [] + svg = d3.select '#cal-heatmap' + .append 'svg' + .attr 'width', 53 * 17 + .attr 'height', 140 + + # Setup each day box + svg.selectAll 'g' + .data timestamps + .enter() + .append 'g' + .attr 'transform', (group, i) -> + _.each group, (stamp) -> + month = new Date(parseInt(stamp.date) * 1000).getMonth() + x = 17 * i + 1 + lastMonth = _.last(months) + + # If undefined, push + if !lastMonth? + months.push + month: month + x: x + else if lastMonth.x is x + lastMonth.month = month + else if lastMonth.month isnt month + months.push + month: month + x: x + "translate(#{17 * i + 1}, 18)" + .selectAll 'rect' + .data (stamp) -> + stamp + .enter() + .append 'rect' + .attr 'x', '0' + .attr 'y', (stamp, i) -> + 17 * i + .attr 'width', 15 + .attr 'height', 15 + .attr 'title', (stamp) -> + "#{stamp.count} contributions
#{gl.utils.formatDate parseInt(stamp.date) * 1000}" + .attr 'class', (stamp) -> + extraClass = '' + if stamp.count isnt 0 + diff = stamp.count / highestValue + classNumber = Math.floor (diff / 0.25) + 1 + extraClass += "user-contrib-cell-#{classNumber}" + + "user-contrib-cell #{extraClass} js-tooltip" + .attr 'data-container', 'body' + .on 'click', (stamp) -> + date = new Date(parseInt(stamp.date) * 1000) formated_date = date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate() $.ajax url: calendar_activities_path @@ -32,3 +80,17 @@ class @Calendar success: (data) -> $(".user-calendar-activities").html data + svg.append 'g' + .selectAll 'text' + .data months + .enter() + .append 'text' + .attr 'x', (date) -> + date.x + .attr 'y', 10 + .attr 'class', 'user-contrib-text' + .text (date) -> + monthNames[date.month] + + $('#cal-heatmap .js-tooltip').tooltip + html: true diff --git a/app/assets/stylesheets/framework/calendar.scss b/app/assets/stylesheets/framework/calendar.scss index 11f39d583bd..da03454d807 100644 --- a/app/assets/stylesheets/framework/calendar.scss +++ b/app/assets/stylesheets/framework/calendar.scss @@ -68,3 +68,33 @@ font-weight: 550; } } + +.user-contrib-cell { + fill: #ededed; + cursor: pointer; + + &:hover { + stroke: #000; + } +} + +.user-contrib-cell-1 { + fill: #acd5f2; +} + +.user-contrib-cell-3 { + fill: #7fa8d1; +} + +.user-contrib-cell-4 { + fill: #49729b; +} + +.user-contrib-cell-5 { + fill: #254e77; +} + +.user-contrib-text { + font-size: 12px; + fill: #959494; +} diff --git a/app/views/users/calendar.html.haml b/app/views/users/calendar.html.haml index 1de71f37d1a..2abee8be2a6 100644 --- a/app/views/users/calendar.html.haml +++ b/app/views/users/calendar.html.haml @@ -6,5 +6,3 @@ #{@starting_month}, '#{user_calendar_activities_path}' ); - -.calendar-hint Summary of issues, merge requests, and push events -- cgit v1.2.1 From 18b361cf809251dd633e31d3dd6d877b31d8db7f Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Wed, 27 Apr 2016 11:07:46 +0100 Subject: Group the contributing calendar by day This aligns the boxes correctly with the day on the left side of the calendar --- app/assets/javascripts/application.js.coffee | 1 - app/assets/javascripts/calendar.js.coffee | 147 ++++++++++++++++++------- app/assets/stylesheets/application.scss | 1 - app/assets/stylesheets/framework/calendar.scss | 69 ++---------- app/assets/stylesheets/pages/profile.scss | 6 - app/controllers/users_controller.rb | 2 - app/views/users/calendar.html.haml | 17 +-- app/views/users/show.html.haml | 7 +- lib/gitlab/contributions_calendar.rb | 2 +- 9 files changed, 132 insertions(+), 120 deletions(-) diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee index bffce5a0c0f..ff69e27bbcf 100644 --- a/app/assets/javascripts/application.js.coffee +++ b/app/assets/javascripts/application.js.coffee @@ -19,7 +19,6 @@ #= require jquery.scrollTo #= require jquery.turbolinks #= require d3 -#= require cal-heatmap #= require turbolinks #= require autosave #= require bootstrap/affix diff --git a/app/assets/javascripts/calendar.js.coffee b/app/assets/javascripts/calendar.js.coffee index ec153f61c2a..9c4d529f7e9 100644 --- a/app/assets/javascripts/calendar.js.coffee +++ b/app/assets/javascripts/calendar.js.coffee @@ -1,52 +1,83 @@ class @Calendar - constructor: (timestamps, starting_year, starting_month, calendar_activities_path) -> + constructor: (timestamps, calendar_activities_path) -> # Get the highest value from the timestampes highestValue = 0 _.each timestamps, (count) -> if count > highestValue highestValue = count - timestamps = _.chain(timestamps) - .map (stamp, key) -> - { - count: stamp - date: key - } - .groupBy (stamp, i) -> - Math.floor i / 7 - .toArray() - .value() + # Loop through the timestamps to create a group of objects + # The group of objects will be grouped based on the day of the week they are + timestampsTmp = [] + i = 0 + group = 0 + _.each timestamps, (count, date) -> + newDate = new Date parseInt(date) * 1000 + day = newDate.getDay() + + # Create a new group array if this is the first day of the week + # or if is first object + if (day is 0 and i isnt 0) or i is 0 + timestampsTmp.push [] + group++ + + innerArray = timestampsTmp[group-1] + + # Push to the inner array the values that will be used to render map + innerArray.push + count: count + date: newDate + day: day + + i++ + + # Color function for chart + color = d3 + .scale + .linear() + .range(['#acd5f2', '#254e77']) + .domain([0, highestValue]) + + # Color function for key + colorKey = d3 + .scale + .linear() + .range(['#acd5f2', '#254e77']) + .domain([0, 3]) + keyColors = ['#ededed', colorKey(0), colorKey(1), colorKey(2), colorKey(3)] monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] months = [] - svg = d3.select '#cal-heatmap' + svg = d3.select '.js-contrib-calendar' .append 'svg' - .attr 'width', 53 * 17 - .attr 'height', 140 + .attr 'width', 54 * 17 + .attr 'height', 167 + .attr 'class', 'contrib-calendar' # Setup each day box svg.selectAll 'g' - .data timestamps + .data timestampsTmp .enter() .append 'g' .attr 'transform', (group, i) -> - _.each group, (stamp) -> - month = new Date(parseInt(stamp.date) * 1000).getMonth() - x = 17 * i + 1 - lastMonth = _.last(months) + _.each group, (stamp, a) -> + if a is 0 and stamp.day is 0 + month = stamp.date.getMonth() + x = (17 * i + 1) + 17 + lastMonth = _.last(months) + if lastMonth? + lastMonthX = lastMonth.x - # If undefined, push - if !lastMonth? - months.push - month: month - x: x - else if lastMonth.x is x - lastMonth.month = month - else if lastMonth.month isnt month + if !lastMonth? months.push month: month x: x - "translate(#{17 * i + 1}, 18)" + else if month isnt lastMonth.month and x - 17 isnt lastMonthX + months.push + month: month + x: x + + "translate(#{(17 * i + 1) + 17}, 18)" .selectAll 'rect' .data (stamp) -> stamp @@ -54,22 +85,20 @@ class @Calendar .append 'rect' .attr 'x', '0' .attr 'y', (stamp, i) -> - 17 * i + (17 * stamp.day) .attr 'width', 15 .attr 'height', 15 .attr 'title', (stamp) -> - "#{stamp.count} contributions
#{gl.utils.formatDate parseInt(stamp.date) * 1000}" - .attr 'class', (stamp) -> - extraClass = '' + "#{stamp.count} contributions
#{gl.utils.formatDate stamp.date}" + .attr 'class', 'user-contrib-cell js-tooltip' + .attr 'fill', (stamp) -> if stamp.count isnt 0 - diff = stamp.count / highestValue - classNumber = Math.floor (diff / 0.25) + 1 - extraClass += "user-contrib-cell-#{classNumber}" - - "user-contrib-cell #{extraClass} js-tooltip" + color(stamp.count) + else + '#ededed' .attr 'data-container', 'body' .on 'click', (stamp) -> - date = new Date(parseInt(stamp.date) * 1000) + date = stamp.date formated_date = date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate() $.ajax url: calendar_activities_path @@ -80,6 +109,7 @@ class @Calendar success: (data) -> $(".user-calendar-activities").html data + # Month titles svg.append 'g' .selectAll 'text' .data months @@ -92,5 +122,44 @@ class @Calendar .text (date) -> monthNames[date.month] - $('#cal-heatmap .js-tooltip').tooltip + # Day titles + days = [{ + text: 'M' + y: 29 + (17 * 1) + }, { + text: 'W' + y: 29 + (17 * 3) + }, { + text: 'F' + y: 29 + (17 * 5) + }] + svg.append 'g' + .selectAll 'text' + .data days + .enter() + .append 'text' + .attr 'text-anchor', 'middle' + .attr 'x', 8 + .attr 'y', (day) -> + day.y + .text (day) -> + day.text + .attr 'class', 'user-contrib-text' + + # Key with color boxes + svg.append 'g' + .attr 'transform', "translate(18, #{17 * 8 + 16})" + .selectAll 'rect' + .data keyColors + .enter() + .append 'rect' + .attr 'width', 15 + .attr 'height', 15 + .attr 'x', (color, i) -> + 17 * i + .attr 'y', 0 + .attr 'fill', (color) -> + color + + $('.js-contrib-calendar .js-tooltip').tooltip html: true diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 69b3b6586de..efdb2b06a8c 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -8,7 +8,6 @@ *= require select2 *= require_self *= require dropzone/basic - *= require cal-heatmap *= require cropper.css *= require animate */ diff --git a/app/assets/stylesheets/framework/calendar.scss b/app/assets/stylesheets/framework/calendar.scss index da03454d807..5b48801485b 100644 --- a/app/assets/stylesheets/framework/calendar.scss +++ b/app/assets/stylesheets/framework/calendar.scss @@ -26,75 +26,28 @@ } } -/** -* This overwrites the default values of the cal-heatmap gem -*/ -.calendar { - .qi { - fill: #fff; - } - - .q1 { - fill: #ededed !important; - } - - .q2 { - fill: #acd5f2 !important; - } - - .q3 { - fill: #7fa8d1 !important; - } - - .q4 { - fill: #49729b !important; - } - - .q5 { - fill: #254e77 !important; - } - - .future { - visibility: hidden; - } - - .domain-background { - fill: none; - shape-rendering: crispedges; - } +.user-calendar { + text-align: center; - .ch-tooltip { - padding: 3px; - font-weight: 550; + .calendar { + display: inline-block; } } .user-contrib-cell { - fill: #ededed; - cursor: pointer; - &:hover { + cursor: pointer; stroke: #000; } } -.user-contrib-cell-1 { - fill: #acd5f2; -} - -.user-contrib-cell-3 { - fill: #7fa8d1; -} - -.user-contrib-cell-4 { - fill: #49729b; -} - -.user-contrib-cell-5 { - fill: #254e77; -} - .user-contrib-text { font-size: 12px; fill: #959494; } + +.calendar-hint { + margin-top: -23px; + float: right; + font-size: 12px; +} diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss index 843379a3f54..ef375e1386c 100644 --- a/app/assets/stylesheets/pages/profile.scss +++ b/app/assets/stylesheets/pages/profile.scss @@ -66,12 +66,6 @@ } } -.calendar-hint { - margin-top: -12px; - float: right; - font-size: 12px; -} - .profile-link-holder { display: inline; diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 799421c185b..a99632454d9 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -74,8 +74,6 @@ class UsersController < ApplicationController def calendar calendar = contributions_calendar @timestamps = calendar.timestamps - @starting_year = calendar.starting_year - @starting_month = calendar.starting_month render 'calendar', layout: false end diff --git a/app/views/users/calendar.html.haml b/app/views/users/calendar.html.haml index 2abee8be2a6..77f2ddefb1e 100644 --- a/app/views/users/calendar.html.haml +++ b/app/views/users/calendar.html.haml @@ -1,8 +1,9 @@ -#cal-heatmap.calendar - :javascript - new Calendar( - #{@timestamps.to_json}, - #{@starting_year}, - #{@starting_month}, - '#{user_calendar_activities_path}' - ); +.clearfix.calendar + .js-contrib-calendar + .calendar-hint + Summary of issues, merge requests, and push events +:javascript + new Calendar( + #{@timestamps.to_json}, + '#{user_calendar_activities_path}' + ); diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index 9017fd54fcc..0c513308308 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -89,10 +89,9 @@ .tab-content #activity.tab-pane .row-content-block.calender-block.white.second-block.hidden-xs - %div{ class: container_class } - .user-calendar{data: {href: user_calendar_path}} - %h4.center.light - %i.fa.fa-spinner.fa-spin + .user-calendar{data: {href: user_calendar_path}} + %h4.center.light + %i.fa.fa-spinner.fa-spin .user-calendar-activities .content_list{ data: {href: user_path} } diff --git a/lib/gitlab/contributions_calendar.rb b/lib/gitlab/contributions_calendar.rb index 85583dce9ee..9dc2602867e 100644 --- a/lib/gitlab/contributions_calendar.rb +++ b/lib/gitlab/contributions_calendar.rb @@ -19,7 +19,7 @@ module Gitlab select('date(created_at) as date, count(id) as total_amount'). map(&:attributes) - dates = (1.year.ago.to_date..(Date.today + 1.day)).to_a + dates = (1.year.ago.to_date..Date.today).to_a dates.each do |date| date_id = date.to_time.to_i.to_s -- cgit v1.2.1 From c3de94404099193c0ca6551ef149da1522adacd1 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Wed, 27 Apr 2016 11:09:40 +0100 Subject: Removed cal heatmap from gemfile --- Gemfile | 3 --- Gemfile.lock | 2 -- 2 files changed, 5 deletions(-) diff --git a/Gemfile b/Gemfile index 6949c16e966..ba1ae9cf900 100644 --- a/Gemfile +++ b/Gemfile @@ -177,9 +177,6 @@ gem 'ruby-fogbugz', '~> 0.2.1' # d3 gem 'd3_rails', '~> 3.5.0' -#cal-heatmap -gem 'cal-heatmap-rails', '~> 3.6.0' - # underscore-rails gem "underscore-rails", "~> 1.8.0" diff --git a/Gemfile.lock b/Gemfile.lock index 4b51bf58bba..b1cd5ab4b17 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -99,7 +99,6 @@ GEM bundler (~> 1.2) thor (~> 0.18) byebug (8.2.1) - cal-heatmap-rails (3.6.0) capybara (2.6.2) addressable mime-types (>= 1.16) @@ -902,7 +901,6 @@ DEPENDENCIES bullet bundler-audit byebug - cal-heatmap-rails (~> 3.6.0) capybara (~> 2.6.2) capybara-screenshot (~> 1.0.0) carrierwave (~> 0.10.0) -- cgit v1.2.1 From 1c9440c2cf171e919f3e7317e9a9827576f9aafd Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Wed, 27 Apr 2016 12:45:14 +0100 Subject: tests update --- features/steps/user.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/steps/user.rb b/features/steps/user.rb index b1d088f07f9..59385a6ab59 100644 --- a/features/steps/user.rb +++ b/features/steps/user.rb @@ -34,7 +34,7 @@ class Spinach::Features::User < Spinach::FeatureSteps end step 'I should see contributions calendar' do - expect(page).to have_css('.cal-heatmap-container') + expect(page).to have_css('.js-contrib-calendar') end def contributed_project -- cgit v1.2.1 From bef5695a81af7a0afbb7ebe30d8ce344afe824f5 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Wed, 27 Apr 2016 17:38:22 +0100 Subject: Formats tooltip title & date correctly Correctly changes the activity when clicking a date - will also revert back to old data when clicking date again --- app/assets/javascripts/calendar.js.coffee | 36 +++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/app/assets/javascripts/calendar.js.coffee b/app/assets/javascripts/calendar.js.coffee index 9c4d529f7e9..dd6adfe978f 100644 --- a/app/assets/javascripts/calendar.js.coffee +++ b/app/assets/javascripts/calendar.js.coffee @@ -1,5 +1,6 @@ class @Calendar constructor: (timestamps, calendar_activities_path) -> + currentSelectedDate = '' # Get the highest value from the timestampes highestValue = 0 _.each timestamps, (count) -> @@ -89,7 +90,14 @@ class @Calendar .attr 'width', 15 .attr 'height', 15 .attr 'title', (stamp) -> - "#{stamp.count} contributions
#{gl.utils.formatDate stamp.date}" + contribText = 'No contributions' + + if stamp.count > 0 + contribText = "#{stamp.count} contribution#{if stamp.count > 1 then 's' else ''}" + + date = dateFormat(stamp.date, 'mmm d, yyyy') + + "#{contribText}
#{date}" .attr 'class', 'user-contrib-cell js-tooltip' .attr 'fill', (stamp) -> if stamp.count isnt 0 @@ -98,16 +106,22 @@ class @Calendar '#ededed' .attr 'data-container', 'body' .on 'click', (stamp) -> - date = stamp.date - formated_date = date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate() - $.ajax - url: calendar_activities_path - data: - date: formated_date - cache: false - dataType: "html" - success: (data) -> - $(".user-calendar-activities").html data + if currentSelectedDate is '' + currentSelectedDate = stamp.date + formated_date = currentSelectedDate.getFullYear() + "-" + (currentSelectedDate.getMonth()+1) + "-" + currentSelectedDate.getDate() + + $.ajax + url: calendar_activities_path + data: + date: formated_date + cache: false + dataType: 'html' + success: (data) -> + $('.user-calendar-activities').html data + else + currentSelectedDate = '' + $('.user-calendar-activities, .content_list').html '' + Pager.getOld() # Month titles svg.append 'g' -- cgit v1.2.1 From 93c0bb8041963d6677cc9c169a0e1e22221dd0cb Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 28 Apr 2016 11:03:14 +0100 Subject: Fixed issue with selected date not loading correctly Added loading icon to selected date box --- app/assets/javascripts/calendar.js.coffee | 44 ++++++++++++++------------ app/assets/stylesheets/framework/calendar.scss | 16 ++-------- app/views/users/calendar_activities.html.haml | 42 +++++++++++++----------- 3 files changed, 49 insertions(+), 53 deletions(-) diff --git a/app/assets/javascripts/calendar.js.coffee b/app/assets/javascripts/calendar.js.coffee index dd6adfe978f..701117747d5 100644 --- a/app/assets/javascripts/calendar.js.coffee +++ b/app/assets/javascripts/calendar.js.coffee @@ -1,6 +1,10 @@ class @Calendar constructor: (timestamps, calendar_activities_path) -> currentSelectedDate = '' + daySpace = 1 + daySize = 15 + daySizeWithSpace = daySize + (daySpace * 2) + # Get the highest value from the timestampes highestValue = 0 _.each timestamps, (count) -> @@ -51,7 +55,7 @@ class @Calendar months = [] svg = d3.select '.js-contrib-calendar' .append 'svg' - .attr 'width', 54 * 17 + .attr 'width', 54 * daySizeWithSpace .attr 'height', 167 .attr 'class', 'contrib-calendar' @@ -64,7 +68,7 @@ class @Calendar _.each group, (stamp, a) -> if a is 0 and stamp.day is 0 month = stamp.date.getMonth() - x = (17 * i + 1) + 17 + x = (daySizeWithSpace * i + 1) + daySizeWithSpace lastMonth = _.last(months) if lastMonth? lastMonthX = lastMonth.x @@ -73,12 +77,12 @@ class @Calendar months.push month: month x: x - else if month isnt lastMonth.month and x - 17 isnt lastMonthX + else if month isnt lastMonth.month and x - daySizeWithSpace isnt lastMonthX months.push month: month x: x - "translate(#{(17 * i + 1) + 17}, 18)" + "translate(#{(daySizeWithSpace * i + 1) + daySizeWithSpace}, 18)" .selectAll 'rect' .data (stamp) -> stamp @@ -86,9 +90,9 @@ class @Calendar .append 'rect' .attr 'x', '0' .attr 'y', (stamp, i) -> - (17 * stamp.day) - .attr 'width', 15 - .attr 'height', 15 + (daySizeWithSpace * stamp.day) + .attr 'width', daySize + .attr 'height', daySize .attr 'title', (stamp) -> contribText = 'No contributions' @@ -106,22 +110,22 @@ class @Calendar '#ededed' .attr 'data-container', 'body' .on 'click', (stamp) -> - if currentSelectedDate is '' + if currentSelectedDate isnt stamp.date currentSelectedDate = stamp.date - formated_date = currentSelectedDate.getFullYear() + "-" + (currentSelectedDate.getMonth()+1) + "-" + currentSelectedDate.getDate() + formatted_date = currentSelectedDate.getFullYear() + "-" + (currentSelectedDate.getMonth()+1) + "-" + currentSelectedDate.getDate() $.ajax url: calendar_activities_path data: - date: formated_date + date: formatted_date cache: false dataType: 'html' + beforeSend: -> + $('.user-calendar-activities').html '
' success: (data) -> $('.user-calendar-activities').html data else - currentSelectedDate = '' - $('.user-calendar-activities, .content_list').html '' - Pager.getOld() + $('.user-calendar-activities').html '' # Month titles svg.append 'g' @@ -139,13 +143,13 @@ class @Calendar # Day titles days = [{ text: 'M' - y: 29 + (17 * 1) + y: 29 + (daySizeWithSpace * 1) }, { text: 'W' - y: 29 + (17 * 3) + y: 29 + (daySizeWithSpace * 3) }, { text: 'F' - y: 29 + (17 * 5) + y: 29 + (daySizeWithSpace * 5) }] svg.append 'g' .selectAll 'text' @@ -162,15 +166,15 @@ class @Calendar # Key with color boxes svg.append 'g' - .attr 'transform', "translate(18, #{17 * 8 + 16})" + .attr 'transform', "translate(18, #{daySizeWithSpace * 8 + 16})" .selectAll 'rect' .data keyColors .enter() .append 'rect' - .attr 'width', 15 - .attr 'height', 15 + .attr 'width', daySize + .attr 'height', daySize .attr 'x', (color, i) -> - 17 * i + daySizeWithSpace * i .attr 'y', 0 .attr 'fill', (color) -> color diff --git a/app/assets/stylesheets/framework/calendar.scss b/app/assets/stylesheets/framework/calendar.scss index 5b48801485b..81118b13bef 100644 --- a/app/assets/stylesheets/framework/calendar.scss +++ b/app/assets/stylesheets/framework/calendar.scss @@ -5,24 +5,12 @@ } .user-calendar-activities { - .calendar_onclick_hr { - padding: 0; - margin: 10px 0; - } - .str-truncated { max-width: 70%; } - .text-expander { - background: #eee; - color: #555; - padding: 0 5px; - cursor: pointer; - margin-left: 4px; - &:hover { - background-color: #ddd; - } + .user-calendar-activities-loading { + font-size: 24px; } } diff --git a/app/views/users/calendar_activities.html.haml b/app/views/users/calendar_activities.html.haml index 027a93a75fc..630d97e339d 100644 --- a/app/views/users/calendar_activities.html.haml +++ b/app/views/users/calendar_activities.html.haml @@ -1,23 +1,27 @@ %h4.prepend-top-20 - %span.light Contributions for + Contributions for %strong #{@calendar_date.to_s(:short)} -%ul.bordered-list - - @events.sort_by(&:created_at).each do |event| - %li - %span.light - %i.fa.fa-clock-o - = event.created_at.to_s(:time) - - if event.push? - #{event.action_name} #{event.ref_type} #{event.ref_name} - - else - = event_action_name(event) - - if event.target - %strong= link_to "##{event.target_iid}", [event.project.namespace.becomes(Namespace), event.project, event.target] - - at - %strong - - if event.project - = link_to_project event.project +- if @events.any? + %ul.bordered-list + - @events.sort_by(&:created_at).each do |event| + %li + %span.light + %i.fa.fa-clock-o + = event.created_at.to_s(:time) + - if event.push? + #{event.action_name} #{event.ref_type} #{event.ref_name} - else - = event.project_name + = event_action_name(event) + - if event.target + %strong= link_to "##{event.target_iid}", [event.project.namespace.becomes(Namespace), event.project, event.target] + + at + %strong + - if event.project + = link_to_project event.project + - else + = event.project_name +- else + %p + No contributions found for #{@calendar_date.to_s(:short)} -- cgit v1.2.1 From b54ea9de7c99df737d8f6fc358f8eb0ef8b20c76 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 28 Apr 2016 11:07:17 +0100 Subject: Updated spacing of the calendar --- app/assets/stylesheets/framework/calendar.scss | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/assets/stylesheets/framework/calendar.scss b/app/assets/stylesheets/framework/calendar.scss index 81118b13bef..8642b7530e2 100644 --- a/app/assets/stylesheets/framework/calendar.scss +++ b/app/assets/stylesheets/framework/calendar.scss @@ -1,4 +1,7 @@ .calender-block { + padding-left: 0; + padding-right: 0; + @media (min-width: $screen-sm-min) and (max-width: $screen-lg-min) { overflow-x: scroll; } -- cgit v1.2.1 From 527d64463530df5a2f5f800885f5f84920b1058b Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Mon, 16 May 2016 12:51:49 +0100 Subject: Moved into class methods --- app/assets/javascripts/calendar.js.coffee | 195 ++++++++++++++++-------------- 1 file changed, 105 insertions(+), 90 deletions(-) diff --git a/app/assets/javascripts/calendar.js.coffee b/app/assets/javascripts/calendar.js.coffee index 701117747d5..f9c7bffdadb 100644 --- a/app/assets/javascripts/calendar.js.coffee +++ b/app/assets/javascripts/calendar.js.coffee @@ -1,32 +1,34 @@ class @Calendar - constructor: (timestamps, calendar_activities_path) -> - currentSelectedDate = '' - daySpace = 1 - daySize = 15 - daySizeWithSpace = daySize + (daySpace * 2) + constructor: (timestamps, @calendar_activities_path) -> + @currentSelectedDate = '' + @daySpace = 1 + @daySize = 15 + @daySizeWithSpace = @daySize + (@daySpace * 2) + @monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] + @months = [] + @highestValue = 0 # Get the highest value from the timestampes - highestValue = 0 - _.each timestamps, (count) -> - if count > highestValue - highestValue = count + _.each timestamps, (count) => + if count > @highestValue + @highestValue = count # Loop through the timestamps to create a group of objects # The group of objects will be grouped based on the day of the week they are - timestampsTmp = [] + @timestampsTmp = [] i = 0 group = 0 - _.each timestamps, (count, date) -> + _.each timestamps, (count, date) => newDate = new Date parseInt(date) * 1000 day = newDate.getDay() # Create a new group array if this is the first day of the week # or if is first object if (day is 0 and i isnt 0) or i is 0 - timestampsTmp.push [] + @timestampsTmp.push [] group++ - innerArray = timestampsTmp[group-1] + innerArray = @timestampsTmp[group-1] # Push to the inner array the values that will be used to render map innerArray.push @@ -36,64 +38,61 @@ class @Calendar i++ - # Color function for chart - color = d3 - .scale - .linear() - .range(['#acd5f2', '#254e77']) - .domain([0, highestValue]) + # Init color functions + @color = @initColor() + @colorKey = @initColorKey() - # Color function for key - colorKey = d3 - .scale - .linear() - .range(['#acd5f2', '#254e77']) - .domain([0, 3]) - keyColors = ['#ededed', colorKey(0), colorKey(1), colorKey(2), colorKey(3)] + # Init the svg element + @renderSvg(group) + @renderDays() + @renderMonths() + @renderDayTitles() + @renderKey() + + @initTooltips() - monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] - months = [] - svg = d3.select '.js-contrib-calendar' + renderSvg: (group) -> + @svg = d3.select '.js-contrib-calendar' .append 'svg' - .attr 'width', 54 * daySizeWithSpace + .attr 'width', (group + 1) * @daySizeWithSpace .attr 'height', 167 .attr 'class', 'contrib-calendar' - # Setup each day box - svg.selectAll 'g' - .data timestampsTmp + renderDays: -> + @svg.selectAll 'g' + .data @timestampsTmp .enter() .append 'g' - .attr 'transform', (group, i) -> - _.each group, (stamp, a) -> + .attr 'transform', (group, i) => + _.each group, (stamp, a) => if a is 0 and stamp.day is 0 month = stamp.date.getMonth() - x = (daySizeWithSpace * i + 1) + daySizeWithSpace - lastMonth = _.last(months) + x = (@daySizeWithSpace * i + 1) + @daySizeWithSpace + lastMonth = _.last(@months) if lastMonth? lastMonthX = lastMonth.x if !lastMonth? - months.push + @months.push month: month x: x - else if month isnt lastMonth.month and x - daySizeWithSpace isnt lastMonthX - months.push + else if month isnt lastMonth.month and x - @daySizeWithSpace isnt lastMonthX + @months.push month: month x: x - "translate(#{(daySizeWithSpace * i + 1) + daySizeWithSpace}, 18)" + "translate(#{(@daySizeWithSpace * i + 1) + @daySizeWithSpace}, 18)" .selectAll 'rect' .data (stamp) -> stamp .enter() .append 'rect' .attr 'x', '0' - .attr 'y', (stamp, i) -> - (daySizeWithSpace * stamp.day) - .attr 'width', daySize - .attr 'height', daySize - .attr 'title', (stamp) -> + .attr 'y', (stamp, i) => + (@daySizeWithSpace * stamp.day) + .attr 'width', @daySize + .attr 'height', @daySize + .attr 'title', (stamp) => contribText = 'No contributions' if stamp.count > 0 @@ -103,55 +102,26 @@ class @Calendar "#{contribText}
#{date}" .attr 'class', 'user-contrib-cell js-tooltip' - .attr 'fill', (stamp) -> + .attr 'fill', (stamp) => if stamp.count isnt 0 - color(stamp.count) + @color(stamp.count) else '#ededed' .attr 'data-container', 'body' - .on 'click', (stamp) -> - if currentSelectedDate isnt stamp.date - currentSelectedDate = stamp.date - formatted_date = currentSelectedDate.getFullYear() + "-" + (currentSelectedDate.getMonth()+1) + "-" + currentSelectedDate.getDate() - - $.ajax - url: calendar_activities_path - data: - date: formatted_date - cache: false - dataType: 'html' - beforeSend: -> - $('.user-calendar-activities').html '
' - success: (data) -> - $('.user-calendar-activities').html data - else - $('.user-calendar-activities').html '' - - # Month titles - svg.append 'g' - .selectAll 'text' - .data months - .enter() - .append 'text' - .attr 'x', (date) -> - date.x - .attr 'y', 10 - .attr 'class', 'user-contrib-text' - .text (date) -> - monthNames[date.month] + .on 'click', @clickDay - # Day titles + renderDayTitles: -> days = [{ text: 'M' - y: 29 + (daySizeWithSpace * 1) + y: 29 + (@daySizeWithSpace * 1) }, { text: 'W' - y: 29 + (daySizeWithSpace * 3) + y: 29 + (@daySizeWithSpace * 3) }, { text: 'F' - y: 29 + (daySizeWithSpace * 5) + y: 29 + (@daySizeWithSpace * 5) }] - svg.append 'g' + @svg.append 'g' .selectAll 'text' .data days .enter() @@ -164,20 +134,65 @@ class @Calendar day.text .attr 'class', 'user-contrib-text' - # Key with color boxes - svg.append 'g' - .attr 'transform', "translate(18, #{daySizeWithSpace * 8 + 16})" + renderMonths: -> + @svg.append 'g' + .selectAll 'text' + .data @months + .enter() + .append 'text' + .attr 'x', (date) -> + date.x + .attr 'y', 10 + .attr 'class', 'user-contrib-text' + .text (date) => + @monthNames[date.month] + + renderKey: -> + keyColors = ['#ededed', @colorKey(0), @colorKey(1), @colorKey(2), @colorKey(3)] + @svg.append 'g' + .attr 'transform', "translate(18, #{@daySizeWithSpace * 8 + 16})" .selectAll 'rect' .data keyColors .enter() .append 'rect' - .attr 'width', daySize - .attr 'height', daySize - .attr 'x', (color, i) -> - daySizeWithSpace * i + .attr 'width', @daySize + .attr 'height', @daySize + .attr 'x', (color, i) => + @daySizeWithSpace * i .attr 'y', 0 .attr 'fill', (color) -> color + initColor: -> + d3.scale + .linear() + .range(['#acd5f2', '#254e77']) + .domain([0, @highestValue]) + + initColorKey: -> + d3.scale + .linear() + .range(['#acd5f2', '#254e77']) + .domain([0, 3]) + + clickDay: (stamp) -> + if @currentSelectedDate isnt stamp.date + @currentSelectedDate = stamp.date + formatted_date = @currentSelectedDate.getFullYear() + "-" + (@currentSelectedDate.getMonth()+1) + "-" + @currentSelectedDate.getDate() + + $.ajax + url: @calendar_activities_path + data: + date: formatted_date + cache: false + dataType: 'html' + beforeSend: -> + $('.user-calendar-activities').html '
' + success: (data) -> + $('.user-calendar-activities').html data + else + $('.user-calendar-activities').html '' + + initTooltips: -> $('.js-contrib-calendar .js-tooltip').tooltip html: true -- cgit v1.2.1 From 74b74e59327ef4e393b937d33ba10c43c1e1087b Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 17 May 2016 15:01:03 +0200 Subject: fix for import URL URI problem when URL contains a space --- lib/gitlab/import_url.rb | 6 +++++- spec/lib/gitlab/import_url_spec.rb | 21 +++++++++++++++++---- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/lib/gitlab/import_url.rb b/lib/gitlab/import_url.rb index d23b013c1f5..f1191cc3a50 100644 --- a/lib/gitlab/import_url.rb +++ b/lib/gitlab/import_url.rb @@ -1,7 +1,7 @@ module Gitlab class ImportUrl def initialize(url, credentials: nil) - @url = URI.parse(URI.encode(url)) + @url = URI.parse(encode(url)) @credentials = credentials end @@ -37,5 +37,9 @@ module Gitlab def valid_credentials? credentials && credentials.is_a?(Hash) && credentials.any? end + + def encode(url) + URI.decode(url).size < url.size ? url : URI.encode(url) + end end end diff --git a/spec/lib/gitlab/import_url_spec.rb b/spec/lib/gitlab/import_url_spec.rb index f758cb8693c..46029b121dc 100644 --- a/spec/lib/gitlab/import_url_spec.rb +++ b/spec/lib/gitlab/import_url_spec.rb @@ -3,19 +3,32 @@ require 'spec_helper' describe Gitlab::ImportUrl do let(:credentials) { { user: 'blah', password: 'password' } } + let(:url) { "https://github.com/me/project.git" } let(:import_url) do - Gitlab::ImportUrl.new("https://github.com/me/project.git", credentials: credentials) + described_class.new(url, credentials: credentials) end - describe :full_url do + describe 'full_url' do it { expect(import_url.full_url).to eq("https://blah:password@github.com/me/project.git") } end - describe :sanitized_url do + describe 'sanitized_url' do it { expect(import_url.sanitized_url).to eq("https://github.com/me/project.git") } end - describe :credentials do + describe 'credentials' do it { expect(import_url.credentials).to eq(credentials) } end + + context 'URL encoding' do + describe 'not encoded URL' do + let(:url) { "https://github.com/me/my project.git" } + it { expect(import_url.sanitized_url).to eq("https://github.com/me/my%20project.git") } + end + + describe 'already encoded URL' do + let(:url) { "https://github.com/me/my%20project.git" } + it { expect(import_url.sanitized_url).to eq("https://github.com/me/my%20project.git") } + end + end end -- cgit v1.2.1 From 8a91f3f27399745722fe527ee76ab18bc5b26245 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 17 May 2016 15:04:33 +0200 Subject: added CHANGELOG --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index 20e2fcb806c..bcf44b9a8d3 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -61,6 +61,7 @@ v 8.8.0 (unreleased) v 8.7.6 - Fix links on wiki pages for relative url setups. !4131 (Artem Sidorenko) + - Fix import by `Any Git URL` broken if the URL contains a space v 8.7.5 - Fix relative links in wiki pages. !4050 -- cgit v1.2.1 From 1cbc898223d2f9b78cb6494108d2aed00d19d00e Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 20 May 2016 18:50:16 -0500 Subject: Improve design of Pipeline view --- CHANGELOG | 1 + app/assets/stylesheets/pages/pipelines.scss | 26 ++++++++++++++++++--- app/views/projects/ci/commits/_commit.html.haml | 31 +++++++++++++------------ app/views/projects/commit/_ci_stage.html.haml | 1 + app/views/projects/pipelines/index.html.haml | 6 ++--- 5 files changed, 44 insertions(+), 21 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 67fca2c6f6d..0884ac1947d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -13,6 +13,7 @@ v 8.8.0 (unreleased) - Added inline diff styling for `change_title` system notes. (Adam Butler) - Project#open_branches has been cleaned up and no longer loads entire records into memory. - Escape HTML in commit titles in system note messages + - Improve design of Pipeline View - Fix creation of Ci::Commit object which can lead to pending, failed in some scenarios - Improve multiple branch push performance by memoizing permission checking - Log to application.log when an admin starts and stops impersonating a user diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 546176b65e4..87b0562c29a 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -1,4 +1,24 @@ -.pipeline-stage { - overflow: hidden; - text-overflow: ellipsis; +.pipelines { + .stage { + max-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .duration, .finished_at { + margin: 4px 0; + } + + .commit-title { + margin: 0; + } + + .controls { + white-space: nowrap; + } + + .btn { + margin: 4px; + } } diff --git a/app/views/projects/ci/commits/_commit.html.haml b/app/views/projects/ci/commits/_commit.html.haml index 13162b41f9b..2ea9333913c 100644 --- a/app/views/projects/ci/commits/_commit.html.haml +++ b/app/views/projects/ci/commits/_commit.html.haml @@ -12,10 +12,10 @@ · = link_to commit.short_sha, namespace_project_commit_path(@project.namespace, @project, commit.sha), class: "commit-id monospace"   - - if commit.latest? - %span.label.label-success latest - if commit.tag? %span.label.label-primary tag + - elsif commit.latest? + %span.label.label-success.has-tooltip{ title: 'Latest build for this branch' } latest - if commit.triggered? %span.label.label-primary triggered - if commit.yaml_errors.present? @@ -23,30 +23,33 @@ - if commit.builds.any?(&:stuck?) %span.label.label-warning stuck - %p - %span - - if commit_data = commit.commit_data - = link_to_gfm commit_data.title, namespace_project_commit_path(@project.namespace, @project, commit_data.id), class: "commit-row-message" - - else - Cant find HEAD commit for this branch + %p.commit-title + - if commit_data = commit.commit_data + = link_to_gfm truncate(commit_data.title, length: 60), namespace_project_commit_path(@project.namespace, @project, commit_data.id), class: "commit-row-message" + - else + Cant find HEAD commit for this branch - stages_status = commit.statuses.stages_status - stages.each do |stage| %td - - if status = stages_status[stage] - - tooltip = "#{stage.titleize}: #{status}" - %span.has-tooltip{ title: "#{tooltip}", class: "ci-status-icon-#{status}" } + - status = stages_status[stage] + - tooltip = "#{stage.titleize}: #{status || 'not found'}" + - if status + = link_to namespace_project_pipeline_path(@project.namespace, @project, commit.id, anchor: stage), class: "has-tooltip ci-status-icon-#{status || 'skipped'}", title: tooltip do = ci_icon_for_status(status) + - else + .light + \- %td - if commit.started_at && commit.finished_at - %p + %p.duration = icon("clock-o")   #{duration_in_words(commit.finished_at, commit.started_at)} - if commit.finished_at - %p + %p.finished_at = icon("calendar")   #{time_ago_with_tooltip(commit.finished_at)} @@ -67,11 +70,9 @@ %span #{build.name} - if can?(current_user, :update_pipeline, @project) -   - if commit.retryable? && commit.builds.failed.any? = link_to retry_namespace_project_pipeline_path(@project.namespace, @project, commit.id), class: 'btn has-tooltip', title: "Retry", method: :post do = icon("repeat") -   - if commit.active? = link_to cancel_namespace_project_pipeline_path(@project.namespace, @project, commit.id), class: 'btn btn-remove has-tooltip', title: "Cancel", method: :post do = icon("remove") diff --git a/app/views/projects/commit/_ci_stage.html.haml b/app/views/projects/commit/_ci_stage.html.haml index aaa318e1eb3..ae7bb01223e 100644 --- a/app/views/projects/commit/_ci_stage.html.haml +++ b/app/views/projects/commit/_ci_stage.html.haml @@ -1,6 +1,7 @@ %tr %th{colspan: 10} %strong + %a{name: stage} - status = statuses.latest.status %span{class: "ci-status-link ci-status-icon-#{status}"} = ci_icon_for_status(status) diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index 9d5b6d367c9..4e2e8190700 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -44,7 +44,7 @@ - else #{@scope.titleize} for this project -%ul.content-list +%ul.content-list.pipelines - stages = @pipelines.stages - if @pipelines.blank? %li @@ -56,8 +56,8 @@ %th ID %th Commit - stages.each do |stage| - %th - %span.pipeline-stage.has-tooltip{ title: "#{stage.titleize}" } + %th.stage + %span.has-tooltip{ title: "#{stage.titleize}" } = stage.titleize.pluralize %th %th -- cgit v1.2.1 From 8d0332368fba65f167f2109daf8a2184d781082b Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Sat, 21 May 2016 09:52:50 -0500 Subject: Improve status rendering --- app/views/projects/ci/commits/_commit.html.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/projects/ci/commits/_commit.html.haml b/app/views/projects/ci/commits/_commit.html.haml index 2ea9333913c..9c63510d864 100644 --- a/app/views/projects/ci/commits/_commit.html.haml +++ b/app/views/projects/ci/commits/_commit.html.haml @@ -36,10 +36,10 @@ - status = stages_status[stage] - tooltip = "#{stage.titleize}: #{status || 'not found'}" - if status - = link_to namespace_project_pipeline_path(@project.namespace, @project, commit.id, anchor: stage), class: "has-tooltip ci-status-icon-#{status || 'skipped'}", title: tooltip do + = link_to namespace_project_pipeline_path(@project.namespace, @project, commit.id, anchor: stage), class: "has-tooltip ci-status-icon-#{status}", title: tooltip do = ci_icon_for_status(status) - else - .light + .light.has-tooltip{ title: tooltip } \- %td -- cgit v1.2.1 From f2f345e6048f80e4d6510db102cd046fca43d4e4 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 23 May 2016 09:05:01 +0200 Subject: avoid encoding import url and delegate good format to user --- lib/gitlab/import_url.rb | 6 +----- spec/lib/gitlab/import_url_spec.rb | 12 ------------ 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/lib/gitlab/import_url.rb b/lib/gitlab/import_url.rb index f1191cc3a50..3cfbc17b89b 100644 --- a/lib/gitlab/import_url.rb +++ b/lib/gitlab/import_url.rb @@ -1,7 +1,7 @@ module Gitlab class ImportUrl def initialize(url, credentials: nil) - @url = URI.parse(encode(url)) + @url = URI.parse(url) @credentials = credentials end @@ -37,9 +37,5 @@ module Gitlab def valid_credentials? credentials && credentials.is_a?(Hash) && credentials.any? end - - def encode(url) - URI.decode(url).size < url.size ? url : URI.encode(url) - end end end diff --git a/spec/lib/gitlab/import_url_spec.rb b/spec/lib/gitlab/import_url_spec.rb index 46029b121dc..7948386b0e6 100644 --- a/spec/lib/gitlab/import_url_spec.rb +++ b/spec/lib/gitlab/import_url_spec.rb @@ -19,16 +19,4 @@ describe Gitlab::ImportUrl do describe 'credentials' do it { expect(import_url.credentials).to eq(credentials) } end - - context 'URL encoding' do - describe 'not encoded URL' do - let(:url) { "https://github.com/me/my project.git" } - it { expect(import_url.sanitized_url).to eq("https://github.com/me/my%20project.git") } - end - - describe 'already encoded URL' do - let(:url) { "https://github.com/me/my%20project.git" } - it { expect(import_url.sanitized_url).to eq("https://github.com/me/my%20project.git") } - end - end end -- cgit v1.2.1 From d83ce65c1a0a8bcec603faf342cd2d78075ffb8d Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 23 May 2016 09:11:21 +0200 Subject: fix changelog and merge --- CHANGELOG | 4 +++- lib/gitlab/url_sanitizer.rb | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 1c26692f3ab..21b383b200d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -83,9 +83,11 @@ v 8.8.0 - Allows MR authors to have the source branch removed when merging the MR. !2801 (Jeroen Jacobs) - When creating a .gitignore file a dropdown with templates will be provided +v 8.7.7 + - Fix import by `Any Git URL` broken if the URL contains a space + v 8.7.6 - Fix links on wiki pages for relative url setups. !4131 (Artem Sidorenko) - - Fix import by `Any Git URL` broken if the URL contains a space - Fix import from GitLab.com to a private instance failure. !4181 - Fix external imports not finding the import data. !4106 diff --git a/lib/gitlab/url_sanitizer.rb b/lib/gitlab/url_sanitizer.rb index c59d53b941a..7d02fe3c971 100644 --- a/lib/gitlab/url_sanitizer.rb +++ b/lib/gitlab/url_sanitizer.rb @@ -7,7 +7,7 @@ module Gitlab end def initialize(url, credentials: nil) - @url = Addressable::URI.parse(URI.encode(url)) + @url = Addressable::URI.parse(url) @credentials = credentials end -- cgit v1.2.1 From 66cebb6f61193a5fb4199b85580a312ed6d94b42 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sat, 21 May 2016 18:02:49 -0500 Subject: Remove `event_to_atom` helper --- app/helpers/events_helper.rb | 22 ---------------------- app/views/dashboard/projects/index.atom.builder | 4 +--- app/views/events/_event.atom.builder | 20 ++++++++++++++++++++ app/views/groups/show.atom.builder | 4 +--- app/views/projects/show.atom.builder | 4 +--- app/views/users/show.atom.builder | 4 +--- 6 files changed, 24 insertions(+), 34 deletions(-) create mode 100644 app/views/events/_event.atom.builder diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb index e1489381706..bfedcb1c42b 100644 --- a/app/helpers/events_helper.rb +++ b/app/helpers/events_helper.rb @@ -159,28 +159,6 @@ module EventsHelper "--broken encoding" end - def event_to_atom(xml, event) - if event.visible_to_user?(current_user) - xml.entry do - event_link = event_feed_url(event) - event_title = event_feed_title(event) - event_summary = event_feed_summary(event) - - xml.id "tag:#{request.host},#{event.created_at.strftime("%Y-%m-%d")}:#{event.id}" - xml.link href: event_link - xml.title truncate(event_title, length: 80) - xml.updated event.created_at.xmlschema - xml.media :thumbnail, width: "40", height: "40", url: image_url(avatar_icon(event.author_email)) - xml.author do |author| - xml.name event.author_name - xml.email event.author_email - end - - xml.summary(type: "xhtml") { |x| x << event_summary unless event_summary.nil? } - end - end - end - def event_row_class(event) if event.body? "event-block" diff --git a/app/views/dashboard/projects/index.atom.builder b/app/views/dashboard/projects/index.atom.builder index d4daf07c6c0..fb5be63b472 100644 --- a/app/views/dashboard/projects/index.atom.builder +++ b/app/views/dashboard/projects/index.atom.builder @@ -6,7 +6,5 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear xml.id dashboard_projects_url xml.updated @events[0].updated_at.xmlschema if @events[0] - @events.each do |event| - event_to_atom(xml, event) - end + xml << render(partial: 'events/event', collection: @events) if @events.any? end diff --git a/app/views/events/_event.atom.builder b/app/views/events/_event.atom.builder new file mode 100644 index 00000000000..7890e717aa7 --- /dev/null +++ b/app/views/events/_event.atom.builder @@ -0,0 +1,20 @@ +return unless event.visible_to_user?(current_user) + +xml.entry do + xml.id "tag:#{request.host},#{event.created_at.strftime("%Y-%m-%d")}:#{event.id}" + xml.link href: event_feed_url(event) + xml.title truncate(event_feed_title(event), length: 80) + xml.updated event.created_at.xmlschema + xml.media :thumbnail, width: "40", height: "40", url: image_url(avatar_icon(event.author_email)) + + xml.author do + xml.name event.author_name + xml.email event.author_email + end + + xml.summary(type: "xhtml") do |summary| + event_summary = event_feed_summary(event) + + summary << event_summary unless event_summary.nil? + end +end diff --git a/app/views/groups/show.atom.builder b/app/views/groups/show.atom.builder index c66b82bb484..b68bf444d27 100644 --- a/app/views/groups/show.atom.builder +++ b/app/views/groups/show.atom.builder @@ -6,7 +6,5 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear xml.id group_url(@group) xml.updated @events[0].updated_at.xmlschema if @events[0] - @events.each do |event| - event_to_atom(xml, event) - end + xml << render(@events) if @events.any? end diff --git a/app/views/projects/show.atom.builder b/app/views/projects/show.atom.builder index 9b3d3f069d9..11310d5e1e1 100644 --- a/app/views/projects/show.atom.builder +++ b/app/views/projects/show.atom.builder @@ -6,7 +6,5 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear xml.id namespace_project_url(@project.namespace, @project) xml.updated @events[0].updated_at.xmlschema if @events[0] - @events.each do |event| - event_to_atom(xml, event) - end + xml << render(@events) if @events.any? end diff --git a/app/views/users/show.atom.builder b/app/views/users/show.atom.builder index e9e466c6350..6c85e5f9fbd 100644 --- a/app/views/users/show.atom.builder +++ b/app/views/users/show.atom.builder @@ -6,7 +6,5 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear xml.id user_url(@user) xml.updated @events[0].updated_at.xmlschema if @events[0] - @events.each do |event| - event_to_atom(xml, event) - end + xml << render(@events) if @events.any? end -- cgit v1.2.1 From 692f11b05d6ec751d1944cb025812481345329a8 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sat, 21 May 2016 18:04:28 -0500 Subject: Render a collection for the Commits atom feed --- app/views/projects/commits/_commit.atom.builder | 14 ++++++++++++++ app/views/projects/commits/show.atom.builder | 15 +-------------- 2 files changed, 15 insertions(+), 14 deletions(-) create mode 100644 app/views/projects/commits/_commit.atom.builder diff --git a/app/views/projects/commits/_commit.atom.builder b/app/views/projects/commits/_commit.atom.builder new file mode 100644 index 00000000000..1657fb46163 --- /dev/null +++ b/app/views/projects/commits/_commit.atom.builder @@ -0,0 +1,14 @@ +xml.entry do + xml.id namespace_project_commit_url(@project.namespace, @project, id: commit.id) + xml.link href: namespace_project_commit_url(@project.namespace, @project, id: commit.id) + xml.title truncate(commit.title, length: 80) + xml.updated commit.committed_date.xmlschema + xml.media :thumbnail, width: "40", height: "40", url: image_url(avatar_icon(commit.author_email)) + + xml.author do |author| + xml.name commit.author_name + xml.email commit.author_email + end + + xml.summary markdown(commit.description, pipeline: :single_line) +end diff --git a/app/views/projects/commits/show.atom.builder b/app/views/projects/commits/show.atom.builder index e310fafd82c..30bb7412073 100644 --- a/app/views/projects/commits/show.atom.builder +++ b/app/views/projects/commits/show.atom.builder @@ -6,18 +6,5 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear xml.id namespace_project_commits_url(@project.namespace, @project, @ref) xml.updated @commits.first.committed_date.xmlschema if @commits.any? - @commits.each do |commit| - xml.entry do - xml.id namespace_project_commit_url(@project.namespace, @project, id: commit.id) - xml.link href: namespace_project_commit_url(@project.namespace, @project, id: commit.id) - xml.title truncate(commit.title, length: 80) - xml.updated commit.committed_date.xmlschema - xml.media :thumbnail, width: "40", height: "40", url: image_url(avatar_icon(commit.author_email)) - xml.author do |author| - xml.name commit.author_name - xml.email commit.author_email - end - xml.summary markdown(commit.description, pipeline: :single_line) - end - end + xml << render(@commits) if @commits.any? end -- cgit v1.2.1 From 7001842dc463f1ba9ac4f1479c7310c75707c35b Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Mon, 23 May 2016 17:06:26 -0400 Subject: Remove `issue_to_atom` helper --- app/helpers/issues_helper.rb | 17 ----------------- app/views/dashboard/issues.atom.builder | 5 +---- app/views/groups/issues.atom.builder | 5 +---- app/views/issues/_issue.atom.builder | 14 ++++++++++++++ app/views/projects/issues/index.atom.builder | 4 +--- 5 files changed, 17 insertions(+), 28 deletions(-) create mode 100644 app/views/issues/_issue.atom.builder diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index 198d39455d7..551409e8855 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -105,23 +105,6 @@ module IssuesHelper return 'hidden' if issue.closed? == closed end - def issue_to_atom(xml, issue) - xml.entry do - xml.id namespace_project_issue_url(issue.project.namespace, - issue.project, issue) - xml.link href: namespace_project_issue_url(issue.project.namespace, - issue.project, issue) - xml.title truncate(issue.title, length: 80) - xml.updated issue.created_at.xmlschema - xml.media :thumbnail, width: "40", height: "40", url: image_url(avatar_icon(issue.author_email)) - xml.author do |author| - xml.name issue.author_name - xml.email issue.author_email - end - xml.summary issue.title - end - end - def merge_requests_sentence(merge_requests) # Sorting based on the `!123` or `group/project!123` reference will sort # local merge requests first. diff --git a/app/views/dashboard/issues.atom.builder b/app/views/dashboard/issues.atom.builder index 0d7b1b30dc3..83c0c6da21b 100644 --- a/app/views/dashboard/issues.atom.builder +++ b/app/views/dashboard/issues.atom.builder @@ -6,8 +6,5 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear xml.id issues_dashboard_url xml.updated @issues.first.created_at.xmlschema if @issues.any? - @issues.each do |issue| - issue_to_atom(xml, issue) - end + xml << render(partial: 'issues/issue', collection: @issues) if @issues.any? end - diff --git a/app/views/groups/issues.atom.builder b/app/views/groups/issues.atom.builder index a6eb9abada6..c19671295af 100644 --- a/app/views/groups/issues.atom.builder +++ b/app/views/groups/issues.atom.builder @@ -6,8 +6,5 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear xml.id issues_group_url xml.updated @issues.first.created_at.xmlschema if @issues.any? - @issues.each do |issue| - issue_to_atom(xml, issue) - end + xml << render(partial: 'issues/issue', collection: @issues) if @issues.any? end - diff --git a/app/views/issues/_issue.atom.builder b/app/views/issues/_issue.atom.builder new file mode 100644 index 00000000000..68a2d19e58d --- /dev/null +++ b/app/views/issues/_issue.atom.builder @@ -0,0 +1,14 @@ +xml.entry do + xml.id namespace_project_issue_url(issue.project.namespace, issue.project, issue) + xml.link href: namespace_project_issue_url(issue.project.namespace, issue.project, issue) + xml.title truncate(issue.title, length: 80) + xml.updated issue.created_at.xmlschema + xml.media :thumbnail, width: "40", height: "40", url: image_url(avatar_icon(issue.author_email)) + + xml.author do |author| + xml.name issue.author_name + xml.email issue.author_email + end + + xml.summary issue.title +end diff --git a/app/views/projects/issues/index.atom.builder b/app/views/projects/issues/index.atom.builder index ee8a9414657..7ad7c9c87e8 100644 --- a/app/views/projects/issues/index.atom.builder +++ b/app/views/projects/issues/index.atom.builder @@ -6,7 +6,5 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear xml.id namespace_project_issues_url(@project.namespace, @project) xml.updated @issues.first.created_at.xmlschema if @issues.any? - @issues.each do |issue| - issue_to_atom(xml, issue) - end + xml << render(partial: 'issues/issue', collection: @issues) if @issues.any? end -- cgit v1.2.1 From b2c411710d80a8d801876ec406f1c6035cc5b23f Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Tue, 24 May 2016 10:59:59 -0500 Subject: Increase max-width of stage cells --- app/assets/stylesheets/pages/pipelines.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 87b0562c29a..ce917a471c7 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -1,6 +1,6 @@ .pipelines { .stage { - max-width: 0; + max-width: 80px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; -- cgit v1.2.1 From 4c058fc429a4173e033a4babcb379c52b5ed13e3 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Tue, 24 May 2016 12:16:37 -0500 Subject: Remove icons from tables; remove timestamp from pipelines, remove info block at top of pipelines --- app/assets/stylesheets/framework/nav.scss | 2 +- app/assets/stylesheets/pages/merge_requests.scss | 6 ------ app/assets/stylesheets/pages/pipelines.scss | 2 +- app/views/projects/ci/builds/_build.html.haml | 4 ---- app/views/projects/ci/commits/_commit.html.haml | 7 ------- .../generic_commit_statuses/_generic_commit_status.html.haml | 4 ---- app/views/projects/pipelines/index.html.haml | 10 +--------- 7 files changed, 3 insertions(+), 32 deletions(-) diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index c70be58f48f..afb0cd1a1e6 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -281,7 +281,7 @@ } .page-with-layout-nav { - margin-top: 50px; + margin-top: $header-height + 2; &.controls-dropdown-visible { @media (max-width: $screen-xs-min) { diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index c4005ba1e69..4f8a8748d3f 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -280,11 +280,5 @@ background-color: $white-light; color: $gl-placeholder-color; } - - th, - td { - padding: 16px; - } } } - diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index ce917a471c7..6128868b670 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -1,6 +1,6 @@ .pipelines { .stage { - max-width: 80px; + max-width: 100px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; diff --git a/app/views/projects/ci/builds/_build.html.haml b/app/views/projects/ci/builds/_build.html.haml index e23a3782c6b..5bd6e3f0ebc 100644 --- a/app/views/projects/ci/builds/_build.html.haml +++ b/app/views/projects/ci/builds/_build.html.haml @@ -57,14 +57,10 @@ %td.duration - if build.duration - = icon("clock-o") -   #{duration_in_words(build.finished_at, build.started_at)} %td.timestamp - if build.finished_at - = icon("calendar") -   %span #{time_ago_with_tooltip(build.finished_at)} - if defined?(coverage) && coverage diff --git a/app/views/projects/ci/commits/_commit.html.haml b/app/views/projects/ci/commits/_commit.html.haml index 9c63510d864..5b6b940a0c4 100644 --- a/app/views/projects/ci/commits/_commit.html.haml +++ b/app/views/projects/ci/commits/_commit.html.haml @@ -45,14 +45,7 @@ %td - if commit.started_at && commit.finished_at %p.duration - = icon("clock-o") -   #{duration_in_words(commit.finished_at, commit.started_at)} - - if commit.finished_at - %p.finished_at - = icon("calendar") -   - #{time_ago_with_tooltip(commit.finished_at)} %td .controls.hidden-xs.pull-right 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 8129514964a..8be124f387a 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 @@ -50,14 +50,10 @@ %td.duration - if generic_commit_status.duration - = icon("clock-o") -   #{duration_in_words(generic_commit_status.finished_at, generic_commit_status.started_at)} %td.timestamp - if generic_commit_status.finished_at - = icon("calendar") -   %span #{time_ago_with_tooltip(generic_commit_status.finished_at)} - if defined?(coverage) && coverage diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index 4e2e8190700..a6c12814adf 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -36,14 +36,6 @@ = icon('wrench') %span CI Lint -.row-content-block - - if @scope == 'running' - Running pipelines for this project - - elsif @scope.nil? - Pipelines for this project - - else - #{@scope.titleize} for this project - %ul.content-list.pipelines - stages = @pipelines.stages - if @pipelines.blank? @@ -59,7 +51,7 @@ %th.stage %span.has-tooltip{ title: "#{stage.titleize}" } = stage.titleize.pluralize - %th + %th Duration %th = render @pipelines, commit_sha: true, stage: true, allow_retry: true, stages: stages -- cgit v1.2.1 From 65925e699839e1f2e01c6c5f7a355d9fae0337d9 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Tue, 24 May 2016 12:31:46 -0500 Subject: Remove top block from builds page --- app/views/admin/builds/index.html.haml | 1 - app/views/projects/builds/index.html.haml | 3 --- spec/features/builds_spec.rb | 1 - 3 files changed, 5 deletions(-) diff --git a/app/views/admin/builds/index.html.haml b/app/views/admin/builds/index.html.haml index ed24757087b..d74cf8598e8 100644 --- a/app/views/admin/builds/index.html.haml +++ b/app/views/admin/builds/index.html.haml @@ -47,4 +47,3 @@ = render "admin/builds/build", build: build = paginate @builds, theme: 'gitlab' - diff --git a/app/views/projects/builds/index.html.haml b/app/views/projects/builds/index.html.haml index 98f4a9416e5..7c0bec264ab 100644 --- a/app/views/projects/builds/index.html.haml +++ b/app/views/projects/builds/index.html.haml @@ -35,9 +35,6 @@ = icon('wrench') %span CI Lint -.row-content-block - #{(@scope || 'all').capitalize} builds from this project - %ul.content-list - if @builds.blank? %li diff --git a/spec/features/builds_spec.rb b/spec/features/builds_spec.rb index f83a78308e3..090a941958f 100644 --- a/spec/features/builds_spec.rb +++ b/spec/features/builds_spec.rb @@ -43,7 +43,6 @@ describe "Builds" do end it { expect(page).to have_selector('.nav-links li.active', text: 'All') } - it { expect(page).to have_selector('.row-content-block', text: 'All builds from this project') } it { expect(page).to have_content @build.short_sha } it { expect(page).to have_content @build.ref } it { expect(page).to have_content @build.name } -- cgit v1.2.1 From b359d5d57f4b836c04e9e2ef7e1fcb3775bd5305 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Tue, 24 May 2016 17:55:57 -0700 Subject: Fix groups API to list only user's accessible projects Closes #17496 --- CHANGELOG | 1 + app/finders/group_projects_finder.rb | 2 +- lib/api/groups.rb | 3 +-- spec/requests/api/groups_spec.rb | 21 ++++++++++++++++++--- 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index a79c3048b79..0866ad89ddd 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.9.0 (unreleased) - Redesign navigation for project pages + - Fix groups API to list only user's accessible projects - Use gitlab-shell v3.0.0 v 8.8.2 (unreleased) diff --git a/app/finders/group_projects_finder.rb b/app/finders/group_projects_finder.rb index 3b9a421b118..aa8f4c1d0e4 100644 --- a/app/finders/group_projects_finder.rb +++ b/app/finders/group_projects_finder.rb @@ -18,7 +18,7 @@ class GroupProjectsFinder < UnionFinder projects = [] if current_user - if @group.users.include?(current_user) + if @group.users.include?(current_user) || current_user.admin? projects << @group.projects unless only_shared projects << @group.shared_projects unless only_owned else diff --git a/lib/api/groups.rb b/lib/api/groups.rb index 91e420832f3..9d8b8d737a9 100644 --- a/lib/api/groups.rb +++ b/lib/api/groups.rb @@ -95,8 +95,7 @@ module API # GET /groups/:id/projects get ":id/projects" do group = find_group(params[:id]) - projects = group.projects - projects = filter_projects(projects) + projects = GroupProjectsFinder.new(group).execute(current_user) projects = paginate projects present projects, with: Entities::Project end diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb index 37ddab83c30..7ecefce80d6 100644 --- a/spec/requests/api/groups_spec.rb +++ b/spec/requests/api/groups_spec.rb @@ -12,6 +12,7 @@ describe API::API, api: true do let!(:group2) { create(:group, :private) } let!(:project1) { create(:project, namespace: group1) } let!(:project2) { create(:project, namespace: group2) } + let!(:project3) { create(:project, namespace: group1, path: 'test', visibility_level: Gitlab::VisibilityLevel::PRIVATE) } before do group1.add_owner(user1) @@ -147,9 +148,11 @@ describe API::API, api: true do context "when authenticated as user" do it "should return the group's projects" do get api("/groups/#{group1.id}/projects", user1) + expect(response.status).to eq(200) - expect(json_response.length).to eq(1) - expect(json_response.first['name']).to eq(project1.name) + expect(json_response.length).to eq(2) + project_names = json_response.map { |proj| proj['name' ] } + expect(project_names).to match_array([project1.name, project3.name]) end it "should not return a non existing group" do @@ -162,6 +165,16 @@ describe API::API, api: true do expect(response.status).to eq(404) end + + it "should only return projects to which user has access" do + project3.team << [user3, :developer] + + get api("/groups/#{group1.id}/projects", user3) + + expect(response.status).to eq(200) + expect(json_response.length).to eq(1) + expect(json_response.first['name']).to eq(project3.name) + end end context "when authenticated as admin" do @@ -181,8 +194,10 @@ describe API::API, api: true do context 'when using group path in URL' do it 'should return any existing group' do get api("/groups/#{group1.path}/projects", admin) + expect(response.status).to eq(200) - expect(json_response.first['name']).to eq(project1.name) + project_names = json_response.map { |proj| proj['name' ] } + expect(project_names).to match_array([project1.name, project3.name]) end it 'should not return a non existing group' do -- cgit v1.2.1 From 5273335247660465a39ffdcb1c801807e84b3eba Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Tue, 24 May 2016 17:53:53 -0400 Subject: Fix forks creation when visibility level is restricted --- CHANGELOG | 1 + app/services/projects/fork_service.rb | 14 +++++++++++++- lib/gitlab/visibility_level.rb | 7 +++++++ spec/services/projects/fork_service_spec.rb | 27 +++++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index c59a66874c3..73f21ed4d8a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.9.0 (unreleased) + - Allow forking projects with restricted visibility level - Redesign navigation for project pages - Use gitlab-shell v3.0.0 - Changed the Slack build message to use the singular duration if necessary (Aran Koning) diff --git a/app/services/projects/fork_service.rb b/app/services/projects/fork_service.rb index 0577ae778d5..de6dc38cc8e 100644 --- a/app/services/projects/fork_service.rb +++ b/app/services/projects/fork_service.rb @@ -3,7 +3,7 @@ module Projects def execute new_params = { forked_from_project_id: @project.id, - visibility_level: @project.visibility_level, + visibility_level: allowed_visibility_level, description: @project.description, name: @project.name, path: @project.path, @@ -19,5 +19,17 @@ module Projects new_project = CreateService.new(current_user, new_params).execute new_project end + + private + + def allowed_visibility_level + project_level = @project.visibility_level + + if Gitlab::VisibilityLevel.non_restricted_level?(project_level) + project_level + else + Gitlab::VisibilityLevel.highest_allowed_level + end + end end end diff --git a/lib/gitlab/visibility_level.rb b/lib/gitlab/visibility_level.rb index a1ee1cba216..9462f3368e6 100644 --- a/lib/gitlab/visibility_level.rb +++ b/lib/gitlab/visibility_level.rb @@ -32,6 +32,13 @@ module Gitlab } end + def highest_allowed_level + restricted_levels = current_application_settings.restricted_visibility_levels + + allowed_levels = self.values - restricted_levels + allowed_levels.max || PRIVATE + end + def allowed_for?(user, level) user.is_admin? || allowed_level?(level.to_i) end diff --git a/spec/services/projects/fork_service_spec.rb b/spec/services/projects/fork_service_spec.rb index d1ee60a0aea..31bb7120d84 100644 --- a/spec/services/projects/fork_service_spec.rb +++ b/spec/services/projects/fork_service_spec.rb @@ -42,6 +42,33 @@ describe Projects::ForkService, services: true do expect(@to_project.builds_enabled?).to be_truthy end end + + context "when project has restricted visibility level" do + context "and only one visibility level is restricted" do + before do + @from_project.update_attributes(visibility_level: Gitlab::VisibilityLevel::INTERNAL) + stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::INTERNAL]) + end + + it "creates fork with highest allowed level" do + forked_project = fork_project(@from_project, @to_user) + + expect(forked_project.visibility_level).to eq(Gitlab::VisibilityLevel::PUBLIC) + end + end + + context "and all visibility levels are restricted" do + before do + stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC, Gitlab::VisibilityLevel::INTERNAL, Gitlab::VisibilityLevel::PRIVATE]) + end + + it "creates fork with private visibility levels" do + forked_project = fork_project(@from_project, @to_user) + + expect(forked_project.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE) + end + end + end end describe :fork_to_namespace do -- cgit v1.2.1 From b10b6f963dd0d0da26e1750263e6b970b839ba0f Mon Sep 17 00:00:00 2001 From: Drew Blessing Date: Wed, 25 May 2016 11:30:11 -0500 Subject: Add new HA diagrams [ci skip] --- doc/administration/high_availability/README.md | 4 ++++ .../img/high_availability/active-active-diagram.png | Bin 0 -> 29607 bytes .../img/high_availability/active-passive-diagram.png | Bin 0 -> 24246 bytes 3 files changed, 4 insertions(+) create mode 100644 doc/administration/img/high_availability/active-active-diagram.png create mode 100644 doc/administration/img/high_availability/active-passive-diagram.png diff --git a/doc/administration/high_availability/README.md b/doc/administration/high_availability/README.md index 43d85ffb775..d74a786ac24 100644 --- a/doc/administration/high_availability/README.md +++ b/doc/administration/high_availability/README.md @@ -19,6 +19,8 @@ Components/Servers Required: - 2 servers/virtual machines (one active/one passive) +![Active/Passive HA Diagram](../img/high_availability/active-passive-diagram.png) + ### Active/Active This architecture scales easily because all application servers handle @@ -26,6 +28,8 @@ user requests simultaneously. The database, Redis, and GitLab application are all deployed on separate servers. The configuration is **only** highly-available if the database, Redis and storage are also configured as such. +![Active/Active HA Diagram](../img/high_availability/active-active-diagram.png) + **Steps to configure active/active:** 1. [Configure the database](database.md) diff --git a/doc/administration/img/high_availability/active-active-diagram.png b/doc/administration/img/high_availability/active-active-diagram.png new file mode 100644 index 00000000000..81259e0ae93 Binary files /dev/null and b/doc/administration/img/high_availability/active-active-diagram.png differ diff --git a/doc/administration/img/high_availability/active-passive-diagram.png b/doc/administration/img/high_availability/active-passive-diagram.png new file mode 100644 index 00000000000..f69ff1d0357 Binary files /dev/null and b/doc/administration/img/high_availability/active-passive-diagram.png differ -- cgit v1.2.1 From 2682c5884777f1bfd5cb0b5c85b1f3c188906460 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 22 Mar 2016 20:27:36 -0400 Subject: Customize ActionMailer preview path --- config/environments/development.rb | 1 + spec/mailers/previews/devise_mailer_preview.rb | 11 +++++++++++ 2 files changed, 12 insertions(+) create mode 100644 spec/mailers/previews/devise_mailer_preview.rb diff --git a/config/environments/development.rb b/config/environments/development.rb index 4f39016bfa4..8cca0039b4a 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -39,6 +39,7 @@ Rails.application.configure do config.action_mailer.delivery_method = :letter_opener_web # Don't make a mess when bootstrapping a development environment config.action_mailer.perform_deliveries = (ENV['BOOTSTRAP'] != '1') + config.action_mailer.preview_path = 'spec/mailers/previews' config.eager_load = false end diff --git a/spec/mailers/previews/devise_mailer_preview.rb b/spec/mailers/previews/devise_mailer_preview.rb new file mode 100644 index 00000000000..8a4d6e7250e --- /dev/null +++ b/spec/mailers/previews/devise_mailer_preview.rb @@ -0,0 +1,11 @@ +class DeviseMailerPreview < ActionMailer::Preview + def confirmation_instructions_for_signup + user = User.new(email: 'signup@example.com') + DeviseMailer.confirmation_instructions(user, 'faketoken', {}) + end + + def confirmation_instructions_for_new_email + user = User.last + DeviseMailer.confirmation_instructions(user, 'faketoken', {}) + end +end -- cgit v1.2.1 From 66ae3897e2a170133f389f1713129e5b49d88ecc Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 22 Mar 2016 20:28:05 -0400 Subject: Make the standard Devise confirmation email our new plaintext version --- app/views/devise/mailer/confirmation_instructions.html.erb | 9 --------- app/views/devise/mailer/confirmation_instructions.text.erb | 9 +++++++++ 2 files changed, 9 insertions(+), 9 deletions(-) delete mode 100644 app/views/devise/mailer/confirmation_instructions.html.erb create mode 100644 app/views/devise/mailer/confirmation_instructions.text.erb diff --git a/app/views/devise/mailer/confirmation_instructions.html.erb b/app/views/devise/mailer/confirmation_instructions.html.erb deleted file mode 100644 index c6fa8f0ee36..00000000000 --- a/app/views/devise/mailer/confirmation_instructions.html.erb +++ /dev/null @@ -1,9 +0,0 @@ -

Welcome <%= @resource.name %>!

- -<% if @resource.unconfirmed_email.present? %> -

You can confirm your email (<%= @resource.unconfirmed_email %>) through the link below:

-<% else %> -

You can confirm your account through the link below:

-<% end %> - -

<%= link_to 'Confirm your account', confirmation_url(@resource, confirmation_token: @token) %>

diff --git a/app/views/devise/mailer/confirmation_instructions.text.erb b/app/views/devise/mailer/confirmation_instructions.text.erb new file mode 100644 index 00000000000..9f76edb76a4 --- /dev/null +++ b/app/views/devise/mailer/confirmation_instructions.text.erb @@ -0,0 +1,9 @@ +Welcome, <%= @resource.name %>! + +<% if @resource.unconfirmed_email.present? %> +You can confirm your email (<%= @resource.unconfirmed_email %>) through the link below: +<% else %> +You can confirm your account through the link below: +<% end %> + +<%= confirmation_url(@resource, confirmation_token: @token) %> -- cgit v1.2.1 From 3e3463218de17011bd4b29a7a27452d4f7652f35 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 22 Mar 2016 22:20:47 -0400 Subject: New confirmation email :fire: --- app/assets/images/mailers/gitlab_header_logo.png | Bin 0 -> 7096 bytes app/assets/images/mailers/gitlab_tanuki_2x.png | Bin 0 -> 2545 bytes app/assets/stylesheets/mailers/devise.scss | 134 +++++++++++++++++++++ app/mailers/devise_mailer.rb | 2 + .../mailer/confirmation_instructions.html.haml | 16 +++ app/views/layouts/devise_mailer.html.haml | 34 ++++++ config/application.rb | 2 +- spec/mailers/previews/devise_mailer_preview.rb | 2 +- 8 files changed, 188 insertions(+), 2 deletions(-) create mode 100644 app/assets/images/mailers/gitlab_header_logo.png create mode 100644 app/assets/images/mailers/gitlab_tanuki_2x.png create mode 100644 app/assets/stylesheets/mailers/devise.scss create mode 100644 app/views/devise/mailer/confirmation_instructions.html.haml create mode 100644 app/views/layouts/devise_mailer.html.haml diff --git a/app/assets/images/mailers/gitlab_header_logo.png b/app/assets/images/mailers/gitlab_header_logo.png new file mode 100644 index 00000000000..35ca1860887 Binary files /dev/null and b/app/assets/images/mailers/gitlab_header_logo.png differ diff --git a/app/assets/images/mailers/gitlab_tanuki_2x.png b/app/assets/images/mailers/gitlab_tanuki_2x.png new file mode 100644 index 00000000000..551dd6ce2ce Binary files /dev/null and b/app/assets/images/mailers/gitlab_tanuki_2x.png differ diff --git a/app/assets/stylesheets/mailers/devise.scss b/app/assets/stylesheets/mailers/devise.scss new file mode 100644 index 00000000000..28611a5ec81 --- /dev/null +++ b/app/assets/stylesheets/mailers/devise.scss @@ -0,0 +1,134 @@ +// NOTE: This stylesheet is for the exclusive use of the `devise_mailer` layout +// used for Devise email templates, and _should not_ be included in any +// application stylesheets. +// +// Styles defined here are embedded directly into the resulting email HTML via +// the `premailer` gem. + +$body-background-color: #363636; +$message-background-color: #fafafa; + +$header-color: #6b4fbb; +$body-color: #444; +$cta-color: #e14329; +$footer-link-color: #7e7e7e; + +$font-family: Helvetica, Arial, sans-serif; + +body { + background-color: $body-background-color; + font-family: $font-family; + margin: 0; + padding: 0; +} + +table { + -premailer-cellpadding: 0; + -premailer-cellspacing: 0; + + border: 0; + border-collapse: separate; + + &#wrapper { + background-color: $body-background-color; + width: 100%; + } + + &#header { + margin: 0 auto; + text-align: left; + width: 600px; + } + + &#body { + background-color: $message-background-color; + border: 1px solid #000; + border-radius: 4px; + margin: 0 auto; + width: 600px; + } + + &#footer { + color: $footer-link-color; + font-size: 14px; + text-align: center; + width: 100%; + } + + td { + &#body-container { + padding: 20px 40px; + } + } +} + +.center { + text-align: center; +} + +#logo { + border: none; + outline: none; + min-height: 88px; + width: 134px; +} + +#content { + h2 { + color: $header-color; + font-size: 30px; + font-weight: 400; + line-height: 34px; + margin-top: 0; + } + + p { + color: $body-color; + font-size: 17px; + line-height: 24px; + margin-bottom: 0; + } +} + +#cta { + border: 1px solid $cta-color; + border-radius: 3px; + display: inline-block; + margin: 20px 0; + padding: 12px 24px; + + a { + background-color: $message-background-color; + color: $cta-color; + display: inline-block; + text-decoration: none; + } +} + +#tanuki { + padding: 40px 0 0; + + img { + border: none; + outline: none; + width: 37px; + min-height: 36px; + } +} + +#tagline { + font-size: 22px; + font-weight: 100; + padding: 4px 0 40px; +} + +#social { + padding: 0 10px 20px; + width: 600px; + word-spacing: 20px; + + a { + color: $footer-link-color; + text-decoration: none; + } +} diff --git a/app/mailers/devise_mailer.rb b/app/mailers/devise_mailer.rb index b616add283a..415f6e12885 100644 --- a/app/mailers/devise_mailer.rb +++ b/app/mailers/devise_mailer.rb @@ -1,4 +1,6 @@ class DeviseMailer < Devise::Mailer default from: "#{Gitlab.config.gitlab.email_display_name} <#{Gitlab.config.gitlab.email_from}>" default reply_to: Gitlab.config.gitlab.email_reply_to + + layout 'devise_mailer' end diff --git a/app/views/devise/mailer/confirmation_instructions.html.haml b/app/views/devise/mailer/confirmation_instructions.html.haml new file mode 100644 index 00000000000..086bb8e083d --- /dev/null +++ b/app/views/devise/mailer/confirmation_instructions.html.haml @@ -0,0 +1,16 @@ +.center + - if @resource.unconfirmed_email.present? + #content + %h2= @resource.unconfirmed_email + %p Click the link below to confirm your email address. + #cta + = link_to 'Confirm your email address', confirmation_url(@resource, confirmation_token: @token) + - else + #content + - if Gitlab.com? + %h2 Thanks for signing up to GitLab! + - else + %h2 Welcome, #{@resource.name}! + %p To get started, click the link below to confirm your account. + #cta + = link_to 'Confirm your account', confirmation_url(@resource, confirmation_token: @token) diff --git a/app/views/layouts/devise_mailer.html.haml b/app/views/layouts/devise_mailer.html.haml new file mode 100644 index 00000000000..c258eafdd51 --- /dev/null +++ b/app/views/layouts/devise_mailer.html.haml @@ -0,0 +1,34 @@ +!!! 5 +%html + %head + %meta(content='text/html; charset=UTF-8' http-equiv='Content-Type') + = stylesheet_link_tag 'mailers/devise' + + %body + %table#wrapper + %tr + %td + %table#header + %td{valign: "top"} + = image_tag('mailers/gitlab_header_logo.png', id: 'logo', alt: 'GitLab Wordmark') + + %table#body + %tr + %td#body-container + = yield + + - if Gitlab.com? + %table#footer + %tr + %td#tanuki + = image_tag('mailers/gitlab_tanuki_2x.png', alt: 'GitLab Logo') + %tr + %td#tagline + Everyone can contribute + %tr + %td#social + = link_to 'Blog', 'https://about.gitlab.com/blog/' + = link_to 'Twitter', 'https://twitter.com/gitlab' + = link_to 'Facebook', 'https://www.facebook.com/gitlab/' + = link_to 'YouTube', 'https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg' + = link_to 'LinkedIn', 'https://www.linkedin.com/company/gitlab-com' diff --git a/config/application.rb b/config/application.rb index 0e5a77285e5..de2bb08c978 100644 --- a/config/application.rb +++ b/config/application.rb @@ -80,7 +80,7 @@ module Gitlab config.assets.precompile << "*.png" config.assets.precompile << "print.css" config.assets.precompile << "notify.css" - config.assets.precompile << "mailers/repository_push_email.css" + config.assets.precompile << "mailers/*.css" # Version of your assets, change this if you want to expire all your assets config.assets.version = '1.0' diff --git a/spec/mailers/previews/devise_mailer_preview.rb b/spec/mailers/previews/devise_mailer_preview.rb index 8a4d6e7250e..dc3062a4332 100644 --- a/spec/mailers/previews/devise_mailer_preview.rb +++ b/spec/mailers/previews/devise_mailer_preview.rb @@ -1,6 +1,6 @@ class DeviseMailerPreview < ActionMailer::Preview def confirmation_instructions_for_signup - user = User.new(email: 'signup@example.com') + user = User.new(name: 'Jane Doe', email: 'signup@example.com') DeviseMailer.confirmation_instructions(user, 'faketoken', {}) end -- cgit v1.2.1 From 8083bc234a8ca9ef4eee2a4f0cb44e2f73cf33bc Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Thu, 14 Apr 2016 16:02:22 -0400 Subject: Don't remove IDs via premailer This makes it easier to debug style rules. --- config/initializers/premailer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/initializers/premailer.rb b/config/initializers/premailer.rb index b9176688bc4..cb00d3cfe95 100644 --- a/config/initializers/premailer.rb +++ b/config/initializers/premailer.rb @@ -3,6 +3,6 @@ Premailer::Rails.config.merge!( generate_text_part: false, preserve_styles: true, remove_comments: true, - remove_ids: true, + remove_ids: false, remove_scripts: false ) -- cgit v1.2.1 From 91483bfeb718c7cede4dcc2372053195ea9a0c65 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Wed, 25 May 2016 16:56:44 -0400 Subject: Add CHANGELOG entry for redesigned confirmation emails [ci skip] --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index 4a38505eeea..1ad98fbc9f1 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.9.0 (unreleased) - Allow forking projects with restricted visibility level - Redesign navigation for project pages + - Redesign account and email confirmation emails - Use gitlab-shell v3.0.0 - Add rake task 'gitlab:db:configure' for conditionally seeding or migrating the database - Changed the Slack build message to use the singular duration if necessary (Aran Koning) -- cgit v1.2.1 From ce727ab6e6e75a760f72cfd9ce36092aeb41c7da Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Wed, 25 May 2016 17:13:20 -0400 Subject: Fix RuboCop --- spec/features/issues/filter_issues_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/features/issues/filter_issues_spec.rb b/spec/features/issues/filter_issues_spec.rb index bfbd06a29e2..1f0594e6b02 100644 --- a/spec/features/issues/filter_issues_spec.rb +++ b/spec/features/issues/filter_issues_spec.rb @@ -186,7 +186,7 @@ describe 'Filter issues', feature: true do fill_in 'issue_search', with: 'testing' page.within '.issues-list' do - expect(page).to_not have_selector('.issue') + expect(page).not_to have_selector('.issue') end end end -- cgit v1.2.1 From ee0d3abcb8b3c8572be9dac1926c3f77f2636a9e Mon Sep 17 00:00:00 2001 From: Connor Shea Date: Wed, 25 May 2016 15:04:21 -0600 Subject: Update state_machines-activerecord from 0.3.0 to 0.4.0. No changelog, see commits: https://github.com/state-machines/state_machines-activerecord/commits/master Includes Rails 5 support. --- Gemfile | 2 +- Gemfile.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Gemfile b/Gemfile index e854a31b425..c236f37e14a 100644 --- a/Gemfile +++ b/Gemfile @@ -121,7 +121,7 @@ group :unicorn do end # State machine -gem "state_machines-activerecord", '~> 0.3.0' +gem "state_machines-activerecord", '~> 0.4.0' # Run events after state machine commits gem 'after_commit_queue' diff --git a/Gemfile.lock b/Gemfile.lock index 4533aa31d5f..dbc0fd15ef4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -790,11 +790,11 @@ GEM activesupport (>= 4.0) sprockets (>= 3.0.0) state_machines (0.4.0) - state_machines-activemodel (0.3.0) - activemodel (~> 4.1) + state_machines-activemodel (0.4.0) + activemodel (>= 4.1, < 5.1) state_machines (>= 0.4.0) - state_machines-activerecord (0.3.0) - activerecord (~> 4.1) + state_machines-activerecord (0.4.0) + activerecord (>= 4.1, < 5.1) state_machines-activemodel (>= 0.3.0) stringex (2.5.2) systemu (2.6.5) @@ -1043,7 +1043,7 @@ DEPENDENCIES spring-commands-spinach (~> 1.1.0) spring-commands-teaspoon (~> 0.0.2) sprockets (~> 3.6.0) - state_machines-activerecord (~> 0.3.0) + state_machines-activerecord (~> 0.4.0) task_list (~> 1.0.2) teaspoon (~> 1.1.0) teaspoon-jasmine (~> 2.2.0) -- cgit v1.2.1 From 84fee47a763b6f1dda8b58e66c893cd8cf6dda8e Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Thu, 12 May 2016 08:23:31 -0500 Subject: Start scrolling tabs design --- app/assets/javascripts/layout_nav.js.coffee | 19 +++++++++++++++++++ app/assets/stylesheets/framework/nav.scss | 29 +++++++++++++++++++++++++++++ app/views/layouts/nav/_group.html.haml | 3 ++- 3 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 app/assets/javascripts/layout_nav.js.coffee diff --git a/app/assets/javascripts/layout_nav.js.coffee b/app/assets/javascripts/layout_nav.js.coffee new file mode 100644 index 00000000000..2f2f5aa85c5 --- /dev/null +++ b/app/assets/javascripts/layout_nav.js.coffee @@ -0,0 +1,19 @@ +class @LayoutNav + $(document).ready -> + $('#scrolling-tabs').on 'scroll', -> + cur = $(this).scrollLeft() + if cur == 0 + return + else + max = 289 + console.log "MAX:" + max + console.log "CUR:" + cur + if cur == max + $('.fa-arrow-right').addClass('end-scroll') + $('.nav-links').addClass('end-scroll') + else + $('.fa-arrow-right').removeClass('end-scroll') + $('.nav-links').removeClass('end-scroll') + return + $('#scrolling-tabs').trigger 'scroll' + return diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index ee4f573f91b..83c27eada3d 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -256,6 +256,30 @@ display: none; } + .fa-arrow-right { + display: none; + position: absolute; + color: #7e7c7c; + bottom: 11px; + right: 0; + padding: 10px 10px 10px 25px; + background: -webkit-linear-gradient(left, rgba(250, 250, 250, 0.4), $background-color 45%); + + &.end-scroll { + opacity: 0; + transition-duration: .3s; + } + } + + @media (max-width: 790px) { + margin-right: 19px; + + .fa-arrow-right { + display: block; + transition-duration: .3s; + } + } + li { a { @@ -276,6 +300,11 @@ color: $gl-icon-color; } } + + &.end-scroll { + margin-right: 0; + transition-duration: .3s; + } } } diff --git a/app/views/layouts/nav/_group.html.haml b/app/views/layouts/nav/_group.html.haml index 3438005863a..781c0651253 100644 --- a/app/views/layouts/nav/_group.html.haml +++ b/app/views/layouts/nav/_group.html.haml @@ -1,6 +1,6 @@ = render 'layouts/nav/group_settings' -%ul.nav-links +%ul.nav-links#scrolling-tabs = nav_link(path: 'groups#show', html_options: {class: 'home'}) do = link_to group_path(@group), title: 'Home' do = icon('group fw') @@ -35,3 +35,4 @@ = icon('users fw') %span Members + = icon('arrow-right') -- cgit v1.2.1 From 65a175bbd9d5e5a8f6937bcbee9505c67f168b38 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Mon, 16 May 2016 14:58:15 -0500 Subject: Remove arrows from mobile scroll fade out --- app/assets/javascripts/layout_nav.js.coffee | 24 +++------ app/assets/stylesheets/framework/nav.scss | 34 +++++++----- app/assets/stylesheets/framework/sidebar.scss | 2 +- app/helpers/nav_helper.rb | 4 ++ app/views/layouts/nav/_group.html.haml | 75 ++++++++++++++------------- app/views/layouts/nav/_profile.html.haml | 3 +- 6 files changed, 74 insertions(+), 68 deletions(-) diff --git a/app/assets/javascripts/layout_nav.js.coffee b/app/assets/javascripts/layout_nav.js.coffee index 2f2f5aa85c5..4586702bc2c 100644 --- a/app/assets/javascripts/layout_nav.js.coffee +++ b/app/assets/javascripts/layout_nav.js.coffee @@ -1,19 +1,11 @@ class @LayoutNav - $(document).ready -> + $ -> $('#scrolling-tabs').on 'scroll', -> - cur = $(this).scrollLeft() - if cur == 0 - return + currentPosition = $(this).scrollLeft() + return if currentPosition == 0 + if $('.nav-control').length + maxPosition = $(this)[0].scrollWidth - $(this).parent().width() + 59 else - max = 289 - console.log "MAX:" + max - console.log "CUR:" + cur - if cur == max - $('.fa-arrow-right').addClass('end-scroll') - $('.nav-links').addClass('end-scroll') - else - $('.fa-arrow-right').removeClass('end-scroll') - $('.nav-links').removeClass('end-scroll') - return - $('#scrolling-tabs').trigger 'scroll' - return + maxPosition = $(this)[0].scrollWidth - $(this).parent().width() + + $('.fade-out').toggleClass('end-scroll', currentPosition is maxPosition) diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index 83c27eada3d..fe3a2aa26be 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -256,14 +256,18 @@ display: none; } - .fa-arrow-right { - display: none; + .fade-out { + opacity: 1; position: absolute; - color: #7e7c7c; - bottom: 11px; + bottom: 10px; right: 0; - padding: 10px 10px 10px 25px; + width: 43px; + height: 35px; + -webkit-transform: translateZ(0); background: -webkit-linear-gradient(left, rgba(250, 250, 250, 0.4), $background-color 45%); + background: -o-linear-gradient(left, rgba(250, 250, 250, 0.4), $background-color 45%); + background: -moz-linear-gradient(left, rgba(250, 250, 250, 0.4), $background-color 45%); + background: linear-gradient(left, rgba(250, 250, 250, 0.4), $background-color 45%); &.end-scroll { opacity: 0; @@ -272,10 +276,7 @@ } @media (max-width: 790px) { - margin-right: 19px; - - .fa-arrow-right { - display: block; + .fade-out { transition-duration: .3s; } } @@ -300,13 +301,20 @@ color: $gl-icon-color; } } + } - &.end-scroll { - margin-right: 0; - transition-duration: .3s; + .nav-control { + .fade-out { + right: 58px; + + @media (min-width: $screen-xs-max) { + right: 67px; + } + @media (max-width: $screen-xs-min) { + right: 0; + } } } - } .page-with-layout-nav { diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss index f90d7a806d3..67f491b6d9c 100644 --- a/app/assets/stylesheets/framework/sidebar.scss +++ b/app/assets/stylesheets/framework/sidebar.scss @@ -324,7 +324,7 @@ .layout-nav { @media (max-width: $screen-xs-min) { - padding-right: 0;; + padding-right: 0; } @media (min-width: $screen-xs-min) and (max-width: $screen-md-min) { diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb index fbb799eecd3..597a12cd53b 100644 --- a/app/helpers/nav_helper.rb +++ b/app/helpers/nav_helper.rb @@ -51,4 +51,8 @@ module NavHelper def layout_dropdown_class "controls-dropdown-visible" if current_user end + + def nav_control_class + "nav-control" if current_user + end end diff --git a/app/views/layouts/nav/_group.html.haml b/app/views/layouts/nav/_group.html.haml index 781c0651253..ba4a7092655 100644 --- a/app/views/layouts/nav/_group.html.haml +++ b/app/views/layouts/nav/_group.html.haml @@ -1,38 +1,39 @@ -= render 'layouts/nav/group_settings' +%div{ class: nav_control_class } + = render 'layouts/nav/group_settings' -%ul.nav-links#scrolling-tabs - = nav_link(path: 'groups#show', html_options: {class: 'home'}) do - = link_to group_path(@group), title: 'Home' do - = icon('group fw') - %span - Group - = nav_link(path: 'groups#activity') do - = link_to activity_group_path(@group), title: 'Activity' do - = icon('dashboard fw') - %span - Activity - = nav_link(controller: [:group, :milestones]) do - = link_to group_milestones_path(@group), title: 'Milestones' do - = icon('clock-o fw') - %span - Milestones - = nav_link(path: 'groups#issues') do - = link_to issues_group_path(@group), title: 'Issues' do - = icon('exclamation-circle fw') - %span - Issues - - issues = IssuesFinder.new(current_user, group_id: @group.id, state: 'opened').execute - %span.badge.count= number_with_delimiter(issues.count) - = nav_link(path: 'groups#merge_requests') do - = link_to merge_requests_group_path(@group), title: 'Merge Requests' do - = icon('tasks fw') - %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) - = nav_link(controller: [:group_members]) do - = link_to group_group_members_path(@group), title: 'Members' do - = icon('users fw') - %span - Members - = icon('arrow-right') + %ul.nav-links#scrolling-tabs + = nav_link(path: 'groups#show', html_options: {class: 'home'}) do + = link_to group_path(@group), title: 'Home' do + = icon('group fw') + %span + Group + = nav_link(path: 'groups#activity') do + = link_to activity_group_path(@group), title: 'Activity' do + = icon('dashboard fw') + %span + Activity + = nav_link(controller: [:group, :milestones]) do + = link_to group_milestones_path(@group), title: 'Milestones' do + = icon('clock-o fw') + %span + Milestones + = nav_link(path: 'groups#issues') do + = link_to issues_group_path(@group), title: 'Issues' do + = icon('exclamation-circle fw') + %span + Issues + - issues = IssuesFinder.new(current_user, group_id: @group.id, state: 'opened').execute + %span.badge.count= number_with_delimiter(issues.count) + = nav_link(path: 'groups#merge_requests') do + = link_to merge_requests_group_path(@group), title: 'Merge Requests' do + = icon('tasks fw') + %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) + = nav_link(controller: [:group_members]) do + = link_to group_group_members_path(@group), title: 'Members' do + = icon('users fw') + %span + Members + .fade-out diff --git a/app/views/layouts/nav/_profile.html.haml b/app/views/layouts/nav/_profile.html.haml index d730840d63a..d3d733d5999 100644 --- a/app/views/layouts/nav/_profile.html.haml +++ b/app/views/layouts/nav/_profile.html.haml @@ -1,4 +1,4 @@ -%ul.nav-links +%ul.nav-links#scrolling-tabs = nav_link(path: 'profiles#show', html_options: {class: 'home'}) do = link_to profile_path, title: 'Profile Settings' do = icon('user fw') @@ -47,3 +47,4 @@ = icon('history fw') %span Audit Log + .fade-out -- cgit v1.2.1 From e8fcd4641a2ef67df2e94b7f161c1a061cd5eb77 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Wed, 18 May 2016 09:47:54 -0500 Subject: Check screen width before increasing max position --- app/assets/javascripts/layout_nav.js.coffee | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/assets/javascripts/layout_nav.js.coffee b/app/assets/javascripts/layout_nav.js.coffee index 4586702bc2c..613243427cc 100644 --- a/app/assets/javascripts/layout_nav.js.coffee +++ b/app/assets/javascripts/layout_nav.js.coffee @@ -3,9 +3,7 @@ class @LayoutNav $('#scrolling-tabs').on 'scroll', -> currentPosition = $(this).scrollLeft() return if currentPosition == 0 - if $('.nav-control').length - maxPosition = $(this)[0].scrollWidth - $(this).parent().width() + 59 - else - maxPosition = $(this)[0].scrollWidth - $(this).parent().width() + maxPosition = $(this)[0].scrollWidth - $(this).parent().width() + maxPosition += 59 if $('.nav-control').length and window.innerWidth > 480 $('.fade-out').toggleClass('end-scroll', currentPosition is maxPosition) -- cgit v1.2.1 From 7876d27db8b330f3c5e306f1c2e657a8b0df8819 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Wed, 18 May 2016 10:48:10 -0500 Subject: Move fade out div --- app/assets/stylesheets/framework/nav.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index fe3a2aa26be..9f5f2f81b8c 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -259,10 +259,10 @@ .fade-out { opacity: 1; position: absolute; - bottom: 10px; + bottom: 16px; right: 0; width: 43px; - height: 35px; + height: 30px; -webkit-transform: translateZ(0); background: -webkit-linear-gradient(left, rgba(250, 250, 250, 0.4), $background-color 45%); background: -o-linear-gradient(left, rgba(250, 250, 250, 0.4), $background-color 45%); -- cgit v1.2.1 From 77c7fb1469446c76c84ce5883d99e0e3debaf515 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Wed, 18 May 2016 11:38:12 -0500 Subject: Fix coffeescript; remove fade out div so area is clickable; remove scrollbar on chrome --- app/assets/javascripts/layout_nav.js.coffee | 6 ++++-- app/assets/stylesheets/framework/nav.scss | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/layout_nav.js.coffee b/app/assets/javascripts/layout_nav.js.coffee index 613243427cc..2f14e3f35ac 100644 --- a/app/assets/javascripts/layout_nav.js.coffee +++ b/app/assets/javascripts/layout_nav.js.coffee @@ -2,8 +2,10 @@ class @LayoutNav $ -> $('#scrolling-tabs').on 'scroll', -> currentPosition = $(this).scrollLeft() - return if currentPosition == 0 + return if currentPosition is 0 + mobileScreenWidth = 480 + controlBtnWidth = $('.controls').width() maxPosition = $(this)[0].scrollWidth - $(this).parent().width() - maxPosition += 59 if $('.nav-control').length and window.innerWidth > 480 + maxPosition += controlBtnWidth if $('.nav-control').length and $(window).width() > mobileScreenWidth $('.fade-out').toggleClass('end-scroll', currentPosition is maxPosition) diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index 9f5f2f81b8c..bf5981bef8b 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -257,6 +257,7 @@ } .fade-out { + visibility: visible; opacity: 1; position: absolute; bottom: 16px; @@ -270,6 +271,7 @@ background: linear-gradient(left, rgba(250, 250, 250, 0.4), $background-color 45%); &.end-scroll { + visibility: hidden; opacity: 0; transition-duration: .3s; } -- cgit v1.2.1 From 3c3402b0ae4c2f70cc421d97ad9605a9abeb9398 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Tue, 24 May 2016 11:30:53 -0500 Subject: Add fade out to left side of layout nav; remove dropdown nav helper; remove controls button from mobile --- app/assets/javascripts/layout_nav.js.coffee | 6 ++- app/assets/stylesheets/framework/nav.scss | 64 +++++++++++++---------------- app/helpers/nav_helper.rb | 4 -- app/views/layouts/_page.html.haml | 2 +- app/views/layouts/nav/_group.html.haml | 3 +- app/views/layouts/nav/_profile.html.haml | 3 +- 6 files changed, 38 insertions(+), 44 deletions(-) diff --git a/app/assets/javascripts/layout_nav.js.coffee b/app/assets/javascripts/layout_nav.js.coffee index 2f14e3f35ac..43dc941a82f 100644 --- a/app/assets/javascripts/layout_nav.js.coffee +++ b/app/assets/javascripts/layout_nav.js.coffee @@ -1,11 +1,13 @@ class @LayoutNav $ -> + $('.fade-left').addClass('end-scroll') $('#scrolling-tabs').on 'scroll', -> currentPosition = $(this).scrollLeft() - return if currentPosition is 0 + $('.fade-left').toggleClass('end-scroll', currentPosition is 0) + mobileScreenWidth = 480 controlBtnWidth = $('.controls').width() maxPosition = $(this)[0].scrollWidth - $(this).parent().width() maxPosition += controlBtnWidth if $('.nav-control').length and $(window).width() > mobileScreenWidth - $('.fade-out').toggleClass('end-scroll', currentPosition is maxPosition) + $('.fade-right').toggleClass('end-scroll', currentPosition is maxPosition) diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index bf5981bef8b..260127e3111 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -1,3 +1,24 @@ +@mixin fade($gradient-direction) { + visibility: visible; + opacity: 1; + position: absolute; + bottom: 16px; + width: 43px; + height: 30px; + transition-duration: .3s; + -webkit-transform: translateZ(0); + background: -webkit-linear-gradient($gradient-direction, rgba(250, 250, 250, 0.4), $background-color 45%); + background: -o-linear-gradient($gradient-direction, rgba(250, 250, 250, 0.4), $background-color 45%); + background: -moz-linear-gradient($gradient-direction, rgba(250, 250, 250, 0.4), $background-color 45%); + background: linear-gradient($gradient-direction, rgba(250, 250, 250, 0.4), $background-color 45%); + + &.end-scroll { + visibility: hidden; + opacity: 0; + transition-duration: .3s; + } +} + .nav-links { padding: 0; margin: 0; @@ -210,12 +231,7 @@ padding: 7px 0 0; @media (max-width: $screen-xs-min) { - float: none; - padding: 0 9px; - - .dropdown-new { - width: 100%; - } + display: none; } i { @@ -256,31 +272,14 @@ display: none; } - .fade-out { - visibility: visible; - opacity: 1; - position: absolute; - bottom: 16px; + .fade-right { + @include fade(left); right: 0; - width: 43px; - height: 30px; - -webkit-transform: translateZ(0); - background: -webkit-linear-gradient(left, rgba(250, 250, 250, 0.4), $background-color 45%); - background: -o-linear-gradient(left, rgba(250, 250, 250, 0.4), $background-color 45%); - background: -moz-linear-gradient(left, rgba(250, 250, 250, 0.4), $background-color 45%); - background: linear-gradient(left, rgba(250, 250, 250, 0.4), $background-color 45%); - - &.end-scroll { - visibility: hidden; - opacity: 0; - transition-duration: .3s; - } } - @media (max-width: 790px) { - .fade-out { - transition-duration: .3s; - } + .fade-left { + @include fade(right); + left: 0; } li { @@ -306,7 +305,8 @@ } .nav-control { - .fade-out { + + .fade-right { right: 58px; @media (min-width: $screen-xs-max) { @@ -322,12 +322,6 @@ .page-with-layout-nav { margin-top: $header-height + 2; - &.controls-dropdown-visible { - @media (max-width: $screen-xs-min) { - margin-top: 96px; - } - } - .right-sidebar { top: ($header-height * 2) + 2; } diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb index 597a12cd53b..f685e547537 100644 --- a/app/helpers/nav_helper.rb +++ b/app/helpers/nav_helper.rb @@ -48,10 +48,6 @@ module NavHelper "page-with-layout-nav" if defined?(nav) && nav end - def layout_dropdown_class - "controls-dropdown-visible" if current_user - end - def nav_control_class "nav-control" if current_user end diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml index 5be0b546a62..1e961853c70 100644 --- a/app/views/layouts/_page.html.haml +++ b/app/views/layouts/_page.html.haml @@ -25,7 +25,7 @@ .layout-nav .container-fluid = render "layouts/nav/#{nav}" - .content-wrapper{ class: "#{layout_nav_class} #{layout_dropdown_class}" } + .content-wrapper{ class: "#{layout_nav_class}" } = render "layouts/broadcast" = render "layouts/flash" = yield :flash_message diff --git a/app/views/layouts/nav/_group.html.haml b/app/views/layouts/nav/_group.html.haml index ba4a7092655..9b8319c51ca 100644 --- a/app/views/layouts/nav/_group.html.haml +++ b/app/views/layouts/nav/_group.html.haml @@ -2,6 +2,7 @@ = render 'layouts/nav/group_settings' %ul.nav-links#scrolling-tabs + .fade-left = nav_link(path: 'groups#show', html_options: {class: 'home'}) do = link_to group_path(@group), title: 'Home' do = icon('group fw') @@ -36,4 +37,4 @@ = icon('users fw') %span Members - .fade-out + .fade-right diff --git a/app/views/layouts/nav/_profile.html.haml b/app/views/layouts/nav/_profile.html.haml index d3d733d5999..a31584c7f81 100644 --- a/app/views/layouts/nav/_profile.html.haml +++ b/app/views/layouts/nav/_profile.html.haml @@ -1,4 +1,5 @@ %ul.nav-links#scrolling-tabs + .fade-left = nav_link(path: 'profiles#show', html_options: {class: 'home'}) do = link_to profile_path, title: 'Profile Settings' do = icon('user fw') @@ -47,4 +48,4 @@ = icon('history fw') %span Audit Log - .fade-out + .fade-right -- cgit v1.2.1 From 1a1eaf481a19cbeedaf5b6137eef73031f33e3d2 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Tue, 24 May 2016 16:06:40 -0500 Subject: Refactor nav links css --- app/assets/stylesheets/framework/nav.scss | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index 260127e3111..182dd05225f 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -274,7 +274,14 @@ .fade-right { @include fade(left); - right: 0; + right: 58px; + + @media (min-width: $screen-xs-max) { + right: 67px; + } + @media (max-width: $screen-xs-min) { + right: 0; + } } .fade-left { @@ -303,20 +310,6 @@ } } } - - .nav-control { - - .fade-right { - right: 58px; - - @media (min-width: $screen-xs-max) { - right: 67px; - } - @media (max-width: $screen-xs-min) { - right: 0; - } - } - } } .page-with-layout-nav { -- cgit v1.2.1 From 1965ec6324d7a67aec485b98030794657624d3ec Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Tue, 24 May 2016 17:14:14 -0500 Subject: Add fade to project nav; fix bug with controls --- app/assets/stylesheets/framework/nav.scss | 22 ++-- app/views/layouts/nav/_project.html.haml | 194 +++++++++++++++--------------- 2 files changed, 113 insertions(+), 103 deletions(-) diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index 182dd05225f..59e9a036f71 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -274,14 +274,7 @@ .fade-right { @include fade(left); - right: 58px; - - @media (min-width: $screen-xs-max) { - right: 67px; - } - @media (max-width: $screen-xs-min) { - right: 0; - } + right: 0; } .fade-left { @@ -310,6 +303,19 @@ } } } + + .nav-control { + .fade-right { + right: 58px; + + @media (min-width: $screen-xs-max) { + right: 67px; + } + @media (max-width: $screen-xs-min) { + right: 0; + } + } + } } .page-with-layout-nav { diff --git a/app/views/layouts/nav/_project.html.haml b/app/views/layouts/nav/_project.html.haml index 33ba654bbee..bffa583fda3 100644 --- a/app/views/layouts/nav/_project.html.haml +++ b/app/views/layouts/nav/_project.html.haml @@ -19,113 +19,117 @@ data: { confirm: leave_project_message(@project) }, method: :delete, title: 'Leave project' do Leave Project -%ul.nav-links - = nav_link(path: 'projects#show', html_options: {class: 'home'}) do - = link_to project_path(@project), title: 'Project', class: 'shortcuts-project' do - = icon('bookmark fw') - %span - Project - = nav_link(path: 'projects#activity') do - = link_to activity_project_path(@project), title: 'Activity', class: 'shortcuts-project-activity' do - = icon('dashboard fw') - %span - Activity - - if project_nav_tab? :files - = nav_link(controller: %w(tree blob blame edit_tree new_tree find_file)) do - = link_to project_files_path(@project), title: 'Files', class: 'shortcuts-tree' do - = icon('files-o fw') +%div{ class: nav_control_class } + %ul.nav-links#scrolling-tabs + .fade-left + = nav_link(path: 'projects#show', html_options: {class: 'home'}) do + = link_to project_path(@project), title: 'Project', class: 'shortcuts-project' do + = icon('bookmark fw') %span - Files - - - if project_nav_tab? :commits - = nav_link(controller: %w(commit commits compare repositories tags branches releases network)) do - = link_to project_commits_path(@project), title: 'Commits', class: 'shortcuts-commits' do - = icon('history fw') + Project + = nav_link(path: 'projects#activity') do + = link_to activity_project_path(@project), title: 'Activity', class: 'shortcuts-project-activity' do + = icon('dashboard fw') %span - Commits + Activity + - if project_nav_tab? :files + = nav_link(controller: %w(tree blob blame edit_tree new_tree find_file)) do + = link_to project_files_path(@project), title: 'Files', class: 'shortcuts-tree' do + = icon('files-o fw') + %span + Files - - if project_nav_tab? :pipelines - = nav_link(controller: :pipelines) do - = link_to project_pipelines_path(@project), title: 'Pipelines', class: 'shortcuts-pipelines' do - = icon('ship fw') - %span - Pipelines - %span.badge.count.ci_counter= number_with_delimiter(@project.ci_commits.running_or_pending.count) + - if project_nav_tab? :commits + = nav_link(controller: %w(commit commits compare repositories tags branches releases network)) do + = link_to project_commits_path(@project), title: 'Commits', class: 'shortcuts-commits' do + = icon('history fw') + %span + Commits - - if project_nav_tab? :builds - = nav_link(controller: %w(builds)) do - = link_to project_builds_path(@project), title: 'Builds', class: 'shortcuts-builds' do - = icon('cubes fw') - %span - Builds - %span.badge.count.builds_counter= number_with_delimiter(@project.builds.running_or_pending.count(:all)) + - if project_nav_tab? :pipelines + = nav_link(controller: :pipelines) do + = link_to project_pipelines_path(@project), title: 'Pipelines', class: 'shortcuts-pipelines' do + = icon('ship fw') + %span + Pipelines + %span.badge.count.ci_counter= number_with_delimiter(@project.ci_commits.running_or_pending.count) - - if project_nav_tab? :container_registry - = nav_link(controller: %w(container_registry)) do - = link_to project_container_registry_path(@project), title: 'Container Registry', class: 'shortcuts-container-registry' do - = icon('hdd-o fw') - %span - Container Registry + - if project_nav_tab? :builds + = nav_link(controller: %w(builds)) do + = link_to project_builds_path(@project), title: 'Builds', class: 'shortcuts-builds' do + = icon('cubes fw') + %span + Builds + %span.badge.count.builds_counter= number_with_delimiter(@project.builds.running_or_pending.count(:all)) - - if project_nav_tab? :graphs - = nav_link(controller: %w(graphs)) do - = link_to namespace_project_graph_path(@project.namespace, @project, current_ref), title: 'Graphs', class: 'shortcuts-graphs' do - = icon('area-chart fw') - %span - Graphs + - if project_nav_tab? :container_registry + = nav_link(controller: %w(container_registry)) do + = link_to project_container_registry_path(@project), title: 'Container Registry', class: 'shortcuts-container-registry' do + = icon('hdd-o fw') + %span + Container Registry - - if project_nav_tab? :milestones - = nav_link(controller: :milestones) do - = link_to namespace_project_milestones_path(@project.namespace, @project), title: 'Milestones' do - = icon('clock-o fw') - %span - Milestones + - if project_nav_tab? :graphs + = nav_link(controller: %w(graphs)) do + = link_to namespace_project_graph_path(@project.namespace, @project, current_ref), title: 'Graphs', class: 'shortcuts-graphs' do + = icon('area-chart fw') + %span + Graphs - - if project_nav_tab? :issues - = nav_link(controller: :issues) do - = link_to url_for_project_issues(@project, only_path: true), title: 'Issues', class: 'shortcuts-issues' do - = icon('exclamation-circle fw') - %span - Issues - - if @project.default_issues_tracker? - %span.badge.count.issue_counter= number_with_delimiter(@project.issues.visible_to_user(current_user).opened.count) + - if project_nav_tab? :milestones + = nav_link(controller: :milestones) do + = link_to namespace_project_milestones_path(@project.namespace, @project), title: 'Milestones' do + = icon('clock-o fw') + %span + Milestones - - 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 - = icon('tasks fw') - %span - Merge Requests - %span.badge.count.merge_counter= number_with_delimiter(@project.merge_requests.opened.count) + - if project_nav_tab? :issues + = nav_link(controller: :issues) do + = link_to url_for_project_issues(@project, only_path: true), title: 'Issues', class: 'shortcuts-issues' do + = icon('exclamation-circle fw') + %span + Issues + - if @project.default_issues_tracker? + %span.badge.count.issue_counter= number_with_delimiter(@project.issues.visible_to_user(current_user).opened.count) - - if project_nav_tab? :labels - = nav_link(controller: :labels) do - = link_to namespace_project_labels_path(@project.namespace, @project), title: 'Labels' do - = icon('tags fw') - %span - Labels + - 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 + = icon('tasks fw') + %span + Merge Requests + %span.badge.count.merge_counter= number_with_delimiter(@project.merge_requests.opened.count) - - if project_nav_tab? :wiki - = nav_link(controller: :wikis) do - = link_to get_project_wiki_path(@project), title: 'Wiki', class: 'shortcuts-wiki' do - = icon('book fw') - %span - Wiki + - if project_nav_tab? :labels + = nav_link(controller: :labels) do + = link_to namespace_project_labels_path(@project.namespace, @project), title: 'Labels' do + = icon('tags fw') + %span + Labels - - if project_nav_tab? :snippets - = nav_link(controller: :snippets) do - = link_to namespace_project_snippets_path(@project.namespace, @project), title: 'Snippets', class: 'shortcuts-snippets' do - = icon('clipboard fw') - %span - Snippets + - if project_nav_tab? :wiki + = nav_link(controller: :wikis) do + = link_to get_project_wiki_path(@project), title: 'Wiki', class: 'shortcuts-wiki' do + = icon('book fw') + %span + Wiki + + - if project_nav_tab? :snippets + = nav_link(controller: :snippets) do + = link_to namespace_project_snippets_path(@project.namespace, @project), title: 'Snippets', class: 'shortcuts-snippets' do + = icon('clipboard fw') + %span + Snippets + + -# Global shortcut to network page for compatibility + - if project_nav_tab? :network + %li.hidden + = link_to namespace_project_network_path(@project.namespace, @project, current_ref), title: 'Network', class: 'shortcuts-network' do + Network - -# Global shortcut to network page for compatibility - - if project_nav_tab? :network + -# Shortcut to create a new issue %li.hidden - = link_to namespace_project_network_path(@project.namespace, @project, current_ref), title: 'Network', class: 'shortcuts-network' do - Network + = link_to new_namespace_project_issue_path(@project.namespace, @project), class: 'shortcuts-new-issue' do + Create a new issue - -# Shortcut to create a new issue - %li.hidden - = link_to new_namespace_project_issue_path(@project.namespace, @project), class: 'shortcuts-new-issue' do - Create a new issue + .fade-right -- cgit v1.2.1 From 79f890ca8549132699bc8169eff73b5c7ff25699 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Wed, 25 May 2016 11:42:43 -0500 Subject: Add fade out to sub nav --- app/assets/javascripts/layout_nav.js.coffee | 8 ++--- app/assets/stylesheets/framework/nav.scss | 50 +++++++++++++++++++++-------- app/views/layouts/nav/_group.html.haml | 2 +- app/views/layouts/nav/_profile.html.haml | 2 +- app/views/layouts/nav/_project.html.haml | 2 +- app/views/shared/_event_filter.html.haml | 4 ++- 6 files changed, 46 insertions(+), 22 deletions(-) diff --git a/app/assets/javascripts/layout_nav.js.coffee b/app/assets/javascripts/layout_nav.js.coffee index 43dc941a82f..3c39ec32f26 100644 --- a/app/assets/javascripts/layout_nav.js.coffee +++ b/app/assets/javascripts/layout_nav.js.coffee @@ -1,13 +1,13 @@ class @LayoutNav $ -> $('.fade-left').addClass('end-scroll') - $('#scrolling-tabs').on 'scroll', -> + $('.scrolling-tabs').scroll (event) -> + el = $(event.target) currentPosition = $(this).scrollLeft() - $('.fade-left').toggleClass('end-scroll', currentPosition is 0) - mobileScreenWidth = 480 controlBtnWidth = $('.controls').width() maxPosition = $(this)[0].scrollWidth - $(this).parent().width() maxPosition += controlBtnWidth if $('.nav-control').length and $(window).width() > mobileScreenWidth - $('.fade-right').toggleClass('end-scroll', currentPosition is maxPosition) + el.find('.fade-left').toggleClass('end-scroll', currentPosition is 0) + el.find('.fade-right').toggleClass('end-scroll', currentPosition is maxPosition) diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index 59e9a036f71..fdd60d85db8 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -1,4 +1,4 @@ -@mixin fade($gradient-direction) { +@mixin fade($gradient-direction, $rgba, $gradient-color) { visibility: visible; opacity: 1; position: absolute; @@ -7,10 +7,10 @@ height: 30px; transition-duration: .3s; -webkit-transform: translateZ(0); - background: -webkit-linear-gradient($gradient-direction, rgba(250, 250, 250, 0.4), $background-color 45%); - background: -o-linear-gradient($gradient-direction, rgba(250, 250, 250, 0.4), $background-color 45%); - background: -moz-linear-gradient($gradient-direction, rgba(250, 250, 250, 0.4), $background-color 45%); - background: linear-gradient($gradient-direction, rgba(250, 250, 250, 0.4), $background-color 45%); + background: -webkit-linear-gradient($gradient-direction, $rgba, $gradient-color 45%); + background: -o-linear-gradient($gradient-direction, $rgba, $gradient-color 45%); + background: -moz-linear-gradient($gradient-direction, $rgba, $gradient-color 45%); + background: linear-gradient($gradient-direction, $rgba, $gradient-color 45%); &.end-scroll { visibility: hidden; @@ -19,6 +19,16 @@ } } +@mixin scrolling-links() { + white-space: nowrap; + overflow-x: auto; + overflow-y: hidden; + -webkit-overflow-scrolling: touch; + &::-webkit-scrollbar { + display: none; + } +} + .nav-links { padding: 0; margin: 0; @@ -262,23 +272,17 @@ } .nav-links { + @include scrolling-links(); border-bottom: none; height: 51px; - white-space: nowrap; - overflow-x: auto; - overflow-y: hidden; - -webkit-overflow-scrolling: touch; - &::-webkit-scrollbar { - display: none; - } .fade-right { - @include fade(left); + @include fade(left, rgba(250, 250, 250, 0.4), $background-color); right: 0; } .fade-left { - @include fade(right); + @include fade(right, rgba(250, 250, 250, 0.4), $background-color); left: 0; } @@ -318,6 +322,24 @@ } } +.nav-block { + position: relative; + + .nav-links { + @include scrolling-links(); + + .fade-right { + @include fade(left, rgba(255, 255, 255, 0.4), $white-light); + right: 0; + } + + .fade-left { + @include fade(right, rgba(255, 255, 255, 0.4), $white-light); + left: 0; + } + } +} + .page-with-layout-nav { margin-top: $header-height + 2; diff --git a/app/views/layouts/nav/_group.html.haml b/app/views/layouts/nav/_group.html.haml index 9b8319c51ca..de15add3617 100644 --- a/app/views/layouts/nav/_group.html.haml +++ b/app/views/layouts/nav/_group.html.haml @@ -1,7 +1,7 @@ %div{ class: nav_control_class } = render 'layouts/nav/group_settings' - %ul.nav-links#scrolling-tabs + %ul.nav-links.scrolling-tabs .fade-left = nav_link(path: 'groups#show', html_options: {class: 'home'}) do = link_to group_path(@group), title: 'Home' do diff --git a/app/views/layouts/nav/_profile.html.haml b/app/views/layouts/nav/_profile.html.haml index a31584c7f81..2efc6c48a48 100644 --- a/app/views/layouts/nav/_profile.html.haml +++ b/app/views/layouts/nav/_profile.html.haml @@ -1,4 +1,4 @@ -%ul.nav-links#scrolling-tabs +%ul.nav-links.scrolling-tabs .fade-left = nav_link(path: 'profiles#show', html_options: {class: 'home'}) do = link_to profile_path, title: 'Profile Settings' do diff --git a/app/views/layouts/nav/_project.html.haml b/app/views/layouts/nav/_project.html.haml index bffa583fda3..087b7472701 100644 --- a/app/views/layouts/nav/_project.html.haml +++ b/app/views/layouts/nav/_project.html.haml @@ -20,7 +20,7 @@ Leave Project %div{ class: nav_control_class } - %ul.nav-links#scrolling-tabs + %ul.nav-links.scrolling-tabs .fade-left = nav_link(path: 'projects#show', html_options: {class: 'home'}) do = link_to project_path(@project), title: 'Project', class: 'shortcuts-project' do diff --git a/app/views/shared/_event_filter.html.haml b/app/views/shared/_event_filter.html.haml index c38d9313dba..30055002213 100644 --- a/app/views/shared/_event_filter.html.haml +++ b/app/views/shared/_event_filter.html.haml @@ -1,5 +1,7 @@ -%ul.nav-links.event-filter +%ul.nav-links.event-filter.scrolling-tabs + .fade-left = event_filter_link EventFilter.push, 'Push events' = event_filter_link EventFilter.merged, 'Merge events' = event_filter_link EventFilter.comments, 'Comments' = event_filter_link EventFilter.team, 'Team' + .fade-right -- cgit v1.2.1 From ec6d456b5023b4a0700a4c9ad8a17ed64b0470e6 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Wed, 25 May 2016 17:12:39 -0500 Subject: Change to xs breakpoint, layout_nav updates --- app/assets/javascripts/layout_nav.js.coffee | 17 +++++++++-------- app/assets/stylesheets/framework/nav.scss | 5 ++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/assets/javascripts/layout_nav.js.coffee b/app/assets/javascripts/layout_nav.js.coffee index 3c39ec32f26..6adac6dac97 100644 --- a/app/assets/javascripts/layout_nav.js.coffee +++ b/app/assets/javascripts/layout_nav.js.coffee @@ -1,13 +1,14 @@ class @LayoutNav $ -> $('.fade-left').addClass('end-scroll') - $('.scrolling-tabs').scroll (event) -> - el = $(event.target) - currentPosition = $(this).scrollLeft() - mobileScreenWidth = 480 + $('.scrolling-tabs').on 'scroll', (event) -> + $this = $(this) + $el = $(event.target) + currentPosition = $this.scrollLeft() + size = bp.getBreakpointSize() controlBtnWidth = $('.controls').width() - maxPosition = $(this)[0].scrollWidth - $(this).parent().width() - maxPosition += controlBtnWidth if $('.nav-control').length and $(window).width() > mobileScreenWidth + maxPosition = $this.get(0).scrollWidth - $this.parent().width() + maxPosition += controlBtnWidth if size isnt 'xs' and $('.nav-control').length - el.find('.fade-left').toggleClass('end-scroll', currentPosition is 0) - el.find('.fade-right').toggleClass('end-scroll', currentPosition is maxPosition) + $el.find('.fade-left').toggleClass('end-scroll', currentPosition is 0) + $el.find('.fade-right').toggleClass('end-scroll', currentPosition is maxPosition) diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index fdd60d85db8..adfe5540704 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -2,7 +2,7 @@ visibility: visible; opacity: 1; position: absolute; - bottom: 16px; + bottom: 12px; width: 43px; height: 30px; transition-duration: .3s; @@ -240,7 +240,7 @@ float: right; padding: 7px 0 0; - @media (max-width: $screen-xs-min) { + @media (max-width: $screen-xs-max) { display: none; } @@ -310,7 +310,6 @@ .nav-control { .fade-right { - right: 58px; @media (min-width: $screen-xs-max) { right: 67px; -- cgit v1.2.1