summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG2
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.lock12
-rw-r--r--app/assets/javascripts/awards_handler.coffee15
-rw-r--r--app/assets/javascripts/merge_request_tabs.js.coffee3
-rw-r--r--app/assets/javascripts/subscription.js.coffee4
-rw-r--r--app/assets/stylesheets/pages/labels.scss58
-rw-r--r--app/controllers/application_controller.rb10
-rw-r--r--app/views/projects/_md_preview.html.haml6
-rw-r--r--app/views/projects/labels/_label.html.haml17
-rw-r--r--app/views/shared/_label_row.html.haml3
-rw-r--r--app/views/votes/_votes_block.html.haml2
-rw-r--r--config/environments/production.rb3
-rw-r--r--db/fixtures/development/07_milestones.rb2
-rw-r--r--db/migrate/20130315124931_user_color_scheme.rb4
-rw-r--r--db/migrate/20130403003950_add_last_activity_column_into_project.rb16
-rw-r--r--db/migrate/20131112220935_add_visibility_level_to_projects.rb6
-rw-r--r--db/migrate/20140313092127_migrate_already_imported_projects.rb8
-rw-r--r--db/migrate/20141007100818_add_visibility_level_to_snippet.rb14
-rw-r--r--doc/ci/build_artifacts/README.md13
-rw-r--r--doc/integration/README.md17
-rw-r--r--doc/project_services/project_services.md19
-rw-r--r--features/steps/project/issues/labels.rb2
-rw-r--r--spec/features/issues/award_emoji_spec.rb64
24 files changed, 235 insertions, 67 deletions
diff --git a/CHANGELOG b/CHANGELOG
index c25ee3c71d3..3561c541df0 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.7.0 (unreleased)
+ - Enable gzip for assets, makes the page size significantly smaller. !3544 / !3632 (Connor Shea)
- Load award emoji images separately unless opening the full picker. Saves several hundred KBs of data for most pages. (Connor Shea)
- All images in discussions and wikis now link to their source files !3464 (Connor Shea).
- Return status code 303 after a branch DELETE operation to avoid project deletion (Stan Hu)
@@ -45,6 +46,7 @@ v 8.6.5
v 8.6.4
- Don't attempt to fetch any tags from a forked repo (Stan Hu)
+ - Redesign the Labels page
v 8.6.3
- Mentions on confidential issues doesn't create todos for non-members. !3374
diff --git a/Gemfile b/Gemfile
index 298cfd260ba..258b5612cd5 100644
--- a/Gemfile
+++ b/Gemfile
@@ -239,7 +239,7 @@ group :development do
gem "foreman"
gem 'brakeman', '~> 3.2.0', require: false
- gem "annotate", "~> 2.6.0"
+ gem "annotate", "~> 2.7.0"
gem "letter_opener", '~> 1.1.2'
gem 'quiet_assets', '~> 1.0.2'
gem 'rerun', '~> 0.11.0'
diff --git a/Gemfile.lock b/Gemfile.lock
index 28b71ac7bc8..9da44a46583 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -51,8 +51,8 @@ GEM
activerecord (>= 3.0)
akismet (2.0.0)
allocations (1.0.4)
- annotate (2.6.10)
- activerecord (>= 3.2, <= 4.3)
+ annotate (2.7.0)
+ activerecord (>= 3.2, < 6.0)
rake (~> 10.4)
arel (6.0.3)
asana (0.4.0)
@@ -145,7 +145,7 @@ GEM
crack (0.4.3)
safe_yaml (~> 1.0.0)
creole (0.5.0)
- css_parser (1.3.7)
+ css_parser (1.4.1)
addressable
d3_rails (3.5.11)
railties (>= 3.1.0)
@@ -559,8 +559,8 @@ GEM
premailer (1.8.6)
css_parser (>= 1.3.6)
htmlentities (>= 4.0.0)
- premailer-rails (1.9.0)
- actionmailer (>= 3, < 5)
+ premailer-rails (1.9.2)
+ actionmailer (>= 3, < 6)
premailer (~> 1.7, >= 1.7.9)
pry (0.10.3)
coderay (~> 1.1.0)
@@ -888,7 +888,7 @@ DEPENDENCIES
after_commit_queue
akismet (~> 2.0)
allocations (~> 1.0)
- annotate (~> 2.6.0)
+ annotate (~> 2.7.0)
asana (~> 0.4.0)
asciidoctor (~> 1.5.2)
attr_encrypted (~> 1.3.4)
diff --git a/app/assets/javascripts/awards_handler.coffee b/app/assets/javascripts/awards_handler.coffee
index 6a670d5e887..af4462ece38 100644
--- a/app/assets/javascripts/awards_handler.coffee
+++ b/app/assets/javascripts/awards_handler.coffee
@@ -22,8 +22,19 @@ class @AwardsHandler
emoji = $(this)
.find(".icon")
.data "emoji"
+
+ if emoji is "thumbsup" and awards_handler.didUserClickEmoji $(this), "thumbsdown"
+ awards_handler.addAward "thumbsdown"
+
+ else if emoji is "thumbsdown" and awards_handler.didUserClickEmoji $(this), "thumbsup"
+ awards_handler.addAward "thumbsup"
+
awards_handler.addAward emoji
+ didUserClickEmoji: (that, emoji) ->
+ if $(that).siblings("button:has([data-emoji=#{emoji}])").attr("data-original-title")
+ $(that).siblings("button:has([data-emoji=#{emoji}])").attr("data-original-title").indexOf('me') > -1
+
showEmojiMenu: ->
if $(".emoji-menu").length
if $(".emoji-menu").is ".is-visible"
@@ -105,7 +116,7 @@ class @AwardsHandler
if origTitle
authors = origTitle.split(', ')
authors.push("me")
- award_block.attr("title", authors.join(", "))
+ award_block.attr("data-original-title", authors.join(", "))
@resetTooltip(award_block)
resetTooltip: (award) ->
@@ -122,7 +133,7 @@ class @AwardsHandler
nodes = []
nodes.push(
- "<button class='btn award-control js-emoji-btn has-tooltip active' title='me'>",
+ "<button class='btn award-control js-emoji-btn has-tooltip active' data-original-title='me'>",
"<div class='icon emoji-icon #{emojiCssClass}' data-emoji='#{emoji}'></div>",
"<span class='award-control-text js-counter'>1</span>",
"</button>"
diff --git a/app/assets/javascripts/merge_request_tabs.js.coffee b/app/assets/javascripts/merge_request_tabs.js.coffee
index 839e6ec2c08..9946249adbf 100644
--- a/app/assets/javascripts/merge_request_tabs.js.coffee
+++ b/app/assets/javascripts/merge_request_tabs.js.coffee
@@ -73,7 +73,8 @@ class @MergeRequestTabs
@expandView()
else if action == 'diffs'
@loadDiff($target.attr('href'))
- @shrinkView()
+ if bp? and bp.getBreakpointSize() isnt 'lg'
+ @shrinkView()
else if action == 'builds'
@loadBuilds($target.attr('href'))
@expandView()
diff --git a/app/assets/javascripts/subscription.js.coffee b/app/assets/javascripts/subscription.js.coffee
index 084f0e0dc65..e4b7a3172ec 100644
--- a/app/assets/javascripts/subscription.js.coffee
+++ b/app/assets/javascripts/subscription.js.coffee
@@ -10,10 +10,10 @@ class @Subscription
btn = $(event.currentTarget)
action = btn.find('span').text()
current_status = @subscription_status.attr('data-status')
- btn.prop('disabled', true)
+ btn.addClass('disabled')
$.post @url, =>
- btn.prop('disabled', false)
+ btn.removeClass('disabled')
status = if current_status == 'subscribed' then 'unsubscribed' else 'subscribed'
@subscription_status.attr('data-status', status)
action = if status == 'subscribed' then 'Unsubscribe' else 'Subscribe'
diff --git a/app/assets/stylesheets/pages/labels.scss b/app/assets/stylesheets/pages/labels.scss
index 4e02ec4e891..3e0a3140be7 100644
--- a/app/assets/stylesheets/pages/labels.scss
+++ b/app/assets/stylesheets/pages/labels.scss
@@ -49,6 +49,15 @@
}
.label-row {
+ .label-name {
+ display: inline-block;
+ width: 200px;
+
+ @media (max-width: $screen-xs-min) {
+ display: block;
+ }
+ }
+
.label {
padding: 9px;
font-size: 14px;
@@ -69,3 +78,52 @@
background-color: $gl-danger;
color: $white-light;
}
+
+.manage-labels-list {
+
+ .prepend-left-10 {
+ display: inline-block;
+ width: 40%;
+ vertical-align: middle;
+
+ @media (max-width: $screen-xs-min) {
+ display: block;
+ width: 100%;
+ margin-left: 0;
+ padding: 10px 0;
+ }
+ }
+
+ .pull-info-right {
+ float: right;
+
+ @media (max-width: $screen-xs-min) {
+ float: none;
+ }
+
+ .action-buttons {
+ border-color: transparent;
+ padding: 6px;
+ color: $gl-text-color;
+
+ &.subscribe-button {
+ padding-left: 0;
+ }
+ }
+
+ i {
+ color: $gl-text-color;
+ }
+
+ .append-right-20 {
+ a {
+ color: $gl-text-color;
+ }
+
+ @media (max-width: $screen-xs-min) {
+ display: block;
+ margin-bottom: 10px;
+ }
+ }
+ }
+}
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index c81cb85dc1b..97d53acde94 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -47,6 +47,16 @@ class ApplicationController < ActionController::Base
email: current_user.email,
username: current_user.username,
)
+
+ Raven.tags_context(program: sentry_program_context)
+ end
+ end
+
+ def sentry_program_context
+ if Sidekiq.server?
+ 'sidekiq'
+ else
+ 'rails'
end
end
diff --git a/app/views/projects/_md_preview.html.haml b/app/views/projects/_md_preview.html.haml
index 4920910fee1..7a78d61a611 100644
--- a/app/views/projects/_md_preview.html.haml
+++ b/app/views/projects/_md_preview.html.haml
@@ -2,13 +2,13 @@
.md-header
%ul.nav-links
%li.active
- %a.js-md-write-button{ href: "#md-write-holder" }
+ %a.js-md-write-button{ href: "#md-write-holder", tabindex: -1 }
Write
%li
- %a.js-md-preview-button{ href: "#md-preview-holder" }
+ %a.js-md-preview-button{ href: "#md-preview-holder", tabindex: -1 }
Preview
%li.pull-right
- %button.zen-cotrol.zen-control-full.js-zen-enter{ type: 'button' }
+ %button.zen-cotrol.zen-control-full.js-zen-enter{ type: 'button', tabindex: -1 }
Go full screen
.md-write-holder
diff --git a/app/views/projects/labels/_label.html.haml b/app/views/projects/labels/_label.html.haml
index 0612863296a..097a65969a6 100644
--- a/app/views/projects/labels/_label.html.haml
+++ b/app/views/projects/labels/_label.html.haml
@@ -1,24 +1,27 @@
%li{id: dom_id(label)}
= render "shared/label_row", label: label
- .pull-right
- %strong.append-right-20
+ .pull-info-right
+ %span.append-right-20
= link_to_label(label, type: :merge_request) do
- = pluralize label.open_merge_requests_count, 'open merge request'
+ = pluralize label.open_merge_requests_count, 'merge request'
- %strong.append-right-20
+ %span.append-right-20
= link_to_label(label) do
= pluralize label.open_issues_count(current_user), 'open issue'
- if current_user
.label-subscription{data: {url: toggle_subscription_namespace_project_label_path(@project.namespace, @project, label)}}
.subscription-status{data: {status: label_subscription_status(label)}}
- %button.btn.btn-sm.btn-info.subscribe-button
+
+ %a.subscribe-button.btn.action-buttons{data: {toggle: "tooltip"}}
%span= label_subscription_toggle_button_text(label)
- if can? current_user, :admin_label, @project
- = link_to 'Edit', edit_namespace_project_label_path(@project.namespace, @project, label), class: 'btn btn-sm'
- = link_to 'Delete', namespace_project_label_path(@project.namespace, @project, label), class: 'btn btn-sm btn-remove remove-row', method: :delete, remote: true, data: {confirm: "Remove this label? Are you sure?"}
+ = link_to edit_namespace_project_label_path(@project.namespace, @project, label), title: "Edit", class: 'btn action-buttons', data: {toggle: "tooltip"} do
+ %i.fa.fa-pencil-square-o
+ = link_to namespace_project_label_path(@project.namespace, @project, label), title: "Delete", class: 'btn action-buttons remove-row', method: :delete, remote: true, data: {confirm: "Remove this label? Are you sure?", toggle: "tooltip"} do
+ %i.fa.fa-trash-o
- if current_user
:javascript
diff --git a/app/views/shared/_label_row.html.haml b/app/views/shared/_label_row.html.haml
index 4b47b0291be..b38c5e18efb 100644
--- a/app/views/shared/_label_row.html.haml
+++ b/app/views/shared/_label_row.html.haml
@@ -1,4 +1,5 @@
%span.label-row
- = link_to_label(label, tooltip: false)
+ %span.label-name
+ = link_to_label(label, tooltip: false)
%span.prepend-left-10
= markdown(label.description, pipeline: :single_line)
diff --git a/app/views/votes/_votes_block.html.haml b/app/views/votes/_votes_block.html.haml
index 49cfcd53d74..dc249155b92 100644
--- a/app/views/votes/_votes_block.html.haml
+++ b/app/views/votes/_votes_block.html.haml
@@ -1,6 +1,6 @@
.awards.votes-block
- awards_sort(votable.notes.awards.grouped_awards).each do |emoji, notes|
- %button.btn.award-control.js-emoji-btn.has-tooltip{class: (note_active_class(notes, current_user)), title: emoji_author_list(notes, current_user), data: {placement: "top"}}
+ %button.btn.award-control.js-emoji-btn.has-tooltip{class: (note_active_class(notes, current_user)), data: {placement: "top", original_title: emoji_author_list(notes, current_user)}}
= emoji_icon(emoji, sprite: false)
%span.award-control-text.js-counter
= notes.count
diff --git a/config/environments/production.rb b/config/environments/production.rb
index 909526605a1..a9d8ac4b6d4 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -21,6 +21,9 @@ Rails.application.configure do
# Generate digests for assets URLs
config.assets.digest = true
+ # Enable compression of compiled assets using gzip.
+ config.assets.compress = true
+
# Defaults to nil and saved in location specified by config.assets.prefix
# config.assets.manifest = YOUR_PATH
diff --git a/db/fixtures/development/07_milestones.rb b/db/fixtures/development/07_milestones.rb
index e028ac82ba3..540e4e68259 100644
--- a/db/fixtures/development/07_milestones.rb
+++ b/db/fixtures/development/07_milestones.rb
@@ -4,7 +4,7 @@ Gitlab::Seeder.quiet do
milestone_params = {
title: "v#{i}.0",
description: FFaker::Lorem.sentence,
- state: ['opened', 'closed'].sample,
+ state: [:active, :closed].sample,
}
milestone = Milestones::CreateService.new(
diff --git a/db/migrate/20130315124931_user_color_scheme.rb b/db/migrate/20130315124931_user_color_scheme.rb
index fe139e32ea7..56c9a31ee3c 100644
--- a/db/migrate/20130315124931_user_color_scheme.rb
+++ b/db/migrate/20130315124931_user_color_scheme.rb
@@ -1,7 +1,9 @@
class UserColorScheme < ActiveRecord::Migration
+ include Gitlab::Database
+
def up
add_column :users, :color_scheme_id, :integer, null: false, default: 1
- User.where(dark_scheme: true).update_all(color_scheme_id: 2)
+ execute("UPDATE users SET color_scheme_id = 2 WHERE dark_scheme = #{true_value}")
remove_column :users, :dark_scheme
end
diff --git a/db/migrate/20130403003950_add_last_activity_column_into_project.rb b/db/migrate/20130403003950_add_last_activity_column_into_project.rb
index 2a036bd9993..85e31608d79 100644
--- a/db/migrate/20130403003950_add_last_activity_column_into_project.rb
+++ b/db/migrate/20130403003950_add_last_activity_column_into_project.rb
@@ -3,14 +3,16 @@ class AddLastActivityColumnIntoProject < ActiveRecord::Migration
add_column :projects, :last_activity_at, :datetime
add_index :projects, :last_activity_at
- Project.find_each do |project|
- last_activity_date = if project.last_activity
- project.last_activity.created_at
- else
- project.updated_at
- end
+ select_all('SELECT id, updated_at FROM projects').each do |project|
+ project_id = project['id']
+ update_date = project['updated_at']
+ event = select_one("SELECT created_at FROM events WHERE project_id = #{project_id} ORDER BY created_at DESC LIMIT 1")
- project.update_attribute(:last_activity_at, last_activity_date)
+ if event && event['created_at']
+ update_date = event['created_at']
+ end
+
+ execute("UPDATE projects SET last_activity_at = '#{update_date}' WHERE id = #{project_id}")
end
end
diff --git a/db/migrate/20131112220935_add_visibility_level_to_projects.rb b/db/migrate/20131112220935_add_visibility_level_to_projects.rb
index cf1e9f912a0..89421cbedad 100644
--- a/db/migrate/20131112220935_add_visibility_level_to_projects.rb
+++ b/db/migrate/20131112220935_add_visibility_level_to_projects.rb
@@ -1,13 +1,15 @@
class AddVisibilityLevelToProjects < ActiveRecord::Migration
+ include Gitlab::Database
+
def self.up
add_column :projects, :visibility_level, :integer, :default => 0, :null => false
- Project.where(public: true).update_all(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
+ execute("UPDATE projects SET visibility_level = #{Gitlab::VisibilityLevel::PUBLIC} WHERE public = #{true_value}")
remove_column :projects, :public
end
def self.down
add_column :projects, :public, :boolean, :default => false, :null => false
- Project.where(visibility_level: Gitlab::VisibilityLevel::PUBLIC).update_all(public: true)
+ execute("UPDATE projects SET public = #{true_value} WHERE visibility_level = #{Gitlab::VisibilityLevel::PUBLIC}")
remove_column :projects, :visibility_level
end
end
diff --git a/db/migrate/20140313092127_migrate_already_imported_projects.rb b/db/migrate/20140313092127_migrate_already_imported_projects.rb
index f4392c0f05e..0a9f73a5758 100644
--- a/db/migrate/20140313092127_migrate_already_imported_projects.rb
+++ b/db/migrate/20140313092127_migrate_already_imported_projects.rb
@@ -1,12 +1,14 @@
class MigrateAlreadyImportedProjects < ActiveRecord::Migration
+ include Gitlab::Database
+
def up
- Project.where(imported: true).update_all(import_status: "finished")
- Project.where(imported: false).update_all(import_status: "none")
+ execute("UPDATE projects SET import_status = 'finished' WHERE imported = #{true_value}")
+ execute("UPDATE projects SET import_status = 'none' WHERE imported = #{false_value}")
remove_column :projects, :imported
end
def down
add_column :projects, :imported, :boolean, default: false
- Project.where(import_status: 'finished').update_all(imported: true)
+ execute("UPDATE projects SET imported = #{true_value} WHERE import_status = 'finished'")
end
end
diff --git a/db/migrate/20141007100818_add_visibility_level_to_snippet.rb b/db/migrate/20141007100818_add_visibility_level_to_snippet.rb
index 7f125acb5d1..93826185e8b 100644
--- a/db/migrate/20141007100818_add_visibility_level_to_snippet.rb
+++ b/db/migrate/20141007100818_add_visibility_level_to_snippet.rb
@@ -1,9 +1,11 @@
class AddVisibilityLevelToSnippet < ActiveRecord::Migration
+ include Gitlab::Database
+
def up
add_column :snippets, :visibility_level, :integer, :default => 0, :null => false
- Snippet.where(private: true).update_all(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
- Snippet.where(private: false).update_all(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
+ execute("UPDATE snippets SET visibility_level = #{Gitlab::VisibilityLevel::PRIVATE} WHERE private = #{true_value}")
+ execute("UPDATE snippets SET visibility_level = #{Gitlab::VisibilityLevel::INTERNAL} WHERE private = #{false_value}")
add_index :snippets, :visibility_level
@@ -12,10 +14,10 @@ class AddVisibilityLevelToSnippet < ActiveRecord::Migration
def down
add_column :snippets, :private, :boolean, :default => false, :null => false
-
- Snippet.where(visibility_level: Gitlab::VisibilityLevel::INTERNAL).update_all(private: false)
- Snippet.where(visibility_level: Gitlab::VisibilityLevel::PRIVATE).update_all(private: true)
-
+
+ execute("UPDATE snippets SET private = #{false_value} WHERE visibility_level = #{Gitlab::VisibilityLevel::INTERNAL}")
+ execute("UPDATE snippets SET private = #{true_value} WHERE visibility_level = #{Gitlab::VisibilityLevel::PRIVATE}")
+
remove_column :snippets, :visibility_level
end
end
diff --git a/doc/ci/build_artifacts/README.md b/doc/ci/build_artifacts/README.md
index 71db5aa5dc8..9553bb11e9d 100644
--- a/doc/ci/build_artifacts/README.md
+++ b/doc/ci/build_artifacts/README.md
@@ -1,7 +1,10 @@
# Introduction to build artifacts
Artifacts is a list of files and directories which are attached to a build
-after it completes successfully.
+after it completes successfully. This feature is enabled by default in all GitLab installations.
+
+_If you are searching for ways to use artifacts, jump to
+[Defining artifacts in `.gitlab-ci.yml`](#defining-artifacts-in-gitlab-ciyml)._
Since GitLab 8.2 and [GitLab Runner] 0.7.0, build artifacts that are created by
GitLab Runner are uploaded to GitLab and are downloadable as a single archive
@@ -16,13 +19,9 @@ The artifacts browser will be available only for new artifacts that are sent
to GitLab using GitLab Runner version 1.0 and up. It will not be possible to
browse old artifacts already uploaded to GitLab.
-## Enabling build artifacts
-
-_If you are searching for ways to use artifacts, jump to
-[Defining artifacts in `.gitlab-ci.yml`](#defining-artifacts-in-gitlab-ciyml)._
+## Disabling build artifacts
-The artifacts feature is enabled by default in all GitLab installations.
-To disable it site-wide, follow the steps below.
+To disable artifacts site-wide, follow the steps below.
---
diff --git a/doc/integration/README.md b/doc/integration/README.md
index 7c8f785a61f..6fe04aa2a06 100644
--- a/doc/integration/README.md
+++ b/doc/integration/README.md
@@ -19,26 +19,15 @@ See the documentation below for details on how to configure these services.
GitLab Enterprise Edition contains [advanced Jenkins support][jenkins].
+[jenkins]: http://doc.gitlab.com/ee/integration/jenkins.html
+
+
## Project services
Integration with services such as Campfire, Flowdock, Gemnasium, HipChat,
Pivotal Tracker, and Slack are available in the form of a [Project Service][].
-You can find these within GitLab in the Services page under Project Settings if
-you are at least a master on the project.
-Project Services are a bit like plugins in that they allow a lot of freedom in
-adding functionality to GitLab. For example there is also a service that can
-send an email every time someone pushes new commits.
-Because GitLab is open source we can ship with the code and tests for all
-plugins. This allows the community to keep the plugins up to date so that they
-always work in newer GitLab versions.
-
-For an overview of what projects services are available without logging in,
-please see the [project_services directory][projects-code].
-
-[jenkins]: http://doc.gitlab.com/ee/integration/jenkins.html
[Project Service]: ../project_services/project_services.md
-[projects-code]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/app/models/project_services
## SSL certificate errors
diff --git a/doc/project_services/project_services.md b/doc/project_services/project_services.md
index 3fea2cff0b9..a5af620d9be 100644
--- a/doc/project_services/project_services.md
+++ b/doc/project_services/project_services.md
@@ -1,7 +1,24 @@
# Project Services
Project services allow you to integrate GitLab with other applications. Below
-is list of the currently supported ones. Click on the service links to see
+is list of the currently supported ones.
+
+You can find these within GitLab in the Services page under Project Settings if
+you are at least a master on the project.
+Project Services are a bit like plugins in that they allow a lot of freedom in
+adding functionality to GitLab. For example there is also a service that can
+send an email every time someone pushes new commits.
+
+Because GitLab is open source we can ship with the code and tests for all
+plugins. This allows the community to keep the plugins up to date so that they
+always work in newer GitLab versions.
+
+For an overview of what projects services are available without logging in,
+please see the [project_services directory][projects-code].
+
+[projects-code]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/app/models/project_services
+
+Click on the service links to see
further configuration instructions and details. Contributions are welcome.
## Services
diff --git a/features/steps/project/issues/labels.rb b/features/steps/project/issues/labels.rb
index 2ab8956867b..0ca2d6257c3 100644
--- a/features/steps/project/issues/labels.rb
+++ b/features/steps/project/issues/labels.rb
@@ -15,7 +15,7 @@ class Spinach::Features::ProjectIssuesLabels < Spinach::FeatureSteps
step 'I delete all labels' do
page.within '.labels' do
- page.all('.btn-remove').each do |remove|
+ page.all('.remove-row').each do |remove|
remove.click
sleep 0.05
end
diff --git a/spec/features/issues/award_emoji_spec.rb b/spec/features/issues/award_emoji_spec.rb
new file mode 100644
index 00000000000..41af789aae2
--- /dev/null
+++ b/spec/features/issues/award_emoji_spec.rb
@@ -0,0 +1,64 @@
+require 'rails_helper'
+
+describe 'Awards Emoji', feature: true do
+ let!(:project) { create(:project) }
+ let!(:user) { create(:user) }
+
+ before do
+ project.team << [user, :master]
+ login_as(user)
+ end
+
+ describe 'Click award emoji from issue#show' do
+ let!(:issue) do
+ create(:issue,
+ author: @user,
+ assignee: @user,
+ project: project)
+ end
+
+ before do
+ visit namespace_project_issue_path(project.namespace, project, issue)
+ end
+
+ it 'should increment the thumbsdown emoji', js: true do
+ find('[data-emoji="thumbsdown"]').click
+ sleep 2
+ expect(thumbsdown_emoji).to have_text("1")
+ end
+
+ context 'click the thumbsup emoji' do
+
+ it 'should increment the thumbsup emoji', js: true do
+ find('[data-emoji="thumbsup"]').click
+ sleep 2
+ expect(thumbsup_emoji).to have_text("1")
+ end
+
+ it 'should decrement the thumbsdown emoji', js: true do
+ expect(thumbsdown_emoji).to have_text("0")
+ end
+ end
+
+ context 'click the thumbsdown emoji' do
+
+ it 'should increment the thumbsdown emoji', js: true do
+ find('[data-emoji="thumbsdown"]').click
+ sleep 2
+ expect(thumbsdown_emoji).to have_text("1")
+ end
+
+ it 'should decrement the thumbsup emoji', js: true do
+ expect(thumbsup_emoji).to have_text("0")
+ end
+ end
+ end
+
+ def thumbsup_emoji
+ page.all('span.js-counter').first
+ end
+
+ def thumbsdown_emoji
+ page.all('span.js-counter').last
+ end
+end