From a5f6af007a307b91b8fa45dfe821d5da31e32c47 Mon Sep 17 00:00:00 2001 From: Jan Bruckner Date: Mon, 5 Oct 2015 15:27:01 +0200 Subject: don't set LATEST_TAG automatically in patch update guide --- doc/update/patch_versions.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/update/patch_versions.md b/doc/update/patch_versions.md index a66a863f6c4..da719229ab6 100644 --- a/doc/update/patch_versions.md +++ b/doc/update/patch_versions.md @@ -23,9 +23,11 @@ sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production cd /home/git/gitlab sudo -u git -H git fetch --all sudo -u git -H git checkout -- Gemfile.lock db/schema.rb -LATEST_TAG=$(git describe --tags `git rev-list --tags --max-count=1`) -sudo -u git -H git checkout $LATEST_TAG -b $LATEST_TAG +sudo -u git -H git checkout LATEST_TAG -b LATEST_TAG ``` +Replace `LATEST_TAG` with the latest GitLab tag you want to update to, for example `v8.0.3`. +Use `git tag -l 'v*.[0-9]' --sort='v:refname'` to see a list of all tags. +Make sure to update patch versions only (check your current version with `cat VERSION`) ### 3. Update gitlab-shell to the corresponding version -- cgit v1.2.1 From 380392212f87fc80bd45c322eda54461d47745b0 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Wed, 30 Sep 2015 17:12:33 -0400 Subject: merge_request: coerce work_in_progress? into a boolean --- app/models/merge_request.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index eb468c6cd53..f69b7a13c4b 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -227,7 +227,7 @@ class MergeRequest < ActiveRecord::Base end def work_in_progress? - title =~ /\A\[?WIP\]?:? /i + !!(title =~ /\A\[?WIP\]?:? /i) end def mergeable? -- cgit v1.2.1 From b7def88c02b3726259800a25ee8bb82c866fe673 Mon Sep 17 00:00:00 2001 From: Drew Blessing Date: Thu, 8 Oct 2015 14:59:46 -0500 Subject: Fix ldap email downcasing bug --- lib/gitlab/ldap/user.rb | 2 +- spec/lib/gitlab/ldap/user_spec.rb | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/lib/gitlab/ldap/user.rb b/lib/gitlab/ldap/user.rb index 1ea7751e27d..4be99dd88c2 100644 --- a/lib/gitlab/ldap/user.rb +++ b/lib/gitlab/ldap/user.rb @@ -35,7 +35,7 @@ module Gitlab end def find_by_email - ::User.find_by(email: auth_hash.email) + ::User.find_by(email: auth_hash.email.downcase) end def update_user_attributes diff --git a/spec/lib/gitlab/ldap/user_spec.rb b/spec/lib/gitlab/ldap/user_spec.rb index fd2e5f6d0e1..b5b56a34952 100644 --- a/spec/lib/gitlab/ldap/user_spec.rb +++ b/spec/lib/gitlab/ldap/user_spec.rb @@ -13,6 +13,17 @@ describe Gitlab::LDAP::User do let(:auth_hash) do OmniAuth::AuthHash.new(uid: 'my-uid', provider: 'ldapmain', info: info) end + let(:ldap_user_upper_case) { Gitlab::LDAP::User.new(auth_hash_upper_case) } + let(:info_upper_case) do + { + name: 'John', + email: 'John@Example.com', # Email address has upper case chars + nickname: 'john' + } + end + let(:auth_hash_upper_case) do + OmniAuth::AuthHash.new(uid: 'my-uid', provider: 'ldapmain', info: info_upper_case) + end describe :changed? do it "marks existing ldap user as changed" do @@ -57,6 +68,16 @@ describe Gitlab::LDAP::User do expect(existing_user.id).to eql ldap_user.gl_user.id end + it 'connects to existing ldap user if the extern_uid changes and email address has upper case characters' do + existing_user = create(:omniauth_user, email: 'john@example.com', extern_uid: 'old-uid', provider: 'ldapmain') + expect{ ldap_user_upper_case.save }.not_to change{ User.count } + + existing_user.reload + expect(existing_user.ldap_identity.extern_uid).to eql 'my-uid' + expect(existing_user.ldap_identity.provider).to eql 'ldapmain' + expect(existing_user.id).to eql ldap_user.gl_user.id + end + it 'maintains an identity per provider' do existing_user = create(:omniauth_user, email: 'john@example.com', provider: 'twitter') expect(existing_user.identities.count).to eql(1) -- cgit v1.2.1 From 6b739027330cb07484b71c748e30d5966f63d647 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Fri, 25 Sep 2015 16:07:08 -0400 Subject: merge_request: add work_in_progress to MR hooks --- CHANGELOG | 1 + app/models/merge_request.rb | 3 ++- doc/web_hooks/web_hooks.md | 6 ++++-- spec/models/merge_request_spec.rb | 11 +++++++++++ 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 66b6e9fdf19..60d2600c497 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -53,6 +53,7 @@ v 8.0.3 - Fix URL shown in Slack notifications - Fix bug where projects would appear to be stuck in the forked import state (Stan Hu) - Fix Error 500 in creating merge requests with > 1000 diffs (Stan Hu) + - Add work_in_progress key to MR web hooks (Ben Boeckel) v 8.0.2 - Fix default avatar not rendering in network graph (Stan Hu) diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index f69b7a13c4b..c83b15c7d39 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -275,7 +275,8 @@ class MergeRequest < ActiveRecord::Base attrs = { source: source_project.hook_attrs, target: target_project.hook_attrs, - last_commit: nil + last_commit: nil, + work_in_progress: work_in_progress? } unless last_commit.nil? diff --git a/doc/web_hooks/web_hooks.md b/doc/web_hooks/web_hooks.md index c185ccfcac3..ef99a69f60a 100644 --- a/doc/web_hooks/web_hooks.md +++ b/doc/web_hooks/web_hooks.md @@ -314,7 +314,8 @@ X-Gitlab-Event: Note Hook "name": "John Smith", "email": "john@example.com" } - } + }, + "work_in_progress": false } } ``` @@ -500,6 +501,7 @@ X-Gitlab-Event: Merge Request Hook "email": "gitlabdev@dv6700.(none)" } }, + "work_in_progress": false, "url": "http://example.com/diaspora/merge_requests/1", "action": "open" } @@ -537,4 +539,4 @@ When you press 'Test Hook' in GitLab, you should see something like this in the {"before":"077a85dd266e6f3573ef7e9ef8ce3343ad659c4e","after":"95cd4a99e93bc4bbabacfa2cd10e6725b1403c60",} example.com - - [14/May/2014:07:45:26 EDT] "POST / HTTP/1.1" 200 0 - -> / -``` \ No newline at end of file +``` diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 17a49013d25..6aaf1c036b0 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -165,6 +165,17 @@ describe MergeRequest do end end + describe "#hook_attrs" do + it "has all the required keys" do + attrs = subject.hook_attrs + attrs = attrs.to_h + expect(attrs).to include(:source) + expect(attrs).to include(:target) + expect(attrs).to include(:last_commit) + expect(attrs).to include(:work_in_progress) + end + end + it_behaves_like 'an editable mentionable' do subject { create(:merge_request) } -- cgit v1.2.1 From 4ee8888498d7fc3921326d4929cf0b57e64411f4 Mon Sep 17 00:00:00 2001 From: Dale Noe Date: Sun, 11 Oct 2015 12:19:05 +0000 Subject: removed extra_sign_in_text examples for gitlab.rb [ci skip] --- doc/customization/welcome_message.md | 30 ++---------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/doc/customization/welcome_message.md b/doc/customization/welcome_message.md index 6c141d1fb7a..e993230bb88 100644 --- a/doc/customization/welcome_message.md +++ b/doc/customization/welcome_message.md @@ -8,31 +8,5 @@ It is possible to add a markdown-formatted welcome message to your GitLab sign-in page. Users of GitLab Enterprise Edition should use the [branded login page feature](/ee/customization/branded_login_page.html) instead. -## Omnibus-gitlab example - -In `/etc/gitlab/gitlab.rb`: - -```ruby -gitlab_rails['extra_sign_in_text'] = <<'EOS' -# ACME GitLab -Welcome to the [ACME](http://www.example.com) GitLab server! -EOS -``` - -Run `sudo gitlab-ctl reconfigure` for changes to take effect. - -## Installation from source - -In `/home/git/gitlab/config/gitlab.yml`: - -```yaml -# snip -production: - # snip - extra: - sign_in_text: | - # ACME GitLab - Welcome to the [ACME](http://www.example.com) GitLab server! -``` - -Run `sudo service gitlab reload` for the change to take effect. +The welcome message (extra_sign_in_text) can now be set/changed in the Admin UI. +Admin area > Settings \ No newline at end of file -- cgit v1.2.1 From bf23ce191ba6daf3dfca604243dd88d2e3996eff Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Sun, 11 Oct 2015 18:17:49 +0200 Subject: Enable arbitration in MailRoom --- Gemfile | 2 +- Gemfile.lock | 4 ++-- config/mail_room.yml.example | 12 +++++++++++- doc/incoming_email/README.md | 30 ++++++++++++++++++++++++++++++ 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/Gemfile b/Gemfile index e8cdb7a4a97..967092994a6 100644 --- a/Gemfile +++ b/Gemfile @@ -290,7 +290,7 @@ gem 'newrelic-grape' gem 'octokit', '~> 3.7.0' -gem "mail_room", "~> 0.5.2" +gem "mail_room", "~> 0.6.0" gem 'email_reply_parser', '~> 0.5.8' diff --git a/Gemfile.lock b/Gemfile.lock index 9911904d304..58426a60683 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -392,7 +392,7 @@ GEM systemu (~> 2.6.2) mail (2.6.3) mime-types (>= 1.16, < 3) - mail_room (0.5.2) + mail_room (0.6.0) method_source (0.8.2) mime-types (1.25.1) mimemagic (0.3.0) @@ -854,7 +854,7 @@ DEPENDENCIES jquery-ui-rails (~> 4.2.1) kaminari (~> 0.16.3) letter_opener (~> 1.1.2) - mail_room (~> 0.5.2) + mail_room (~> 0.6.0) minitest (~> 5.7.0) mousetrap-rails (~> 1.4.6) mysql2 (~> 0.3.16) diff --git a/config/mail_room.yml.example b/config/mail_room.yml.example index ed4a5193a6a..bb624e8a187 100644 --- a/config/mail_room.yml.example +++ b/config/mail_room.yml.example @@ -12,8 +12,10 @@ # :email: "gitlab-incoming@gmail.com" # # Email account password # :password: "password" + # # The name of the mailbox where incoming mail will end up. Usually "inbox". # :name: "inbox" + # # Always "sidekiq". # :delivery_method: sidekiq # # Always true. @@ -25,5 +27,13 @@ # :namespace: resque:gitlab # # Always "incoming_email". # :queue: incoming_email - # # Always "EmailReceiverWorker" + # # Always "EmailReceiverWorker". # :worker: EmailReceiverWorker + + # # Always "redis". + # :arbitration_method: redis + # :arbitration_options: + # # The URL to the Redis server. Should match the URL in config/resque.yml. + # :redis_url: redis://localhost:6379 + # # Always "mail_room:gitlab". + # :namespace: mail_room:gitlab diff --git a/doc/incoming_email/README.md b/doc/incoming_email/README.md index 87267423471..076c8c049a8 100644 --- a/doc/incoming_email/README.md +++ b/doc/incoming_email/README.md @@ -118,8 +118,10 @@ To set up a basic Postfix mail server with IMAP access on Ubuntu, follow [these :email: "incoming" # Email account password :password: "[REDACTED]" + # The name of the mailbox where incoming mail will end up. Usually "inbox". :name: "inbox" + # Always "sidekiq". :delivery_method: sidekiq # Always true. @@ -133,6 +135,14 @@ To set up a basic Postfix mail server with IMAP access on Ubuntu, follow [these :queue: incoming_email # Always "EmailReceiverWorker" :worker: EmailReceiverWorker + + # Always "redis". + :arbitration_method: redis + :arbitration_options: + # The URL to the Redis server. Should match the URL in config/resque.yml. + :redis_url: redis://localhost:6379 + # Always "mail_room:gitlab". + :namespace: mail_room:gitlab ``` ```yaml @@ -151,8 +161,10 @@ To set up a basic Postfix mail server with IMAP access on Ubuntu, follow [these :email: "gitlab-incoming@gmail.com" # Email account password :password: "[REDACTED]" + # The name of the mailbox where incoming mail will end up. Usually "inbox". :name: "inbox" + # Always "sidekiq". :delivery_method: sidekiq # Always true. @@ -166,6 +178,14 @@ To set up a basic Postfix mail server with IMAP access on Ubuntu, follow [these :queue: incoming_email # Always "EmailReceiverWorker" :worker: EmailReceiverWorker + + # Always "redis". + :arbitration_method: redis + :arbitration_options: + # The URL to the Redis server. Should match the URL in config/resque.yml. + :redis_url: redis://localhost:6379 + # Always "mail_room:gitlab". + :namespace: mail_room:gitlab ``` 5. Edit the init script configuration at `/etc/default/gitlab` to enable `mail_room`: @@ -228,8 +248,10 @@ To set up a basic Postfix mail server with IMAP access on Ubuntu, follow [these :email: "gitlab-incoming@gmail.com" # Email account password :password: "[REDACTED]" + # The name of the mailbox where incoming mail will end up. Usually "inbox". :name: "inbox" + # Always "sidekiq". :delivery_method: sidekiq # Always true. @@ -243,6 +265,14 @@ To set up a basic Postfix mail server with IMAP access on Ubuntu, follow [these :queue: incoming_email # Always "EmailReceiverWorker" :worker: EmailReceiverWorker + + # Always "redis". + :arbitration_method: redis + :arbitration_options: + # The URL to the Redis server. Should match the URL in config/resque.yml. + :redis_url: redis://localhost:6379 + # Always "mail_room:gitlab". + :namespace: mail_room:gitlab ``` 4. Uncomment the `mail_room` line in your `Procfile`: -- cgit v1.2.1 From 914cfbd2f154ed3154a7dc3cee3309713eea786f Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Tue, 6 Oct 2015 12:01:16 +0200 Subject: Implement Commit Status API --- CHANGELOG | 1 + app/models/ability.rb | 2 + app/models/ci/build.rb | 87 +---- app/models/ci/commit.rb | 88 +++-- app/models/commit.rb | 8 + app/models/commit_status.rb | 79 +++++ app/models/generic_commit_status.rb | 15 + app/services/ci/create_commit_service.rb | 2 + app/views/projects/builds/_build.html.haml | 50 --- app/views/projects/builds/show.html.haml | 6 +- app/views/projects/commit/ci.html.haml | 36 +- .../commit_statuses/_commit_status.html.haml | 52 +++ ...008123042_add_type_and_description_to_builds.rb | 9 + ...30321_migrate_name_to_description_for_builds.rb | 5 + db/schema.rb | 7 +- doc/api/commits.md | 3 +- lib/api/api.rb | 1 + lib/api/commit_statuses.rb | 79 +++++ lib/api/entities.rb | 8 +- lib/ci/api/entities.rb | 4 +- spec/factories/ci/builds.rb | 1 + spec/factories/commit_statuses.rb | 15 + spec/features/commits_spec.rb | 1 + spec/models/build_spec.rb | 276 +++++++++++++++ spec/models/ci/build_spec.rb | 387 --------------------- spec/models/ci/commit_spec.rb | 57 ++- .../ci/project_services/mail_service_spec.rb | 8 +- spec/models/commit_status_spec.rb | 157 +++++++++ spec/models/generic_commit_status_spec.rb | 39 +++ spec/requests/api/commit_status_spec.rb | 135 +++++++ spec/requests/api/commits_spec.rb | 13 + 31 files changed, 1043 insertions(+), 588 deletions(-) create mode 100644 app/models/commit_status.rb create mode 100644 app/models/generic_commit_status.rb delete mode 100644 app/views/projects/builds/_build.html.haml create mode 100644 app/views/projects/commit_statuses/_commit_status.html.haml create mode 100644 db/migrate/20151008123042_add_type_and_description_to_builds.rb create mode 100644 db/migrate/20151008130321_migrate_name_to_description_for_builds.rb create mode 100644 lib/api/commit_statuses.rb create mode 100644 spec/factories/commit_statuses.rb create mode 100644 spec/models/build_spec.rb delete mode 100644 spec/models/ci/build_spec.rb create mode 100644 spec/models/commit_status_spec.rb create mode 100644 spec/models/generic_commit_status_spec.rb create mode 100644 spec/requests/api/commit_status_spec.rb diff --git a/CHANGELOG b/CHANGELOG index a3d796bea66..e38d465dd96 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -16,6 +16,7 @@ v 8.1.0 (unreleased) - Move CI charts to project graphs area - Fix cases where Markdown did not render links in activity feed (Stan Hu) - Add first and last to pagination (Zeger-Jan van de Weg) + - Added Commit Status API - Show CI status on commit page - Show CI status on Your projects page and Starred projects page - Remove "Continuous Integration" page from dashboard diff --git a/app/models/ability.rb b/app/models/ability.rb index a020b24a550..77c121ca5e8 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -135,6 +135,8 @@ class Ability def project_report_rules project_guest_rules + [ + :create_commit_status, + :read_commit_statuses, :download_code, :fork_project, :create_project_snippet, diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 5d17f4418ed..41ce522b2ff 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -24,32 +24,19 @@ # module Ci - class Build < ActiveRecord::Base - extend Ci::Model - + class Build < CommitStatus LAZY_ATTRIBUTES = ['trace'] - belongs_to :commit, class_name: 'Ci::Commit' belongs_to :runner, class_name: 'Ci::Runner' belongs_to :trigger_request, class_name: 'Ci::TriggerRequest' - belongs_to :user serialize :options - validates :commit, presence: true - validates :status, presence: true validates :coverage, numericality: true, allow_blank: true validates_presence_of :ref - scope :running, ->() { where(status: "running") } - scope :pending, ->() { where(status: "pending") } - scope :success, ->() { where(status: "success") } - scope :failed, ->() { where(status: "failed") } scope :unstarted, ->() { where(runner_id: nil) } - scope :running_or_pending, ->() { where(status:[:running, :pending]) } - scope :latest, ->() { where(id: unscope(:select).select('max(id)').group(:name, :ref)).order(stage_idx: :asc) } scope :ignore_failures, ->() { where(allow_failure: false) } - scope :for_ref, ->(ref) { where(ref: ref) } scope :similar, ->(build) { where(ref: build.ref, tag: build.tag, trigger_request_id: build.trigger_request_id) } acts_as_taggable @@ -74,13 +61,14 @@ module Ci def create_from(build) new_build = build.dup - new_build.status = :pending + new_build.status = 'pending' new_build.runner_id = nil + new_build.trigger_request_id = nil new_build.save end def retry(build) - new_build = Ci::Build.new(status: :pending) + new_build = Ci::Build.new(status: 'pending') new_build.ref = build.ref new_build.tag = build.tag new_build.options = build.options @@ -98,28 +86,7 @@ module Ci end state_machine :status, initial: :pending do - event :run do - transition pending: :running - end - - event :drop do - transition running: :failed - end - - event :success do - transition running: :success - end - - event :cancel do - transition [:pending, :running] => :canceled - end - - after_transition pending: :running do |build, transition| - build.update_attributes started_at: Time.now - end - after_transition any => [:success, :failed, :canceled] do |build, transition| - build.update_attributes finished_at: Time.now project = build.project if project.web_hooks? @@ -136,19 +103,10 @@ module Ci build.update_coverage end end - - state :pending, value: 'pending' - state :running, value: 'running' - state :failed, value: 'failed' - state :success, value: 'success' - state :canceled, value: 'canceled' end - delegate :sha, :short_sha, :project, :gl_project, - to: :commit, prefix: false - - def before_sha - Gitlab::Git::BLANK_SHA + def ignored? + failed? && allow_failure? end def trace_html @@ -156,22 +114,6 @@ module Ci html || '' end - def started? - !pending? && !canceled? && started_at - end - - def active? - running? || pending? - end - - def complete? - canceled? || success? || failed? - end - - def ignored? - failed? && allow_failure? - end - def timeout project.timeout end @@ -180,14 +122,6 @@ module Ci yaml_variables + project_variables + trigger_variables end - def duration - if started_at && finished_at - finished_at - started_at - elsif started_at - Time.now - started_at - end - end - def project commit.project end @@ -278,6 +212,15 @@ module Ci "#{dir_to_trace}/#{id}.log" end + def description + name + end + + def target_url + Gitlab::Application.routes.url_helpers. + namespace_project_build_url(gl_project.namespace, gl_project, self) + end + private def yaml_variables diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb index fde754a92a1..042a68681bb 100644 --- a/app/models/ci/commit.rb +++ b/app/models/ci/commit.rb @@ -20,7 +20,8 @@ module Ci extend Ci::Model belongs_to :gl_project, class_name: '::Project', foreign_key: :gl_project_id - has_many :builds, dependent: :destroy, class_name: 'Ci::Build' + has_many :statuses, dependent: :destroy, class_name: 'CommitStatus' + has_many :builds, class_name: 'Ci::Build' has_many :trigger_requests, dependent: :destroy, class_name: 'Ci::TriggerRequest' validates_presence_of :sha @@ -81,12 +82,11 @@ module Ci end def stage - running_or_pending = builds_without_retry.running_or_pending - running_or_pending.limit(1).pluck(:stage).first + running_or_pending = statuses.latest.running_or_pending + running_or_pending.first.try(:stage) end def create_builds(ref, tag, user, trigger_request = nil) - return if skip_ci? && trigger_request.blank? return unless config_processor config_processor.stages.any? do |stage| CreateBuildsService.new.execute(self, stage, ref, tag, user, trigger_request).present? @@ -94,7 +94,6 @@ module Ci end def create_next_builds(ref, tag, user, trigger_request) - return if skip_ci? && trigger_request.blank? return unless config_processor stages = builds.where(ref: ref, tag: tag, trigger_request: trigger_request).group_by(&:stage) @@ -107,39 +106,47 @@ module Ci end def refs - builds.group(:ref).pluck(:ref) + statuses.pluck(:ref).compact.uniq end - def last_ref - builds.latest.first.try(:ref) - end - - def builds_without_retry - builds.latest + def statuses_for_ref(ref = nil) + if ref + statuses.for_ref(ref) + else + statuses + end end - def builds_without_retry_for_ref(ref) - builds.for_ref(ref).latest + def builds_without_retry(ref = nil) + if ref + builds.for_ref(ref).latest + else + builds.latest + end end - def retried_builds - @retried_builds ||= (builds.order(id: :desc) - builds_without_retry) + def retried + @retried ||= (statuses.order(id: :desc) - statuses.latest) end - def status - if skip_ci? - return 'skipped' - elsif yaml_errors.present? + def status(ref = nil) + if yaml_errors.present? return 'failed' - elsif builds.none? + end + + latest_statuses = statuses.latest.to_a + latest_statuses.reject! { |status| status.try(&:allow_failure?) } + latest_statuses.select! { |status| status.ref == nil || status.ref == ref } if ref + + if latest_statuses.none? return 'skipped' - elsif success? + elsif latest_statuses.all?(&:success?) 'success' - elsif pending? + elsif latest_statuses.all?(&:pending?) 'pending' - elsif running? + elsif latest_statuses.any?(&:running?) || latest_statuses.any?(&:pending?) 'running' - elsif canceled? + elsif latest_statuses.all?(&:canceled?) 'canceled' else 'failed' @@ -147,21 +154,15 @@ module Ci end def pending? - builds_without_retry.all? do |build| - build.pending? - end + status == 'pending' end def running? - builds_without_retry.any? do |build| - build.running? || build.pending? - end + status == 'running' end def success? - builds_without_retry.all? do |build| - build.success? || build.ignored? - end + status == 'success' end def failed? @@ -169,21 +170,15 @@ module Ci end def canceled? - builds_without_retry.all? do |build| - build.canceled? - end - end - - def duration - @duration ||= builds_without_retry.select(&:duration).sum(&:duration).to_i + status == 'canceled' end - def duration_for_ref(ref) - builds_without_retry_for_ref(ref).select(&:duration).sum(&:duration).to_i + def duration(ref = nil) + statuses_for_ref(ref).latest.select(&:duration).sum(&:duration).to_i end def finished_at - @finished_at ||= builds.order('finished_at DESC').first.try(:finished_at) + @finished_at ||= statuses.order('finished_at DESC').first.try(:finished_at) end def coverage @@ -195,8 +190,8 @@ module Ci end end - def matrix_for_ref?(ref) - builds_without_retry_for_ref(ref).pluck(:id).size > 1 + def matrix?(ref) + builds_without_retry(ref).pluck(:id).size > 1 end def config_processor @@ -217,7 +212,6 @@ module Ci end def skip_ci? - return false if builds.any? git_commit_message =~ /(\[ci skip\])/ if git_commit_message end diff --git a/app/models/commit.rb b/app/models/commit.rb index aff329d71fa..d5c50013525 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -184,4 +184,12 @@ class Commit def parents @parents ||= Commit.decorate(super, project) end + + def ci_commit + project.ci_commit(sha) + end + + def status + ci_commit.try(:status) || :not_found + end end diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb new file mode 100644 index 00000000000..4c6de18527b --- /dev/null +++ b/app/models/commit_status.rb @@ -0,0 +1,79 @@ +class CommitStatus < ActiveRecord::Base + self.table_name = 'ci_builds' + + belongs_to :commit, class_name: 'Ci::Commit' + belongs_to :user + + validates :commit, presence: true + validates :status, inclusion: {in: %w(pending running failed success canceled)} + + validates_presence_of :name + + scope :running, ->() { where(status: 'running') } + scope :pending, ->() { where(status: 'pending') } + scope :success, ->() { where(status: 'success') } + scope :failed, ->() { where(status: 'failed') } + scope :running_or_pending, ->() { where(status:[:running, :pending]) } + scope :latest, ->() { where(id: unscope(:select).select('max(id)').group(:name, :ref)).order(stage_idx: :asc) } + scope :for_ref, ->(ref) { where(ref: [ref, nil]) } + scope :running_or_pending, ->() { where(status: [:running, :pending]) } + + state_machine :status, initial: :pending do + event :run do + transition pending: :running + end + + event :drop do + transition running: :failed + end + + event :success do + transition [:pending, :running] => :success + end + + event :cancel do + transition [:pending, :running] => :canceled + end + + after_transition pending: :running do |build, transition| + build.update_attributes started_at: Time.now + end + + after_transition any => [:success, :failed, :canceled] do |build, transition| + build.update_attributes finished_at: Time.now + end + + state :pending, value: 'pending' + state :running, value: 'running' + state :failed, value: 'failed' + state :success, value: 'success' + state :canceled, value: 'canceled' + end + + delegate :sha, :short_sha, :gl_project, + to: :commit, prefix: false + + def before_sha + Gitlab::Git::BLANK_SHA + end + + def started? + !pending? && !canceled? && started_at + end + + def active? + running? || pending? + end + + def complete? + canceled? || success? || failed? + end + + def duration + if started_at && finished_at + finished_at - started_at + elsif started_at + Time.now - started_at + end + end +end diff --git a/app/models/generic_commit_status.rb b/app/models/generic_commit_status.rb new file mode 100644 index 00000000000..fa54e3540d0 --- /dev/null +++ b/app/models/generic_commit_status.rb @@ -0,0 +1,15 @@ +class GenericCommitStatus < CommitStatus + before_validation :set_default_values + + # GitHub compatible API + alias_attribute :context, :name + + def set_default_values + self.context ||= 'default' + self.stage ||= 'external' + end + + def tags + [:external] + end +end diff --git a/app/services/ci/create_commit_service.rb b/app/services/ci/create_commit_service.rb index fc1ae5774d5..0ae35387579 100644 --- a/app/services/ci/create_commit_service.rb +++ b/app/services/ci/create_commit_service.rb @@ -17,6 +17,8 @@ module Ci tag = origin_ref.start_with?('refs/tags/') commit = project.gl_project.ensure_ci_commit(sha) + return false if commit.skip_ci? + commit.update_committed! commit.create_builds(ref, tag, user) diff --git a/app/views/projects/builds/_build.html.haml b/app/views/projects/builds/_build.html.haml deleted file mode 100644 index 65fd9413b60..00000000000 --- a/app/views/projects/builds/_build.html.haml +++ /dev/null @@ -1,50 +0,0 @@ -- gl_project = build.project.gl_project -%tr.build - %td.status - = ci_status_with_icon(build.status) - - %td.build-link - = link_to namespace_project_build_path(gl_project.namespace, gl_project, build) do - %strong Build ##{build.id} - - - if defined?(ref) - %td - = build.ref - - %td - = build.stage - - %td - = build.name - .pull-right - - if build.tags.any? - - build.tag_list.each do |tag| - %span.label.label-primary - = tag - - if build.trigger_request - %span.label.label-info triggered - - if build.allow_failure - %span.label.label-danger allowed to fail - - %td.duration - - if build.duration - #{duration_in_words(build.finished_at, build.started_at)} - - %td.timestamp - - if build.finished_at - %span #{time_ago_in_words build.finished_at} ago - - - if build.project.coverage_enabled? - %td.coverage - - if build.coverage - #{build.coverage}% - - %td - - if defined?(controls) && current_user && can?(current_user, :manage_builds, gl_project) - .pull-right - - if build.active? - = link_to cancel_namespace_project_build_path(gl_project.namespace, gl_project, build, return_to: request.original_url), title: 'Cancel build' do - %i.fa.fa-remove.cred - - elsif build.commands.present? - = link_to retry_namespace_project_build_path(gl_project.namespace, gl_project, build, return_to: request.original_url), method: :post, title: 'Retry build' do - %i.fa.fa-repeat diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml index b561078e8c7..66e668f3771 100644 --- a/app/views/projects/builds/show.html.haml +++ b/app/views/projects/builds/show.html.haml @@ -7,9 +7,9 @@ %code #{@build.ref} #up-build-trace - - if @commit.matrix_for_ref?(@build.ref) + - if @commit.matrix?(@build.ref) %ul.center-top-menu.build-top-menu - - @commit.builds_without_retry_for_ref(@build.ref).each do |build| + - @commit.builds_without_retry(@build.ref).each do |build| %li{class: ('active' if build == @build) } = link_to namespace_project_build_path(@project.namespace, @project, build) do = ci_icon_for_status(build.status) @@ -20,7 +20,7 @@ = build.id - - unless @commit.builds_without_retry_for_ref(@build.ref).include?(@build) + - unless @commit.builds_without_retry(@build.ref).include?(@build) %li.active %a Build ##{@build.id} diff --git a/app/views/projects/commit/ci.html.haml b/app/views/projects/commit/ci.html.haml index 26ab38445c2..7f106631cac 100644 --- a/app/views/projects/commit/ci.html.haml +++ b/app/views/projects/commit/ci.html.haml @@ -20,13 +20,35 @@ .bs-callout.bs-callout-warning \.gitlab-ci.yml not found in this commit -- @ci_commit.refs.each do |ref| +- if @ci_commit.refs.blank? + .gray-content-block.second-block + Latest builds + - if @ci_commit.duration > 0 + %small.pull-right + %i.fa.fa-time + #{time_interval_in_words @ci_commit.duration} + + %table.table.builds + %thead + %tr + %th Status + %th Build ID + %th Stage + %th Name + %th Duration + %th Finished at + - if @ci_project && @ci_project.coverage_enabled? + %th Coverage + %th + = render partial: "projects/commit_statuses/commit_status", collection: @ci_commit.statuses.latest, coverage: @ci_project.try(:coverage_enabled?), controls: true + +- @ci_commit.refs.sort.each do |ref| .gray-content-block.second-block Builds for #{ref} - - if @ci_commit.duration_for_ref(ref) > 0 + - if @ci_commit.duration(ref) > 0 %small.pull-right %i.fa.fa-time - #{time_interval_in_words @ci_commit.duration_for_ref(ref)} + #{time_interval_in_words @ci_commit.duration(ref)} %table.table.builds %thead @@ -40,10 +62,10 @@ - if @ci_project && @ci_project.coverage_enabled? %th Coverage %th - = render partial: "projects/builds/build", collection: @ci_commit.builds_without_retry.for_ref(ref), controls: true + = render partial: "projects/commit_statuses/commit_status", collection: @ci_commit.statuses.for_ref(ref).latest, coverage: @ci_project.try(:coverage_enabled?), controls: true -- if @ci_commit.retried_builds.any? - %h3 +- if @ci_commit.retried.any? + .gray-content-block.second-block Retried builds %table.table.builds @@ -59,4 +81,4 @@ - if @ci_project && @ci_project.coverage_enabled? %th Coverage %th - = render partial: "projects/builds/build", collection: @ci_commit.retried_builds, ref: true + = render partial: "projects/commit_statuses/commit_status", collection: @ci_commit.retried, coverage: @ci_project.try(:coverage_enabled?), ref: true diff --git a/app/views/projects/commit_statuses/_commit_status.html.haml b/app/views/projects/commit_statuses/_commit_status.html.haml new file mode 100644 index 00000000000..f79929c70bf --- /dev/null +++ b/app/views/projects/commit_statuses/_commit_status.html.haml @@ -0,0 +1,52 @@ +%tr.commit_status + %td.status + = ci_status_with_icon(commit_status.status) + + %td.commit_status-link + - if commit_status.target_url + = link_to commit_status.target_url do + %strong Build ##{commit_status.id} + - else + %strong Build ##{commit_status.id} + + - if defined?(ref) + %td + = commit_status.ref + + %td + = commit_status.stage + + %td + = commit_status.description + .pull-right + - if commit_status.tags.any? + - commit_status.tags.each do |tag| + %span.label.label-primary + = tag + - if commit_status.try(:trigger_request) + %span.label.label-info triggered + - if commit_status.try(:allow_failure) + %span.label.label-danger allowed to fail + + %td.duration + - if commit_status.duration + #{duration_in_words(commit_status.finished_at, commit_status.started_at)} + + %td.timestamp + - if commit_status.finished_at + %span #{time_ago_in_words commit_status.finished_at} ago + + - if defined?(coverage) + %td.coverage + - if commit_status.try(:coverage) + #{commit_status.coverage}% + + %td + - if defined?(controls) && current_user && can?(current_user, :manage_builds, gl_project) + .pull-right + - if commit_status.active? + = link_to cancel_namespace_project_build_path(gl_project.namespace, gl_project, commit_status, return_to: request.original_url), title: 'Cancel commit_status' do + %i.fa.fa-remove.cred + - elsif commit_status.commands.present? + = link_to retry_namespace_project_build_path(gl_project.namespace, gl_project, commit_status, return_to: request.original_url), method: :post, title: 'Retry commit_status' do + %i.fa.fa-repeat diff --git a/db/migrate/20151008123042_add_type_and_description_to_builds.rb b/db/migrate/20151008123042_add_type_and_description_to_builds.rb new file mode 100644 index 00000000000..c72b1c611c6 --- /dev/null +++ b/db/migrate/20151008123042_add_type_and_description_to_builds.rb @@ -0,0 +1,9 @@ +class AddTypeAndDescriptionToBuilds < ActiveRecord::Migration + def change + add_column :ci_builds, :type, :string + add_column :ci_builds, :target_url, :string + add_column :ci_builds, :description, :string + add_index :ci_builds, [:commit_id, :type, :ref] + add_index :ci_builds, [:commit_id, :type, :name, :ref] + end +end diff --git a/db/migrate/20151008130321_migrate_name_to_description_for_builds.rb b/db/migrate/20151008130321_migrate_name_to_description_for_builds.rb new file mode 100644 index 00000000000..f5c44babd84 --- /dev/null +++ b/db/migrate/20151008130321_migrate_name_to_description_for_builds.rb @@ -0,0 +1,5 @@ +class MigrateNameToDescriptionForBuilds < ActiveRecord::Migration + def change + execute("UPDATE ci_builds SET type='Ci::Build' WHERE type IS NULL") + end +end diff --git a/db/schema.rb b/db/schema.rb index c5c462c2e57..7a11dfca034 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20151007120511) do +ActiveRecord::Schema.define(version: 20151008130321) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -103,9 +103,14 @@ ActiveRecord::Schema.define(version: 20151007120511) do t.boolean "tag" t.string "ref" t.integer "user_id" + t.string "type" + t.string "target_url" + t.string "description" end add_index "ci_builds", ["commit_id", "stage_idx", "created_at"], name: "index_ci_builds_on_commit_id_and_stage_idx_and_created_at", using: :btree + add_index "ci_builds", ["commit_id", "type", "name", "ref"], name: "index_ci_builds_on_commit_id_and_type_and_name_and_ref", using: :btree + add_index "ci_builds", ["commit_id", "type", "ref"], name: "index_ci_builds_on_commit_id_and_type_and_ref", using: :btree add_index "ci_builds", ["commit_id"], name: "index_ci_builds_on_commit_id", using: :btree add_index "ci_builds", ["project_id", "commit_id"], name: "index_ci_builds_on_project_id_and_commit_id", using: :btree add_index "ci_builds", ["project_id"], name: "index_ci_builds_on_project_id", using: :btree diff --git a/doc/api/commits.md b/doc/api/commits.md index eb8d6a43592..b22d040bf0d 100644 --- a/doc/api/commits.md +++ b/doc/api/commits.md @@ -62,7 +62,8 @@ Parameters: "authored_date": "2012-09-20T09:06:12+03:00", "parent_ids": [ "ae1d9fb46aa2b07ee9836d49862ec4e2c46fbbba" - ] + ], + "status": "running" } ``` diff --git a/lib/api/api.rb b/lib/api/api.rb index c09488d3547..afc0402f9e1 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -46,6 +46,7 @@ module API mount Services mount Files mount Commits + mount CommitStatus mount Namespaces mount Branches mount Labels diff --git a/lib/api/commit_statuses.rb b/lib/api/commit_statuses.rb new file mode 100644 index 00000000000..cfe8739b175 --- /dev/null +++ b/lib/api/commit_statuses.rb @@ -0,0 +1,79 @@ +require 'mime/types' + +module API + # Project commit statuses API + class CommitStatus < Grape::API + resource :projects do + before { authenticate! } + before { authorize! :read_commit_statuses, user_project } + + # Get a commit's statuses + # + # Parameters: + # id (required) - The ID of a project + # sha (required) - The commit hash + # ref (optional) - The ref + # stage (optional) - The stage + # name (optional) - The name + # all (optional) - Show all statuses, default: false + # Examples: + # GET /projects/:id/repository/commits/:sha/statuses + get ':id/repository/commits/:sha/statuses' do + sha = params[:sha] + ci_commit = user_project.ci_commit(sha) + not_found! 'Commit' unless ci_commit + statuses = ci_commit.statuses + statuses = statuses.latest unless parse_boolean(params[:all]) + statuses = statuses.where(ref: params[:ref]) if params[:ref].present? + statuses = statuses.where(name: params[:stage]) if params[:stage].present? + statuses = statuses.where(name: params[:name]) if params[:name].present? + present paginate(statuses), with: Entities::CommitStatus + end + + # Post status to commit + # + # Parameters: + # id (required) - The ID of a project + # sha (required) - The commit hash + # ref (optional) - The ref + # state (required) - The state of the status. Can be: pending, running, success, error or failure + # target_url (optional) - The target URL to associate with this status + # description (optional) - A short description of the status + # name or context (optional) - A string label to differentiate this status from the status of other systems. Default: "default" + # Examples: + # POST /projects/:id/repository/commits/:sha/status + post ':id/statuses/:sha' do + required_attributes! [:state] + attrs = attributes_for_keys [:ref, :target_url, :description, :context, :name] + commit = @project.commit(params[:sha]) + not_found! 'Commit' unless commit + + ci_commit = @project.ensure_ci_commit(commit.sha) + + name = params[:name] || params[:context] + status = GenericCommitStatus.running_or_pending.find_by(commit: ci_commit, name: name, ref: params[:ref]) + status = GenericCommitStatus.new(commit: ci_commit) unless status + status.update(attrs) + + case params[:state].to_s + when 'running' + status.run + when 'success' + status.success + when 'failed' + status.drop + when 'canceled' + status.cancel + else + status.status = params[:state].to_s + end + + if status.save + present status, with: Entities::CommitStatus + else + render_validation_error!(status) + end + end + end + end +end diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 9620d36ac41..e1c5a459751 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -65,7 +65,7 @@ module API expose :issues_enabled, :merge_requests_enabled, :wiki_enabled, :snippets_enabled, :created_at, :last_activity_at expose :creator_id expose :namespace - expose :forked_from_project, using: Entities::ForkedFromProject, if: lambda{ | project, options | project.forked? } + expose :forked_from_project, using: Entities::ForkedFromProject, if: lambda { |project, options| project.forked? } expose :avatar_url expose :star_count, :forks_count end @@ -149,6 +149,7 @@ module API class RepoCommitDetail < RepoCommit expose :parent_ids, :committed_date, :authored_date + expose :status end class ProjectSnippet < Grape::Entity @@ -228,6 +229,11 @@ module API expose :created_at end + class CommitStatus < Grape::Entity + expose :id, :sha, :ref, :status, :name, :target_url, :description, + :created_at, :started_at, :finished_at + end + class Event < Grape::Entity expose :title, :project_id, :action_name expose :target_id, :target_type, :author_id diff --git a/lib/ci/api/entities.rb b/lib/ci/api/entities.rb index f47bc1236b8..b80c0b8b273 100644 --- a/lib/ci/api/entities.rb +++ b/lib/ci/api/entities.rb @@ -2,7 +2,7 @@ module Ci module API module Entities class Commit < Grape::Entity - expose :id, :ref, :sha, :project_id, :before_sha, :created_at + expose :id, :sha, :project_id, :created_at expose :status, :finished_at, :duration expose :git_commit_message, :git_author_name, :git_author_email end @@ -12,7 +12,7 @@ module Ci end class Build < Grape::Entity - expose :id, :commands, :ref, :sha, :project_id, :repo_url, + expose :id, :commands, :ref, :sha, :status, :project_id, :repo_url, :before_sha, :allow_git_fetch, :project_name expose :options do |model| diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb index 21b582afba4..2fcd70182b9 100644 --- a/spec/factories/ci/builds.rb +++ b/spec/factories/ci/builds.rb @@ -27,6 +27,7 @@ FactoryGirl.define do factory :ci_build, class: Ci::Build do + name 'test' ref 'master' tag false started_at 'Di 29. Okt 09:51:28 CET 2013' diff --git a/spec/factories/commit_statuses.rb b/spec/factories/commit_statuses.rb new file mode 100644 index 00000000000..52de437052d --- /dev/null +++ b/spec/factories/commit_statuses.rb @@ -0,0 +1,15 @@ +FactoryGirl.define do + factory :commit_status, class: CommitStatus do + started_at 'Di 29. Okt 09:51:28 CET 2013' + finished_at 'Di 29. Okt 09:53:28 CET 2013' + name 'default' + status 'success' + description 'commit status' + commit factory: :ci_commit + + factory :generic_commit_status, class: GenericCommitStatus do + name 'generic' + description 'external commit status' + end + end +end diff --git a/spec/features/commits_spec.rb b/spec/features/commits_spec.rb index 5da220859e3..cbb6360069b 100644 --- a/spec/features/commits_spec.rb +++ b/spec/features/commits_spec.rb @@ -12,6 +12,7 @@ describe "Commits" do @ci_project = project.ensure_gitlab_ci_project @commit = FactoryGirl.create :ci_commit, gl_project: project, sha: project.commit.sha @build = FactoryGirl.create :ci_build, commit: @commit + @generic_status = FactoryGirl.create :generic_commit_status, commit: @commit end before do diff --git a/spec/models/build_spec.rb b/spec/models/build_spec.rb new file mode 100644 index 00000000000..d875015b991 --- /dev/null +++ b/spec/models/build_spec.rb @@ -0,0 +1,276 @@ +# == Schema Information +# +# Table name: builds +# +# id :integer not null, primary key +# project_id :integer +# status :string(255) +# finished_at :datetime +# trace :text +# created_at :datetime +# updated_at :datetime +# started_at :datetime +# runner_id :integer +# commit_id :integer +# coverage :float +# commands :text +# job_id :integer +# name :string(255) +# deploy :boolean default(FALSE) +# options :text +# allow_failure :boolean default(FALSE), not null +# stage :string(255) +# trigger_request_id :integer +# + +require 'spec_helper' + +describe Ci::Build do + let(:project) { FactoryGirl.create :ci_project } + let(:gl_project) { FactoryGirl.create :empty_project, gitlab_ci_project: project } + let(:commit) { FactoryGirl.create :ci_commit, gl_project: gl_project } + let(:build) { FactoryGirl.create :ci_build, commit: commit } + + it { is_expected.to validate_presence_of :ref } + + it { is_expected.to respond_to :trace_html } + + describe :first_pending do + let(:first) { FactoryGirl.create :ci_build, commit: commit, status: 'pending', created_at: Date.yesterday } + let(:second) { FactoryGirl.create :ci_build, commit: commit, status: 'pending' } + before { first; second } + subject { Ci::Build.first_pending } + + it { is_expected.to be_a(Ci::Build) } + it('returns with the first pending build') { is_expected.to eq(first) } + end + + describe :create_from do + before do + build.status = 'success' + build.save + end + let(:create_from_build) { Ci::Build.create_from build } + + it 'there should be a pending task' do + expect(Ci::Build.pending.count(:all)).to eq 0 + create_from_build + expect(Ci::Build.pending.count(:all)).to be > 0 + end + end + + describe :ignored? do + subject { build.ignored? } + + context 'if build is not allowed to fail' do + before { build.allow_failure = false } + + context 'and build.status is success' do + before { build.status = 'success' } + + it { is_expected.to be_falsey } + end + + context 'and build.status is failed' do + before { build.status = 'failed' } + + it { is_expected.to be_falsey } + end + end + + context 'if build is allowed to fail' do + before { build.allow_failure = true } + + context 'and build.status is success' do + before { build.status = 'success' } + + it { is_expected.to be_falsey } + end + + context 'and build.status is failed' do + before { build.status = 'failed' } + + it { is_expected.to be_truthy } + end + end + end + + describe :trace do + subject { build.trace_html } + + it { is_expected.to be_empty } + + context 'if build.trace contains text' do + let(:text) { 'example output' } + before { build.trace = text } + + it { is_expected.to include(text) } + it { expect(subject.length).to be >= text.length } + end + + context 'if build.trace hides token' do + let(:token) { 'my_secret_token' } + + before do + build.project.update_attributes(token: token) + build.update_attributes(trace: token) + end + + it { is_expected.to_not include(token) } + end + end + + describe :timeout do + subject { build.timeout } + + it { is_expected.to eq(commit.project.timeout) } + end + + describe :options do + let(:options) do + { + image: "ruby:2.1", + services: [ + "postgres" + ] + } + end + + subject { build.options } + it { is_expected.to eq(options) } + end + + describe :allow_git_fetch do + subject { build.allow_git_fetch } + + it { is_expected.to eq(project.allow_git_fetch) } + end + + describe :project do + subject { build.project } + + it { is_expected.to eq(commit.project) } + end + + describe :project_id do + subject { build.project_id } + + it { is_expected.to eq(commit.project_id) } + end + + describe :project_name do + subject { build.project_name } + + it { is_expected.to eq(project.name) } + end + + describe :repo_url do + subject { build.repo_url } + + it { is_expected.to eq(project.repo_url_with_auth) } + end + + describe :extract_coverage do + context 'valid content & regex' do + subject { build.extract_coverage('Coverage 1033 / 1051 LOC (98.29%) covered', '\(\d+.\d+\%\) covered') } + + it { is_expected.to eq(98.29) } + end + + context 'valid content & bad regex' do + subject { build.extract_coverage('Coverage 1033 / 1051 LOC (98.29%) covered', 'very covered') } + + it { is_expected.to be_nil } + end + + context 'no coverage content & regex' do + subject { build.extract_coverage('No coverage for today :sad:', '\(\d+.\d+\%\) covered') } + + it { is_expected.to be_nil } + end + + context 'multiple results in content & regex' do + subject { build.extract_coverage(' (98.39%) covered. (98.29%) covered', '\(\d+.\d+\%\) covered') } + + it { is_expected.to eq(98.29) } + end + end + + describe :variables do + context 'returns variables' do + subject { build.variables } + + let(:variables) do + [ + { key: :DB_NAME, value: 'postgres', public: true } + ] + end + + it { is_expected.to eq(variables) } + + context 'and secure variables' do + let(:secure_variables) do + [ + { key: 'SECRET_KEY', value: 'secret_value', public: false } + ] + end + + before do + build.project.variables << Ci::Variable.new(key: 'SECRET_KEY', value: 'secret_value') + end + + it { is_expected.to eq(variables + secure_variables) } + + context 'and trigger variables' do + let(:trigger) { FactoryGirl.create :ci_trigger, project: project } + let(:trigger_request) { FactoryGirl.create :ci_trigger_request_with_variables, commit: commit, trigger: trigger } + let(:trigger_variables) do + [ + { key: :TRIGGER_KEY, value: 'TRIGGER_VALUE', public: false } + ] + end + + before do + build.trigger_request = trigger_request + end + + it { is_expected.to eq(variables + secure_variables + trigger_variables) } + end + end + end + end + + describe :project_recipients do + let(:pusher_email) { 'pusher@gitlab.test' } + let(:user) { User.new(notification_email: pusher_email) } + subject { build.project_recipients } + + before do + build.update_attributes(user: user) + end + + it 'should return pusher_email as only recipient when no additional recipients are given' do + project.update_attributes(email_add_pusher: true, + email_recipients: '') + is_expected.to eq([pusher_email]) + end + + it 'should return pusher_email and additional recipients' do + project.update_attributes(email_add_pusher: true, + email_recipients: 'rec1 rec2') + is_expected.to eq(['rec1', 'rec2', pusher_email]) + end + + it 'should return recipients' do + project.update_attributes(email_add_pusher: false, + email_recipients: 'rec1 rec2') + is_expected.to eq(['rec1', 'rec2']) + end + + it 'should return unique recipients only' do + project.update_attributes(email_add_pusher: true, + email_recipients: "rec1 rec1 #{pusher_email}") + is_expected.to eq(['rec1', pusher_email]) + end + end +end diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb deleted file mode 100644 index da56f6e31ae..00000000000 --- a/spec/models/ci/build_spec.rb +++ /dev/null @@ -1,387 +0,0 @@ -# == Schema Information -# -# Table name: builds -# -# id :integer not null, primary key -# project_id :integer -# status :string(255) -# finished_at :datetime -# trace :text -# created_at :datetime -# updated_at :datetime -# started_at :datetime -# runner_id :integer -# commit_id :integer -# coverage :float -# commands :text -# job_id :integer -# name :string(255) -# deploy :boolean default(FALSE) -# options :text -# allow_failure :boolean default(FALSE), not null -# stage :string(255) -# trigger_request_id :integer -# - -require 'spec_helper' - -describe Ci::Build do - let(:project) { FactoryGirl.create :ci_project } - let(:gl_project) { FactoryGirl.create :empty_project, gitlab_ci_project: project } - let(:commit) { FactoryGirl.create :ci_commit, gl_project: gl_project } - let(:build) { FactoryGirl.create :ci_build, commit: commit } - subject { build } - - it { is_expected.to belong_to(:commit) } - it { is_expected.to belong_to(:user) } - it { is_expected.to validate_presence_of :status } - it { is_expected.to validate_presence_of :ref } - - it { is_expected.to respond_to :success? } - it { is_expected.to respond_to :failed? } - it { is_expected.to respond_to :running? } - it { is_expected.to respond_to :pending? } - it { is_expected.to respond_to :trace_html } - - describe :first_pending do - let(:first) { FactoryGirl.create :ci_build, commit: commit, status: 'pending', created_at: Date.yesterday } - let(:second) { FactoryGirl.create :ci_build, commit: commit, status: 'pending' } - before { first; second } - subject { Ci::Build.first_pending } - - it { is_expected.to be_a(Ci::Build) } - it('returns with the first pending build') { is_expected.to eq(first) } - end - - describe :create_from do - before do - build.status = 'success' - build.save - end - let(:create_from_build) { Ci::Build.create_from build } - - it 'there should be a pending task' do - expect(Ci::Build.pending.count(:all)).to eq 0 - create_from_build - expect(Ci::Build.pending.count(:all)).to be > 0 - end - end - - describe :started? do - subject { build.started? } - - context 'without started_at' do - before { build.started_at = nil } - - it { is_expected.to be_falsey } - end - - %w(running success failed).each do |status| - context "if build status is #{status}" do - before { build.status = status } - - it { is_expected.to be_truthy } - end - end - - %w(pending canceled).each do |status| - context "if build status is #{status}" do - before { build.status = status } - - it { is_expected.to be_falsey } - end - end - end - - describe :active? do - subject { build.active? } - - %w(pending running).each do |state| - context "if build.status is #{state}" do - before { build.status = state } - - it { is_expected.to be_truthy } - end - end - - %w(success failed canceled).each do |state| - context "if build.status is #{state}" do - before { build.status = state } - - it { is_expected.to be_falsey } - end - end - end - - describe :complete? do - subject { build.complete? } - - %w(success failed canceled).each do |state| - context "if build.status is #{state}" do - before { build.status = state } - - it { is_expected.to be_truthy } - end - end - - %w(pending running).each do |state| - context "if build.status is #{state}" do - before { build.status = state } - - it { is_expected.to be_falsey } - end - end - end - - describe :ignored? do - subject { build.ignored? } - - context 'if build is not allowed to fail' do - before { build.allow_failure = false } - - context 'and build.status is success' do - before { build.status = 'success' } - - it { is_expected.to be_falsey } - end - - context 'and build.status is failed' do - before { build.status = 'failed' } - - it { is_expected.to be_falsey } - end - end - - context 'if build is allowed to fail' do - before { build.allow_failure = true } - - context 'and build.status is success' do - before { build.status = 'success' } - - it { is_expected.to be_falsey } - end - - context 'and build.status is failed' do - before { build.status = 'failed' } - - it { is_expected.to be_truthy } - end - end - end - - describe :trace do - subject { build.trace_html } - - it { is_expected.to be_empty } - - context 'if build.trace contains text' do - let(:text) { 'example output' } - before { build.trace = text } - - it { is_expected.to include(text) } - it { expect(subject.length).to be >= text.length } - end - - context 'if build.trace hides token' do - let(:token) { 'my_secret_token' } - - before do - build.project.update_attributes(token: token) - build.update_attributes(trace: token) - end - - it { is_expected.to_not include(token) } - end - end - - describe :timeout do - subject { build.timeout } - - it { is_expected.to eq(commit.project.timeout) } - end - - describe :duration do - subject { build.duration } - - it { is_expected.to eq(120.0) } - - context 'if the building process has not started yet' do - before do - build.started_at = nil - build.finished_at = nil - end - - it { is_expected.to be_nil } - end - - context 'if the building process has started' do - before do - build.started_at = Time.now - 1.minute - build.finished_at = nil - end - - it { is_expected.to be_a(Float) } - it { is_expected.to be > 0.0 } - end - end - - describe :options do - let(:options) do - { - image: "ruby:2.1", - services: [ - "postgres" - ] - } - end - - subject { build.options } - it { is_expected.to eq(options) } - end - - describe :sha do - subject { build.sha } - - it { is_expected.to eq(commit.sha) } - end - - describe :short_sha do - subject { build.short_sha } - - it { is_expected.to eq(commit.short_sha) } - end - - describe :allow_git_fetch do - subject { build.allow_git_fetch } - - it { is_expected.to eq(project.allow_git_fetch) } - end - - describe :project do - subject { build.project } - - it { is_expected.to eq(commit.project) } - end - - describe :project_id do - subject { build.project_id } - - it { is_expected.to eq(commit.project_id) } - end - - describe :project_name do - subject { build.project_name } - - it { is_expected.to eq(project.name) } - end - - describe :repo_url do - subject { build.repo_url } - - it { is_expected.to eq(project.repo_url_with_auth) } - end - - describe :extract_coverage do - context 'valid content & regex' do - subject { build.extract_coverage('Coverage 1033 / 1051 LOC (98.29%) covered', '\(\d+.\d+\%\) covered') } - - it { is_expected.to eq(98.29) } - end - - context 'valid content & bad regex' do - subject { build.extract_coverage('Coverage 1033 / 1051 LOC (98.29%) covered', 'very covered') } - - it { is_expected.to be_nil } - end - - context 'no coverage content & regex' do - subject { build.extract_coverage('No coverage for today :sad:', '\(\d+.\d+\%\) covered') } - - it { is_expected.to be_nil } - end - - context 'multiple results in content & regex' do - subject { build.extract_coverage(' (98.39%) covered. (98.29%) covered', '\(\d+.\d+\%\) covered') } - - it { is_expected.to eq(98.29) } - end - end - - describe :variables do - context 'returns variables' do - subject { build.variables } - - let(:variables) do - [ - { key: :DB_NAME, value: 'postgres', public: true } - ] - end - - it { is_expected.to eq(variables) } - - context 'and secure variables' do - let(:secure_variables) do - [ - { key: 'SECRET_KEY', value: 'secret_value', public: false } - ] - end - - before do - build.project.variables << Ci::Variable.new(key: 'SECRET_KEY', value: 'secret_value') - end - - it { is_expected.to eq(variables + secure_variables) } - - context 'and trigger variables' do - let(:trigger) { FactoryGirl.create :ci_trigger, project: project } - let(:trigger_request) { FactoryGirl.create :ci_trigger_request_with_variables, commit: commit, trigger: trigger } - let(:trigger_variables) do - [ - { key: :TRIGGER_KEY, value: 'TRIGGER_VALUE', public: false } - ] - end - - before do - build.trigger_request = trigger_request - end - - it { is_expected.to eq(variables + secure_variables + trigger_variables) } - end - end - end - end - - describe :project_recipients do - let(:pusher_email) { 'pusher@gitlab.test' } - let(:user) { User.new(notification_email: pusher_email) } - subject { build.project_recipients } - - before do - build.update_attributes(user: user) - end - - it 'should return pusher_email as only recipient when no additional recipients are given' do - project.update_attributes(email_add_pusher: true, - email_recipients: '') - is_expected.to eq([pusher_email]) - end - - it 'should return pusher_email and additional recipients' do - project.update_attributes(email_add_pusher: true, - email_recipients: 'rec1 rec2') - is_expected.to eq(['rec1', 'rec2', pusher_email]) - end - - it 'should return recipients' do - project.update_attributes(email_add_pusher: false, - email_recipients: 'rec1 rec2') - is_expected.to eq(['rec1', 'rec2']) - end - - it 'should return unique recipients only' do - project.update_attributes(email_add_pusher: true, - email_recipients: "rec1 rec1 #{pusher_email}") - is_expected.to eq(['rec1', pusher_email]) - end - end -end diff --git a/spec/models/ci/commit_spec.rb b/spec/models/ci/commit_spec.rb index acff1ddf0fc..371add4ee59 100644 --- a/spec/models/ci/commit_spec.rb +++ b/spec/models/ci/commit_spec.rb @@ -23,6 +23,8 @@ describe Ci::Commit do let(:commit) { FactoryGirl.create :ci_commit, gl_project: gl_project } it { is_expected.to belong_to(:gl_project) } + it { is_expected.to have_many(:statuses) } + it { is_expected.to have_many(:trigger_requests) } it { is_expected.to have_many(:builds) } it { is_expected.to validate_presence_of :sha } @@ -47,10 +49,12 @@ describe Ci::Commit do @second = FactoryGirl.create :ci_build, commit: commit end - it "creates new build" do + it "creates only a new build" do expect(commit.builds.count(:all)).to eq 2 + expect(commit.statuses.count(:all)).to eq 2 commit.retry expect(commit.builds.count(:all)).to eq 3 + expect(commit.statuses.count(:all)).to eq 3 end end @@ -78,8 +82,8 @@ describe Ci::Commit do subject { commit.stage } before do - @second = FactoryGirl.create :ci_build, commit: commit, name: 'deploy', stage: 'deploy', stage_idx: 1, status: :pending - @first = FactoryGirl.create :ci_build, commit: commit, name: 'test', stage: 'test', stage_idx: 0, status: :pending + @second = FactoryGirl.create :commit_status, commit: commit, name: 'deploy', stage: 'deploy', stage_idx: 1, status: 'pending' + @first = FactoryGirl.create :commit_status, commit: commit, name: 'test', stage: 'test', stage_idx: 0, status: 'pending' end it 'returns first running stage' do @@ -88,7 +92,7 @@ describe Ci::Commit do context 'first build succeeded' do before do - @first.update_attributes(status: :success) + @first.success end it 'returns last running stage' do @@ -98,8 +102,8 @@ describe Ci::Commit do context 'all builds succeeded' do before do - @first.update_attributes(status: :success) - @second.update_attributes(status: :success) + @first.success + @second.success end it 'returns nil' do @@ -111,6 +115,33 @@ describe Ci::Commit do describe :create_next_builds do end + describe :refs do + subject { commit.refs } + + before do + FactoryGirl.create :commit_status, commit: commit, name: 'deploy' + FactoryGirl.create :commit_status, commit: commit, name: 'deploy', ref: 'develop' + FactoryGirl.create :commit_status, commit: commit, name: 'deploy', ref: 'master' + end + + it 'returns all refs' do + is_expected.to contain_exactly('master', 'develop') + end + end + + describe :retried do + subject { commit.retried } + + before do + @commit1 = FactoryGirl.create :ci_build, commit: commit, name: 'deploy' + @commit2 = FactoryGirl.create :ci_build, commit: commit, name: 'deploy' + end + + it 'returns old builds' do + is_expected.to contain_exactly(@commit1) + end + end + describe :create_builds do let(:commit) { FactoryGirl.create :ci_commit, gl_project: gl_project } @@ -252,10 +283,10 @@ describe Ci::Commit do describe :should_create_next_builds? do before do - @build1 = FactoryGirl.create :ci_build, commit: commit, name: 'build1', ref: 'master', tag: false, status: :success - @build2 = FactoryGirl.create :ci_build, commit: commit, name: 'build1', ref: 'develop', tag: false, status: :failed - @build3 = FactoryGirl.create :ci_build, commit: commit, name: 'build1', ref: 'master', tag: true, status: :failed - @build4 = FactoryGirl.create :ci_build, commit: commit, name: 'build4', ref: 'master', tag: false, status: :success + @build1 = FactoryGirl.create :ci_build, commit: commit, name: 'build1', ref: 'master', tag: false, status: 'success' + @build2 = FactoryGirl.create :ci_build, commit: commit, name: 'build1', ref: 'develop', tag: false, status: 'failed' + @build3 = FactoryGirl.create :ci_build, commit: commit, name: 'build1', ref: 'master', tag: true, status: 'failed' + @build4 = FactoryGirl.create :ci_build, commit: commit, name: 'build4', ref: 'master', tag: false, status: 'success' end context 'for success' do @@ -266,7 +297,7 @@ describe Ci::Commit do context 'for failed' do before do - @build4.update_attributes(status: :failed) + @build4.update_attributes(status: 'failed') end it 'to not create' do @@ -286,7 +317,7 @@ describe Ci::Commit do context 'for running' do before do - @build4.update_attributes(status: :running) + @build4.update_attributes(status: 'running') end it 'to not create' do @@ -296,7 +327,7 @@ describe Ci::Commit do context 'for retried' do before do - @build5 = FactoryGirl.create :ci_build, commit: commit, name: 'build4', ref: 'master', tag: false, status: :failed + @build5 = FactoryGirl.create :ci_build, commit: commit, name: 'build4', ref: 'master', tag: false, status: 'failed' end it 'to not create' do diff --git a/spec/models/ci/project_services/mail_service_spec.rb b/spec/models/ci/project_services/mail_service_spec.rb index 04e870dce7f..2ce5c2b4707 100644 --- a/spec/models/ci/project_services/mail_service_spec.rb +++ b/spec/models/ci/project_services/mail_service_spec.rb @@ -58,7 +58,7 @@ describe Ci::MailService do let(:project) { FactoryGirl.create(:ci_project, email_add_pusher: true, email_only_broken_builds: false) } let(:gl_project) { FactoryGirl.create(:empty_project, gitlab_ci_project: project) } let(:commit) { FactoryGirl.create(:ci_commit, gl_project: gl_project) } - let(:build) { FactoryGirl.create(:ci_build, status: :success, commit: commit, user: user) } + let(:build) { FactoryGirl.create(:ci_build, status: 'success', commit: commit, user: user) } before do allow(mail).to receive_messages( @@ -86,7 +86,7 @@ describe Ci::MailService do end let(:gl_project) { FactoryGirl.create(:empty_project, gitlab_ci_project: project) } let(:commit) { FactoryGirl.create(:ci_commit, gl_project: gl_project) } - let(:build) { FactoryGirl.create(:ci_build, status: :success, commit: commit, user: user) } + let(:build) { FactoryGirl.create(:ci_build, status: 'success', commit: commit, user: user) } before do allow(mail).to receive_messages( @@ -115,7 +115,7 @@ describe Ci::MailService do end let(:gl_project) { FactoryGirl.create(:empty_project, gitlab_ci_project: project) } let(:commit) { FactoryGirl.create(:ci_commit, gl_project: gl_project) } - let(:build) { FactoryGirl.create(:ci_build, status: :success, commit: commit, user: user) } + let(:build) { FactoryGirl.create(:ci_build, status: 'success', commit: commit, user: user) } before do allow(mail).to receive_messages( @@ -144,7 +144,7 @@ describe Ci::MailService do end let(:gl_project) { FactoryGirl.create(:empty_project, gitlab_ci_project: project) } let(:commit) { FactoryGirl.create(:ci_commit, gl_project: gl_project) } - let(:build) { FactoryGirl.create(:ci_build, status: :success, commit: commit, user: user) } + let(:build) { FactoryGirl.create(:ci_build, status: 'success', commit: commit, user: user) } before do allow(mail).to receive_messages( diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb new file mode 100644 index 00000000000..c1af50afb7c --- /dev/null +++ b/spec/models/commit_status_spec.rb @@ -0,0 +1,157 @@ +require 'spec_helper' + +describe CommitStatus do + let(:commit) { FactoryGirl.create :ci_commit } + let(:commit_status) { FactoryGirl.create :commit_status, commit: commit } + + it { is_expected.to belong_to(:commit) } + it { is_expected.to belong_to(:user) } + it { is_expected.to validate_presence_of(:name) } + it { is_expected.to validate_inclusion_of(:status).in_array(%w(pending running failed success canceled)) } + + it { is_expected.to delegate_method(:sha).to(:commit) } + it { is_expected.to delegate_method(:short_sha).to(:commit) } + it { is_expected.to delegate_method(:gl_project).to(:commit) } + + it { is_expected.to respond_to :success? } + it { is_expected.to respond_to :failed? } + it { is_expected.to respond_to :running? } + it { is_expected.to respond_to :pending? } + + describe :started? do + subject { commit_status.started? } + + context 'without started_at' do + before { commit_status.started_at = nil } + + it { is_expected.to be_falsey } + end + + %w(running success failed).each do |status| + context "if commit status is #{status}" do + before { commit_status.status = status } + + it { is_expected.to be_truthy } + end + end + + %w(pending canceled).each do |status| + context "if commit status is #{status}" do + before { commit_status.status = status } + + it { is_expected.to be_falsey } + end + end + end + + describe :active? do + subject { commit_status.active? } + + %w(pending running).each do |state| + context "if commit_status.status is #{state}" do + before { commit_status.status = state } + + it { is_expected.to be_truthy } + end + end + + %w(success failed canceled).each do |state| + context "if commit_status.status is #{state}" do + before { commit_status.status = state } + + it { is_expected.to be_falsey } + end + end + end + + describe :complete? do + subject { commit_status.complete? } + + %w(success failed canceled).each do |state| + context "if commit_status.status is #{state}" do + before { commit_status.status = state } + + it { is_expected.to be_truthy } + end + end + + %w(pending running).each do |state| + context "if commit_status.status is #{state}" do + before { commit_status.status = state } + + it { is_expected.to be_falsey } + end + end + end + + describe :duration do + subject { commit_status.duration } + + it { is_expected.to eq(120.0) } + + context 'if the building process has not started yet' do + before do + commit_status.started_at = nil + commit_status.finished_at = nil + end + + it { is_expected.to be_nil } + end + + context 'if the building process has started' do + before do + commit_status.started_at = Time.now - 1.minute + commit_status.finished_at = nil + end + + it { is_expected.to be_a(Float) } + it { is_expected.to be > 0.0 } + end + end + + describe :latest do + subject { CommitStatus.latest.order(:id) } + + before do + @commit1 = FactoryGirl.create :commit_status, commit: commit, name: 'aa', ref: 'bb', status: 'running' + @commit2 = FactoryGirl.create :commit_status, commit: commit, name: 'cc', ref: 'cc', status: 'pending' + @commit3 = FactoryGirl.create :commit_status, commit: commit, name: 'aa', ref: 'cc', status: 'success' + @commit4 = FactoryGirl.create :commit_status, commit: commit, name: 'cc', ref: 'bb', status: 'success' + @commit5 = FactoryGirl.create :commit_status, commit: commit, name: 'aa', ref: 'bb', status: 'success' + end + + it 'return unique statuses' do + is_expected.to eq([@commit2, @commit3, @commit4, @commit5]) + end + end + + describe :for_ref do + subject { CommitStatus.for_ref('bb').order(:id) } + + before do + @commit1 = FactoryGirl.create :commit_status, commit: commit, name: 'aa', ref: 'bb', status: 'running' + @commit2 = FactoryGirl.create :commit_status, commit: commit, name: 'cc', ref: 'cc', status: 'pending' + @commit3 = FactoryGirl.create :commit_status, commit: commit, name: 'aa', ref: nil, status: 'success' + end + + it 'return statuses with equal and nil ref set' do + is_expected.to eq([@commit1, @commit3]) + end + end + + describe :running_or_pending do + subject { CommitStatus.running_or_pending.order(:id) } + + before do + @commit1 = FactoryGirl.create :commit_status, commit: commit, name: 'aa', ref: 'bb', status: 'running' + @commit2 = FactoryGirl.create :commit_status, commit: commit, name: 'cc', ref: 'cc', status: 'pending' + @commit3 = FactoryGirl.create :commit_status, commit: commit, name: 'aa', ref: nil, status: 'success' + @commit4 = FactoryGirl.create :commit_status, commit: commit, name: 'dd', ref: nil, status: 'failed' + @commit5 = FactoryGirl.create :commit_status, commit: commit, name: 'ee', ref: nil, status: 'canceled' + end + + it 'return statuses that are running or pending' do + is_expected.to eq([@commit1, @commit2]) + end + end +end diff --git a/spec/models/generic_commit_status_spec.rb b/spec/models/generic_commit_status_spec.rb new file mode 100644 index 00000000000..f442fa5fbe5 --- /dev/null +++ b/spec/models/generic_commit_status_spec.rb @@ -0,0 +1,39 @@ +require 'spec_helper' + +describe GenericCommitStatus do + let(:commit) { FactoryGirl.create :ci_commit } + let(:generic_commit_status) { FactoryGirl.create :generic_commit_status, commit: commit } + + describe :context do + subject { generic_commit_status.context } + before { generic_commit_status.context = 'my_context' } + + it { is_expected.to eq(generic_commit_status.name) } + end + + describe :tags do + subject { generic_commit_status.tags } + + it { is_expected.to eq([:external]) } + end + + describe :set_default_values do + before do + generic_commit_status.context = nil + generic_commit_status.stage = nil + generic_commit_status.save + end + + describe :context do + subject { generic_commit_status.context } + + it { is_expected.to_not be_nil } + end + + describe :stage do + subject { generic_commit_status.stage } + + it { is_expected.to_not be_nil } + end + end +end diff --git a/spec/requests/api/commit_status_spec.rb b/spec/requests/api/commit_status_spec.rb new file mode 100644 index 00000000000..d1dc97e1846 --- /dev/null +++ b/spec/requests/api/commit_status_spec.rb @@ -0,0 +1,135 @@ +require 'spec_helper' + +describe API::API, api: true do + include ApiHelpers + let(:user) { create(:user) } + let(:user2) { create(:user) } + let!(:project) { create(:project, creator_id: user.id) } + let!(:reporter) { create(:project_member, user: user, project: project, access_level: ProjectMember::REPORTER) } + let!(:guest) { create(:project_member, user: user2, project: project, access_level: ProjectMember::GUEST) } + let(:commit) { project.repository.commit } + let!(:ci_commit) { project.ensure_ci_commit(commit.id) } + let(:commit_status) { create(:commit_status, commit: ci_commit) } + + describe "GET /projects/:id/repository/commits/:sha/statuses" do + context "reporter user" do + let(:statuses_id) { json_response.map { |status| status['id'] } } + + before do + @status1 = create(:commit_status, commit: ci_commit, status: 'running') + @status2 = create(:commit_status, commit: ci_commit, name: 'coverage', status: 'pending') + @status3 = create(:commit_status, commit: ci_commit, name: 'coverage', ref: 'develop', status: 'running') + @status4 = create(:commit_status, commit: ci_commit, name: 'coverage', status: 'success') + @status5 = create(:commit_status, commit: ci_commit, ref: 'develop', status: 'success') + @status6 = create(:commit_status, commit: ci_commit, status: 'success') + end + + it "should return latest commit statuses" do + get api("/projects/#{project.id}/repository/commits/#{commit.id}/statuses", user) + expect(response.status).to eq(200) + + expect(json_response).to be_an Array + expect(statuses_id).to contain_exactly(@status3.id, @status4.id, @status5.id, @status6.id) + end + + it "should return all commit statuses" do + get api("/projects/#{project.id}/repository/commits/#{commit.id}/statuses?all=1", user) + expect(response.status).to eq(200) + + expect(json_response).to be_an Array + expect(statuses_id).to contain_exactly(@status1.id, @status2.id, @status3.id, @status4.id, @status5.id, @status6.id) + end + + it "should return latest commit statuses for specific ref" do + get api("/projects/#{project.id}/repository/commits/#{commit.id}/statuses?ref=develop", user) + expect(response.status).to eq(200) + + expect(json_response).to be_an Array + expect(statuses_id).to contain_exactly(@status3.id, @status5.id) + end + + it "should return latest commit statuses for specific name" do + get api("/projects/#{project.id}/repository/commits/#{commit.id}/statuses?name=coverage", user) + expect(response.status).to eq(200) + + expect(json_response).to be_an Array + expect(statuses_id).to contain_exactly(@status3.id, @status4.id) + end + end + + context "guest user" do + it "should not return project commits" do + get api("/projects/#{project.id}/repository/commits/#{commit.id}/statuses", user2) + expect(response.status).to eq(403) + end + end + + context "unauthorized user" do + it "should not return project commits" do + get api("/projects/#{project.id}/repository/commits/#{commit.id}/statuses") + expect(response.status).to eq(401) + end + end + end + + describe 'POST /projects/:id/repository/commits/:sha/status' do + let(:post_url) { "/projects/#{project.id}/repository/commits/#{commit.id}/status" } + + context 'reporter user' do + context 'should create commit status' do + it 'with only required parameters' do + post api(post_url, user), state: 'success' + expect(response.status).to eq(201) + expect(json_response['sha']).to eq(commit.id) + expect(json_response['status']).to eq('success') + expect(json_response['name']).to eq('default') + expect(json_response['ref']).to be_nil + expect(json_response['target_url']).to be_nil + expect(json_response['description']).to be_nil + end + + it 'with all optional parameters' do + post api(post_url, user), state: 'success', context: 'coverage', ref: 'develop', target_url: 'url', description: 'test' + expect(response.status).to eq(201) + expect(json_response['sha']).to eq(commit.id) + expect(json_response['status']).to eq('success') + expect(json_response['name']).to eq('coverage') + expect(json_response['ref']).to eq('develop') + expect(json_response['target_url']).to eq('url') + expect(json_response['description']).to eq('test') + end + end + + context 'should not create commit status' do + it 'with invalid state' do + post api(post_url, user), state: 'invalid' + expect(response.status).to eq(400) + end + + it 'without state' do + post api(post_url, user) + expect(response.status).to eq(400) + end + + it 'invalid commit' do + post api("/projects/#{project.id}/repository/commits/invalid_sha/status", user), state: 'running' + expect(response.status).to eq(404) + end + end + end + + context 'guest user' do + it 'should not create commit status' do + post api(post_url, user2) + expect(response.status).to eq(403) + end + end + + context 'unauthorized user' do + it 'should not create commit status' do + post api(post_url) + expect(response.status).to eq(401) + end + end + end +end diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb index a1c248c636e..49acc3368f4 100644 --- a/spec/requests/api/commits_spec.rb +++ b/spec/requests/api/commits_spec.rb @@ -47,6 +47,19 @@ describe API::API, api: true do get api("/projects/#{project.id}/repository/commits/invalid_sha", user) expect(response.status).to eq(404) end + + it "should return not_found for CI status" do + get api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}", user) + expect(response.status).to eq(200) + expect(json_response['status']).to eq('not_found') + end + + it "should return status for CI" do + ci_commit = project.ensure_ci_commit(project.repository.commit.sha) + get api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}", user) + expect(response.status).to eq(200) + expect(json_response['status']).to eq(ci_commit.status) + end end context "unauthorized user" do -- cgit v1.2.1 From d805c5dbb3c2fde0a3b97f86a2dd3abc35e72bd9 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Fri, 9 Oct 2015 19:08:37 +0300 Subject: Add spellcheck=false to certain input fields --- app/views/admin/users/index.html.haml | 2 +- app/views/ci/admin/runners/index.html.haml | 2 +- app/views/ci/admin/runners/show.html.haml | 2 +- app/views/dashboard/projects/_projects.html.haml | 2 +- app/views/explore/groups/index.html.haml | 2 +- app/views/explore/projects/_filter.html.haml | 2 +- app/views/groups/_projects.html.haml | 2 +- app/views/groups/group_members/index.html.haml | 2 +- app/views/layouts/_search.html.haml | 2 +- app/views/projects/project_members/index.html.haml | 2 +- app/views/search/_form.html.haml | 2 +- app/views/shared/issuable/_search_form.html.haml | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml index e3698ac1c46..71e15d555d3 100644 --- a/app/views/admin/users/index.html.haml +++ b/app/views/admin/users/index.html.haml @@ -32,7 +32,7 @@ %hr = form_tag admin_users_path, method: :get, class: 'form-inline' do .form-group - = search_field_tag :name, params[:name], placeholder: 'Name, email or username', class: 'form-control' + = search_field_tag :name, params[:name], placeholder: 'Name, email or username', class: 'form-control', spellcheck: false = hidden_field_tag "filter", params[:filter] = button_tag class: 'btn btn-primary' do %i.fa.fa-search diff --git a/app/views/ci/admin/runners/index.html.haml b/app/views/ci/admin/runners/index.html.haml index b9d6703ff41..01ce81b4476 100644 --- a/app/views/ci/admin/runners/index.html.haml +++ b/app/views/ci/admin/runners/index.html.haml @@ -27,7 +27,7 @@ .pull-left = form_tag ci_admin_runners_path, id: 'runners-search', class: 'form-inline', method: :get do .form-group - = search_field_tag :search, params[:search], class: 'form-control', placeholder: 'Runner description or token' + = search_field_tag :search, params[:search], class: 'form-control', placeholder: 'Runner description or token', spellcheck: false = submit_tag 'Search', class: 'btn' .pull-right.light diff --git a/app/views/ci/admin/runners/show.html.haml b/app/views/ci/admin/runners/show.html.haml index 5bb442cbf92..92787b2e6ac 100644 --- a/app/views/ci/admin/runners/show.html.haml +++ b/app/views/ci/admin/runners/show.html.haml @@ -76,7 +76,7 @@ %td = form_tag ci_admin_runner_path(@runner), id: 'runner-projects-search', class: 'form-inline', method: :get do .form-group - = search_field_tag :search, params[:search], class: 'form-control' + = search_field_tag :search, params[:search], class: 'form-control', spellcheck: false = submit_tag 'Search', class: 'btn' %td diff --git a/app/views/dashboard/projects/_projects.html.haml b/app/views/dashboard/projects/_projects.html.haml index e09e032a7f1..d0194a17b01 100644 --- a/app/views/dashboard/projects/_projects.html.haml +++ b/app/views/dashboard/projects/_projects.html.haml @@ -1,7 +1,7 @@ .projects-list-holder .projects-search-form .input-group - = search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control' + = search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control', spellcheck: false - if current_user.can_create_project? %span.input-group-btn = link_to new_project_path, class: 'btn btn-green' do diff --git a/app/views/explore/groups/index.html.haml b/app/views/explore/groups/index.html.haml index 83d4d321c83..fcb07b04083 100644 --- a/app/views/explore/groups/index.html.haml +++ b/app/views/explore/groups/index.html.haml @@ -11,7 +11,7 @@ = form_tag explore_groups_path, method: :get, class: 'form-inline form-tiny' do |f| = hidden_field_tag :sort, @sort .form-group - = search_field_tag :search, params[:search], placeholder: "Filter by name", class: "form-control search-text-input", id: "groups_search" + = search_field_tag :search, params[:search], placeholder: "Filter by name", class: "form-control search-text-input", id: "groups_search", spellcheck: false .form-group = button_tag 'Search', class: "btn btn-default" diff --git a/app/views/explore/projects/_filter.html.haml b/app/views/explore/projects/_filter.html.haml index 5a3d689d1e5..2761272aa8a 100644 --- a/app/views/explore/projects/_filter.html.haml +++ b/app/views/explore/projects/_filter.html.haml @@ -1,7 +1,7 @@ .pull-left = form_tag explore_projects_filter_path, method: :get, class: 'form-inline form-tiny' do |f| .form-group - = search_field_tag :search, params[:search], placeholder: "Filter by name", class: "form-control search-text-input", id: "projects_search" + = search_field_tag :search, params[:search], placeholder: "Filter by name", class: "form-control search-text-input", id: "projects_search", spellcheck: false .form-group = button_tag 'Search', class: "btn btn-success" diff --git a/app/views/groups/_projects.html.haml b/app/views/groups/_projects.html.haml index 2b27a88794d..76da3276e47 100644 --- a/app/views/groups/_projects.html.haml +++ b/app/views/groups/_projects.html.haml @@ -1,7 +1,7 @@ .panel.panel-default.projects-list-holder .panel-heading.clearfix .input-group - = search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control' + = search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control', spellcheck: false - if can? current_user, :create_projects, @group %span.input-group-btn = link_to new_project_path(namespace_id: @group.id), class: 'btn btn-green' do diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml index 3a6d07ebddf..fee4b0052b5 100644 --- a/app/views/groups/group_members/index.html.haml +++ b/app/views/groups/group_members/index.html.haml @@ -12,7 +12,7 @@ .clearfix.js-toggle-container = form_tag group_group_members_path(@group), method: :get, class: 'form-inline member-search-form' do .form-group - = search_field_tag :search, params[:search], { placeholder: 'Find existing member by name', class: 'form-control search-text-input' } + = search_field_tag :search, params[:search], { placeholder: 'Find existing member by name', class: 'form-control search-text-input', spellcheck: false } = button_tag 'Search', class: 'btn' - if current_user && current_user.can?(:admin_group_member, @group) diff --git a/app/views/layouts/_search.html.haml b/app/views/layouts/_search.html.haml index e2d2dec7ab8..ceb64ce3157 100644 --- a/app/views/layouts/_search.html.haml +++ b/app/views/layouts/_search.html.haml @@ -1,6 +1,6 @@ .search = form_tag search_path, method: :get, class: 'navbar-form pull-left' do |f| - = search_field_tag "search", nil, placeholder: search_placeholder, class: "search-input form-control" + = search_field_tag "search", nil, placeholder: search_placeholder, class: "search-input form-control", spellcheck: false = hidden_field_tag :group_id, @group.try(:id) - if @project && @project.persisted? = hidden_field_tag :project_id, @project.id diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml index 9a0a824b811..82809bec5b8 100644 --- a/app/views/projects/project_members/index.html.haml +++ b/app/views/projects/project_members/index.html.haml @@ -5,7 +5,7 @@ .clearfix.js-toggle-container = form_tag namespace_project_project_members_path(@project.namespace, @project), method: :get, class: 'form-inline member-search-form' do .form-group - = search_field_tag :search, params[:search], { placeholder: 'Find existing member by name', class: 'form-control search-text-input' } + = search_field_tag :search, params[:search], { placeholder: 'Find existing member by name', class: 'form-control search-text-input', spellcheck: false } = button_tag 'Search', class: 'btn' - if can?(current_user, :admin_project_member, @project) diff --git a/app/views/search/_form.html.haml b/app/views/search/_form.html.haml index 3938c545cad..17b0981f073 100644 --- a/app/views/search/_form.html.haml +++ b/app/views/search/_form.html.haml @@ -6,7 +6,7 @@ .search-holder.clearfix .input-group - = search_field_tag :search, params[:search], placeholder: "Search for projects, issues etc", class: "form-control search-text-input", id: "dashboard_search", autofocus: true + = search_field_tag :search, params[:search], placeholder: "Search for projects, issues etc", class: "form-control search-text-input", id: "dashboard_search", autofocus: true, spellcheck: false %span.input-group-btn = button_tag 'Search', class: "btn btn-primary" - unless params[:snippets].eql? 'true' diff --git a/app/views/shared/issuable/_search_form.html.haml b/app/views/shared/issuable/_search_form.html.haml index 58c3de64b77..3a5ad00aa91 100644 --- a/app/views/shared/issuable/_search_form.html.haml +++ b/app/views/shared/issuable/_search_form.html.haml @@ -1,6 +1,6 @@ = form_tag(path, method: :get, id: "issue_search_form", class: 'pull-left issue-search-form') do .append-right-10.hidden-xs.hidden-sm - = search_field_tag :issue_search, params[:issue_search], { placeholder: 'Filter by title or description', class: 'form-control issue_search search-text-input' } + = search_field_tag :issue_search, params[:issue_search], { placeholder: 'Filter by title or description', class: 'form-control issue_search search-text-input', spellcheck: false } = hidden_field_tag :state, params['state'] = hidden_field_tag :scope, params['scope'] = hidden_field_tag :assignee_id, params['assignee_id'] -- cgit v1.2.1 From 887494761ee41e8e647753e597fab534ed738058 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 12 Oct 2015 12:15:35 +0200 Subject: Fix commit status POST URL --- lib/api/commit_statuses.rb | 2 +- spec/requests/api/commit_status_spec.rb | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/api/commit_statuses.rb b/lib/api/commit_statuses.rb index cfe8739b175..41c05334296 100644 --- a/lib/api/commit_statuses.rb +++ b/lib/api/commit_statuses.rb @@ -41,7 +41,7 @@ module API # description (optional) - A short description of the status # name or context (optional) - A string label to differentiate this status from the status of other systems. Default: "default" # Examples: - # POST /projects/:id/repository/commits/:sha/status + # POST /projects/:id/statuses/:sha post ':id/statuses/:sha' do required_attributes! [:state] attrs = attributes_for_keys [:ref, :target_url, :description, :context, :name] diff --git a/spec/requests/api/commit_status_spec.rb b/spec/requests/api/commit_status_spec.rb index d1dc97e1846..b9e6dfc15a7 100644 --- a/spec/requests/api/commit_status_spec.rb +++ b/spec/requests/api/commit_status_spec.rb @@ -72,8 +72,8 @@ describe API::API, api: true do end end - describe 'POST /projects/:id/repository/commits/:sha/status' do - let(:post_url) { "/projects/#{project.id}/repository/commits/#{commit.id}/status" } + describe 'POST /projects/:id/statuses/:sha' do + let(:post_url) { "/projects/#{project.id}/statuses/#{commit.id}" } context 'reporter user' do context 'should create commit status' do @@ -112,7 +112,7 @@ describe API::API, api: true do end it 'invalid commit' do - post api("/projects/#{project.id}/repository/commits/invalid_sha/status", user), state: 'running' + post api("/projects/#{project.id}/statuses/invalid_sha", user), state: 'running' expect(response.status).to eq(404) end end -- cgit v1.2.1 From 7ef156a24292f98d89bc424cc245f00548831863 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 12 Oct 2015 12:15:48 +0200 Subject: Add author to statuses --- app/models/commit_status.rb | 2 ++ lib/api/commit_statuses.rb | 2 +- lib/api/entities.rb | 1 + spec/models/commit_status_spec.rb | 7 +++++++ 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index 4c6de18527b..de7b29a649d 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -9,6 +9,8 @@ class CommitStatus < ActiveRecord::Base validates_presence_of :name + alias_attribute :author, :user + scope :running, ->() { where(status: 'running') } scope :pending, ->() { where(status: 'pending') } scope :success, ->() { where(status: 'success') } diff --git a/lib/api/commit_statuses.rb b/lib/api/commit_statuses.rb index 41c05334296..c478b3dc245 100644 --- a/lib/api/commit_statuses.rb +++ b/lib/api/commit_statuses.rb @@ -52,7 +52,7 @@ module API name = params[:name] || params[:context] status = GenericCommitStatus.running_or_pending.find_by(commit: ci_commit, name: name, ref: params[:ref]) - status = GenericCommitStatus.new(commit: ci_commit) unless status + status = GenericCommitStatus.new(commit: ci_commit, user: current_user) unless status status.update(attrs) case params[:state].to_s diff --git a/lib/api/entities.rb b/lib/api/entities.rb index e1c5a459751..bfb242bb6fd 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -232,6 +232,7 @@ module API class CommitStatus < Grape::Entity expose :id, :sha, :ref, :status, :name, :target_url, :description, :created_at, :started_at, :finished_at + expose :author, using: Entities::UserBasic end class Event < Grape::Entity diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb index c1af50afb7c..cbefa7798de 100644 --- a/spec/models/commit_status_spec.rb +++ b/spec/models/commit_status_spec.rb @@ -18,6 +18,13 @@ describe CommitStatus do it { is_expected.to respond_to :running? } it { is_expected.to respond_to :pending? } + describe :author do + subject { commit_status.author } + before { commit_status.author = User.new } + + it { is_expected.to eq(commit_status.user) } + end + describe :started? do subject { commit_status.started? } -- cgit v1.2.1 From 07f60552728db7276ad24dafd1ff601ae49442d2 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Fri, 9 Oct 2015 13:20:38 +0300 Subject: Invalidate stored service password if the endpoint URL is changed --- app/models/project_services/bamboo_service.rb | 7 +++ app/models/project_services/teamcity_service.rb | 7 +++ app/models/service.rb | 9 ++++ .../models/project_services/bamboo_service_spec.rb | 56 ++++++++++++++++++++++ .../project_services/teamcity_service_spec.rb | 56 ++++++++++++++++++++++ spec/models/service_spec.rb | 23 +++++++++ 6 files changed, 158 insertions(+) create mode 100644 spec/models/project_services/bamboo_service_spec.rb create mode 100644 spec/models/project_services/teamcity_service_spec.rb diff --git a/app/models/project_services/bamboo_service.rb b/app/models/project_services/bamboo_service.rb index d8aedbd2ab4..5f5255ab487 100644 --- a/app/models/project_services/bamboo_service.rb +++ b/app/models/project_services/bamboo_service.rb @@ -40,12 +40,19 @@ class BambooService < CiService attr_accessor :response after_save :compose_service_hook, if: :activated? + before_update :reset_password def compose_service_hook hook = service_hook || build_service_hook hook.save end + def reset_password + if prop_updated?(:bamboo_url) + self.password = nil + end + end + def title 'Atlassian Bamboo CI' end diff --git a/app/models/project_services/teamcity_service.rb b/app/models/project_services/teamcity_service.rb index 3c002a1634b..fb11cad352e 100644 --- a/app/models/project_services/teamcity_service.rb +++ b/app/models/project_services/teamcity_service.rb @@ -37,12 +37,19 @@ class TeamcityService < CiService attr_accessor :response after_save :compose_service_hook, if: :activated? + before_update :reset_password def compose_service_hook hook = service_hook || build_service_hook hook.save end + def reset_password + if prop_updated?(:teamcity_url) + self.password = nil + end + end + def title 'JetBrains TeamCity CI' end diff --git a/app/models/service.rb b/app/models/service.rb index 60fcc9d2857..7e845d565b1 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -117,6 +117,15 @@ class Service < ActiveRecord::Base end end + # ActiveRecord does not provide a mechanism to track changes in serialized keys. + # This is why we need to perform extra query to do it mannually. + def prop_updated?(prop_name) + relation_name = self.type.underscore + previous_value = project.send(relation_name).send(prop_name) + return false if previous_value.nil? + previous_value != send(prop_name) + end + def async_execute(data) return unless supported_events.include?(data[:object_kind]) diff --git a/spec/models/project_services/bamboo_service_spec.rb b/spec/models/project_services/bamboo_service_spec.rb new file mode 100644 index 00000000000..f8a3493f52d --- /dev/null +++ b/spec/models/project_services/bamboo_service_spec.rb @@ -0,0 +1,56 @@ +# == Schema Information +# +# Table name: services +# +# id :integer not null, primary key +# type :string(255) +# title :string(255) +# project_id :integer +# created_at :datetime +# updated_at :datetime +# active :boolean default(FALSE), not null +# properties :text +# template :boolean default(FALSE) +# push_events :boolean default(TRUE) +# issues_events :boolean default(TRUE) +# merge_requests_events :boolean default(TRUE) +# tag_push_events :boolean default(TRUE) +# note_events :boolean default(TRUE), not null +# + +require 'spec_helper' + +describe BambooService, models: true do + describe "Associations" do + it { is_expected.to belong_to :project } + it { is_expected.to have_one :service_hook } + end + + describe "Execute" do + let(:user) { create(:user) } + let(:project) { create(:project) } + + before do + @bamboo_service = BambooService.create( + project: create(:project), + properties: { + bamboo_url: 'http://gitlab.com', + username: 'mic', + password: "password" + } + ) + end + + it "reset password if url changed" do + @bamboo_service.bamboo_url = 'http://gitlab1.com' + @bamboo_service.save + expect(@bamboo_service.password).to be_nil + end + + it "does not reset password if username changed" do + @bamboo_service.username = "some_name" + @bamboo_service.save + expect(@bamboo_service.password).to eq("password") + end + end +end diff --git a/spec/models/project_services/teamcity_service_spec.rb b/spec/models/project_services/teamcity_service_spec.rb new file mode 100644 index 00000000000..3dbd2346bcc --- /dev/null +++ b/spec/models/project_services/teamcity_service_spec.rb @@ -0,0 +1,56 @@ +# == Schema Information +# +# Table name: services +# +# id :integer not null, primary key +# type :string(255) +# title :string(255) +# project_id :integer +# created_at :datetime +# updated_at :datetime +# active :boolean default(FALSE), not null +# properties :text +# template :boolean default(FALSE) +# push_events :boolean default(TRUE) +# issues_events :boolean default(TRUE) +# merge_requests_events :boolean default(TRUE) +# tag_push_events :boolean default(TRUE) +# note_events :boolean default(TRUE), not null +# + +require 'spec_helper' + +describe TeamcityService, models: true do + describe "Associations" do + it { is_expected.to belong_to :project } + it { is_expected.to have_one :service_hook } + end + + describe "Execute" do + let(:user) { create(:user) } + let(:project) { create(:project) } + + before do + @teamcity_service = TeamcityService.create( + project: create(:project), + properties: { + teamcity_url: 'http://gitlab.com', + username: 'mic', + password: "password" + } + ) + end + + it "reset password if url changed" do + @teamcity_service.teamcity_url = 'http://gitlab1.com' + @teamcity_service.save + expect(@teamcity_service.password).to be_nil + end + + it "does not reset password if username changed" do + @teamcity_service.username = "some_name" + @teamcity_service.save + expect(@teamcity_service.password).to eq("password") + end + end +end diff --git a/spec/models/service_spec.rb b/spec/models/service_spec.rb index a213ffe6c4b..da87ea5b84f 100644 --- a/spec/models/service_spec.rb +++ b/spec/models/service_spec.rb @@ -103,4 +103,27 @@ describe Service do end end end + + describe "#prop_updated?" do + let(:service) do + BambooService.create( + project: create(:project), + properties: { + bamboo_url: 'http://gitlab.com', + username: 'mic', + password: "password" + } + ) + end + + it "returns false" do + service.username = "key_changed" + expect(service.prop_updated?(:bamboo_url)).to be_falsy + end + + it "returns true" do + service.bamboo_url = "http://other.com" + expect(service.prop_updated?(:bamboo_url)).to be_truthy + end + end end -- cgit v1.2.1 From 0aefeeb882b40d740b80f15ac6610a88a340d30b Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 12 Oct 2015 12:16:00 +0200 Subject: Add Commit Status documentation --- app/models/ci/commit.rb | 2 +- app/models/commit_status.rb | 2 +- doc/api/commits.md | 82 +++++++++++++++++++++++++++++++++++++++++++++ lib/api/commit_statuses.rb | 20 +++++------ 4 files changed, 94 insertions(+), 12 deletions(-) diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb index 042a68681bb..623ff619c49 100644 --- a/app/models/ci/commit.rb +++ b/app/models/ci/commit.rb @@ -136,7 +136,7 @@ module Ci latest_statuses = statuses.latest.to_a latest_statuses.reject! { |status| status.try(&:allow_failure?) } - latest_statuses.select! { |status| status.ref == nil || status.ref == ref } if ref + latest_statuses.select! { |status| status.ref.nil? || status.ref == ref } if ref if latest_statuses.none? return 'skipped' diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index de7b29a649d..a4896a76316 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -5,7 +5,7 @@ class CommitStatus < ActiveRecord::Base belongs_to :user validates :commit, presence: true - validates :status, inclusion: {in: %w(pending running failed success canceled)} + validates :status, inclusion: { in: %w(pending running failed success canceled) } validates_presence_of :name diff --git a/doc/api/commits.md b/doc/api/commits.md index b22d040bf0d..78144dd42ef 100644 --- a/doc/api/commits.md +++ b/doc/api/commits.md @@ -157,3 +157,85 @@ Parameters: "line_type": "new" } ``` + +## Get the status of a commit + +Get the statuses of a commit in a project. + +``` +GET /projects/:id/repository/commits/:sha/statuses +``` + +Parameters: + +- `id` (required) - The ID of a project +- `sha` (required) - The commit SHA +- `ref` (optional) - Filter by ref name, it can be branch or tag +- `stage` (optional) - Filter by stage +- `name` (optional) - Filer by status name, eg. jenkins +- `all` (optional) - The flag to return all statuses, not only latest ones + +```json +[ + { + "id": 13, + "sha": "b0b3a907f41409829b307a28b82fdbd552ee5a27", + "ref": "test", + "status": "success", + "name": "ci/jenkins", + "target_url": "http://jenkins/project/url", + "description": "Jenkins success", + "created_at": "2015-10-12T09:47:16.250Z", + "started_at": "2015-10-12T09:47:16.250Z"", + "finished_at": "2015-10-12T09:47:16.262Z", + "author": { + "id": 1, + "username": "admin", + "email": "admin@local.host", + "name": "Administrator", + "blocked": false, + "created_at": "2012-04-29T08:46:00Z" + } + } +] +``` + +## Post the status to commit + +Adds or updates a status of a commit. +Optionally you can post comments on a specific line of a commit. Therefor both `path`, `line_new` and `line_old` are required. + +``` +POST /projects/:id/statuses/:sha +``` + +- `id` (required) - The ID of a project +- `sha` (required) - The commit SHA +- `state` (required) - The state of the status. Can be: pending, running, success, failed, canceled +- `ref` (optional) - The ref (branch or tag) to which the status refers +- `name` or `context` (optional) - The label to differentiate this status from the status of other systems. Default: "default" +- `target_url` (optional) - The target URL to associate with this status +- `description` (optional) - The short description of the status + +```json +{ + "id": 13, + "sha": "b0b3a907f41409829b307a28b82fdbd552ee5a27", + "ref": "test", + "status": "success", + "name": "ci/jenkins", + "target_url": "http://jenkins/project/url", + "description": "Jenkins success", + "created_at": "2015-10-12T09:47:16.250Z", + "started_at": "2015-10-12T09:47:16.250Z"", + "finished_at": "2015-10-12T09:47:16.262Z", + "author": { + "id": 1, + "username": "admin", + "email": "admin@local.host", + "name": "Administrator", + "blocked": false, + "created_at": "2012-04-29T08:46:00Z" + } +} +``` diff --git a/lib/api/commit_statuses.rb b/lib/api/commit_statuses.rb index c478b3dc245..ca750320e40 100644 --- a/lib/api/commit_statuses.rb +++ b/lib/api/commit_statuses.rb @@ -56,16 +56,16 @@ module API status.update(attrs) case params[:state].to_s - when 'running' - status.run - when 'success' - status.success - when 'failed' - status.drop - when 'canceled' - status.cancel - else - status.status = params[:state].to_s + when 'running' + status.run + when 'success' + status.success + when 'failed' + status.drop + when 'canceled' + status.cancel + else + status.status = params[:state].to_s end if status.save -- cgit v1.2.1 From c2c8f8acc41747280356e157e749c1cafbd807e3 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Mon, 12 Oct 2015 14:36:06 +0200 Subject: Remove warning about Reply by email and HA --- doc/incoming_email/README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/doc/incoming_email/README.md b/doc/incoming_email/README.md index 076c8c049a8..aafa2345fab 100644 --- a/doc/incoming_email/README.md +++ b/doc/incoming_email/README.md @@ -2,10 +2,6 @@ GitLab can be set up to allow users to comment on issues and merge requests by replying to notification emails. -**Warning**: Do not enable Reply by email if you have **multiple GitLab application servers**. -Due to an issue with the way incoming emails are read from the mail server, every incoming reply-by-email email will result in as many comments being created as you have application servers. -[A fix is being worked on.](https://github.com/tpitale/mail_room/issues/46) - ## Get a mailbox Reply by email requires an IMAP-enabled email account, with a provider or server that supports [email sub-addressing](https://en.wikipedia.org/wiki/Email_address#Sub-addressing). Sub-addressing is a feature where any email to `user+some_arbitrary_tag@example.com` will end up in the mailbox for `user@example.com`, and is supported by providers such as Gmail, Yahoo! Mail, Outlook.com and iCloud, as well as the Postfix mail server which you can run on-premises. -- cgit v1.2.1 From d6a523d78569020a00cf707f34a1824996261037 Mon Sep 17 00:00:00 2001 From: teuneboon Date: Mon, 12 Oct 2015 14:37:07 +0200 Subject: Fix typo(missing quote) when deleting groups --- app/controllers/groups_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 524218290c6..735de309fd6 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -88,7 +88,7 @@ class GroupsController < Groups::ApplicationController def destroy DestroyGroupService.new(@group, current_user).execute - redirect_to root_path, alert: "Group '#{@group.name} was deleted." + redirect_to root_path, alert: "Group '#{@group.name}' was deleted." end protected -- cgit v1.2.1 From 5479797f0a3a648824fd98d17360bbf886957bf1 Mon Sep 17 00:00:00 2001 From: teuneboon Date: Mon, 12 Oct 2015 14:37:56 +0200 Subject: Make group deleted text consistent with group created and updated texts --- app/controllers/groups_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 735de309fd6..40fb15a5b36 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -88,7 +88,7 @@ class GroupsController < Groups::ApplicationController def destroy DestroyGroupService.new(@group, current_user).execute - redirect_to root_path, alert: "Group '#{@group.name}' was deleted." + redirect_to root_path, alert: "Group '#{@group.name}' was successfully deleted." end protected -- cgit v1.2.1 From cba6d62323eba2286f78e8aea12a5ecd26903728 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 12 Oct 2015 14:49:23 +0200 Subject: Move CI styles to pages dir Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/ci/builds.scss | 75 --- app/assets/stylesheets/ci/lint.scss | 10 - app/assets/stylesheets/ci/projects.scss | 59 -- app/assets/stylesheets/ci/runners.scss | 36 - app/assets/stylesheets/ci/status.scss | 37 -- app/assets/stylesheets/ci/xterm.scss | 906 -------------------------- app/assets/stylesheets/pages/builds.scss | 75 +++ app/assets/stylesheets/pages/ci_projects.scss | 59 ++ app/assets/stylesheets/pages/lint.scss | 10 + app/assets/stylesheets/pages/runners.scss | 36 + app/assets/stylesheets/pages/status.scss | 37 ++ app/assets/stylesheets/pages/xterm.scss | 906 ++++++++++++++++++++++++++ 12 files changed, 1123 insertions(+), 1123 deletions(-) delete mode 100644 app/assets/stylesheets/ci/builds.scss delete mode 100644 app/assets/stylesheets/ci/lint.scss delete mode 100644 app/assets/stylesheets/ci/projects.scss delete mode 100644 app/assets/stylesheets/ci/runners.scss delete mode 100644 app/assets/stylesheets/ci/status.scss delete mode 100644 app/assets/stylesheets/ci/xterm.scss create mode 100644 app/assets/stylesheets/pages/builds.scss create mode 100644 app/assets/stylesheets/pages/ci_projects.scss create mode 100644 app/assets/stylesheets/pages/lint.scss create mode 100644 app/assets/stylesheets/pages/runners.scss create mode 100644 app/assets/stylesheets/pages/status.scss create mode 100644 app/assets/stylesheets/pages/xterm.scss diff --git a/app/assets/stylesheets/ci/builds.scss b/app/assets/stylesheets/ci/builds.scss deleted file mode 100644 index 74dc3e321c1..00000000000 --- a/app/assets/stylesheets/ci/builds.scss +++ /dev/null @@ -1,75 +0,0 @@ -.build-page { - pre.trace { - background: #111111; - color: #fff; - font-family: $monospace_font; - white-space: pre; - white-space: pre-wrap; /* css-3 */ - white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ - white-space: -pre-wrap; /* Opera 4-6 */ - white-space: -o-pre-wrap; /* Opera 7 */ - word-wrap: break-word; /* Internet Explorer 5.5+ */ - overflow: auto; - overflow-y: hidden; - font-size: 12px; - - .fa-refresh { - font-size: 24px; - margin-left: 20px; - } - } - - .autoscroll-container { - position: fixed; - bottom: 10px; - right: 20px; - z-index: 100; - } - - .scroll-controls { - position: fixed; - bottom: 10px; - left: 250px; - z-index: 100; - - a { - display: block; - margin-bottom: 5px; - } - } - - .page-sidebar-collapsed { - .scroll-controls { - left: 70px; - } - } - - .build-widget { - padding: 10px; - background: $background-color; - margin-bottom: 20px; - border-radius: 4px; - - .title { - margin-top: 0; - color: #666; - line-height: 1.5; - } - .attr-name { - color: #777; - } - } - - .alert-disabled { - background: $background-color; - - a { - color: #3084bb !important; - } - } - - .build-top-menu { - margin-top: 0; - margin-bottom: 2px; - } -} diff --git a/app/assets/stylesheets/ci/lint.scss b/app/assets/stylesheets/ci/lint.scss deleted file mode 100644 index 6d2bd33b28b..00000000000 --- a/app/assets/stylesheets/ci/lint.scss +++ /dev/null @@ -1,10 +0,0 @@ -.ci-body { - .incorrect-syntax{ - font-size: 19px; - color: red; - } - .correct-syntax{ - font-size: 19px; - color: #47a447; - } -} diff --git a/app/assets/stylesheets/ci/projects.scss b/app/assets/stylesheets/ci/projects.scss deleted file mode 100644 index 8c5273abcda..00000000000 --- a/app/assets/stylesheets/ci/projects.scss +++ /dev/null @@ -1,59 +0,0 @@ -.ci-body { - .project-title { - margin: 0; - color: #444; - font-size: 20px; - line-height: 1.5; - } - - .wide-table-holder { - margin-left: -$gl-padding; - margin-right: -$gl-padding; - } - - .builds, - .projects-table { - .light { - border-color: $border-color; - } - - th, td { - padding: 10px $gl-padding; - } - - td { - color: $gl-gray; - vertical-align: middle !important; - - a { - font-weight: normal; - text-decoration: none; - } - } - } - - .commit-info { - .attr-name { - margin-right: 5px; - } - - pre.commit-message { - background: none; - padding: 0; - margin: 0; - border: none; - margin: 20px 0; - border-radius: 0; - } - } - - .loading{ - font-size: 20px; - } - - .ci-charts { - fieldset { - margin-bottom: 16px; - } - } -} diff --git a/app/assets/stylesheets/ci/runners.scss b/app/assets/stylesheets/ci/runners.scss deleted file mode 100644 index 2b15ab83129..00000000000 --- a/app/assets/stylesheets/ci/runners.scss +++ /dev/null @@ -1,36 +0,0 @@ -.ci-body { - .runner-state { - padding: 6px 12px; - margin-right: 10px; - color: #FFF; - - &.runner-state-shared { - background: #32b186; - } - &.runner-state-specific { - background: #3498db; - } - } - - .runner-status-online { - color: green; - } - - .runner-status-offline { - color: gray; - } - - .runner-status-paused { - color: red; - } - - .runner { - .btn { - padding: 1px 6px; - } - - h4 { - font-weight: normal; - } - } -} diff --git a/app/assets/stylesheets/ci/status.scss b/app/assets/stylesheets/ci/status.scss deleted file mode 100644 index a7d3b2197f1..00000000000 --- a/app/assets/stylesheets/ci/status.scss +++ /dev/null @@ -1,37 +0,0 @@ -.ci-status { - padding: 2px 7px; - margin-right: 5px; - border: 1px solid #EEE; - white-space: nowrap; - @include border-radius(4px); - - &:hover { - text-decoration: none; - } - - &.ci-failed { - color: $gl-danger; - border-color: $gl-danger; - } - - &.ci-success { - color: $gl-success; - border-color: $gl-success; - } - - &.ci-info { - color: $gl-info; - border-color: $gl-info; - } - - &.ci-disabled { - color: $gl-gray; - border-color: $gl-gray; - } - - &.ci-pending, - &.ci-running { - color: $gl-warning; - border-color: $gl-warning; - } -} diff --git a/app/assets/stylesheets/ci/xterm.scss b/app/assets/stylesheets/ci/xterm.scss deleted file mode 100644 index 9a50096c0d0..00000000000 --- a/app/assets/stylesheets/ci/xterm.scss +++ /dev/null @@ -1,906 +0,0 @@ -.build-page { - // color codes are based on http://en.wikipedia.org/wiki/File:Xterm_256color_chart.svg - // see also: https://gist.github.com/jasonm23/2868981 - - $black: #000000; - $red: #cd0000; - $green: #00cd00; - $yellow: #cdcd00; - $blue: #0000ee; // according to wikipedia, this is the xterm standard - //$blue: #1e90ff; // this is used by all the terminals I tried (when configured with the xterm color profile) - $magenta: #cd00cd; - $cyan: #00cdcd; - $white: #e5e5e5; - $l-black: #7f7f7f; - $l-red: #ff0000; - $l-green: #00ff00; - $l-yellow: #ffff00; - $l-blue: #5c5cff; - $l-magenta: #ff00ff; - $l-cyan: #00ffff; - $l-white: #ffffff; - - .term-bold { - font-weight: bold; - } - .term-italic { - font-style: italic; - } - .term-conceal { - visibility: hidden; - } - .term-underline { - text-decoration: underline; - } - .term-cross { - text-decoration: line-through; - } - - .term-fg-black { - color: $black; - } - .term-fg-red { - color: $red; - } - .term-fg-green { - color: $green; - } - .term-fg-yellow { - color: $yellow; - } - .term-fg-blue { - color: $blue; - } - .term-fg-magenta { - color: $magenta; - } - .term-fg-cyan { - color: $cyan; - } - .term-fg-white { - color: $white; - } - .term-fg-l-black { - color: $l-black; - } - .term-fg-l-red { - color: $l-red; - } - .term-fg-l-green { - color: $l-green; - } - .term-fg-l-yellow { - color: $l-yellow; - } - .term-fg-l-blue { - color: $l-blue; - } - .term-fg-l-magenta { - color: $l-magenta; - } - .term-fg-l-cyan { - color: $l-cyan; - } - .term-fg-l-white { - color: $l-white; - } - - .term-bg-black { - background-color: $black; - } - .term-bg-red { - background-color: $red; - } - .term-bg-green { - background-color: $green; - } - .term-bg-yellow { - background-color: $yellow; - } - .term-bg-blue { - background-color: $blue; - } - .term-bg-magenta { - background-color: $magenta; - } - .term-bg-cyan { - background-color: $cyan; - } - .term-bg-white { - background-color: $white; - } - .term-bg-l-black { - background-color: $l-black; - } - .term-bg-l-red { - background-color: $l-red; - } - .term-bg-l-green { - background-color: $l-green; - } - .term-bg-l-yellow { - background-color: $l-yellow; - } - .term-bg-l-blue { - background-color: $l-blue; - } - .term-bg-l-magenta { - background-color: $l-magenta; - } - .term-bg-l-cyan { - background-color: $l-cyan; - } - .term-bg-l-white { - background-color: $l-white; - } - - - .xterm-fg-0 { - color: #000000; - } - .xterm-fg-1 { - color: #800000; - } - .xterm-fg-2 { - color: #008000; - } - .xterm-fg-3 { - color: #808000; - } - .xterm-fg-4 { - color: #000080; - } - .xterm-fg-5 { - color: #800080; - } - .xterm-fg-6 { - color: #008080; - } - .xterm-fg-7 { - color: #c0c0c0; - } - .xterm-fg-8 { - color: #808080; - } - .xterm-fg-9 { - color: #ff0000; - } - .xterm-fg-10 { - color: #00ff00; - } - .xterm-fg-11 { - color: #ffff00; - } - .xterm-fg-12 { - color: #0000ff; - } - .xterm-fg-13 { - color: #ff00ff; - } - .xterm-fg-14 { - color: #00ffff; - } - .xterm-fg-15 { - color: #ffffff; - } - .xterm-fg-16 { - color: #000000; - } - .xterm-fg-17 { - color: #00005f; - } - .xterm-fg-18 { - color: #000087; - } - .xterm-fg-19 { - color: #0000af; - } - .xterm-fg-20 { - color: #0000d7; - } - .xterm-fg-21 { - color: #0000ff; - } - .xterm-fg-22 { - color: #005f00; - } - .xterm-fg-23 { - color: #005f5f; - } - .xterm-fg-24 { - color: #005f87; - } - .xterm-fg-25 { - color: #005faf; - } - .xterm-fg-26 { - color: #005fd7; - } - .xterm-fg-27 { - color: #005fff; - } - .xterm-fg-28 { - color: #008700; - } - .xterm-fg-29 { - color: #00875f; - } - .xterm-fg-30 { - color: #008787; - } - .xterm-fg-31 { - color: #0087af; - } - .xterm-fg-32 { - color: #0087d7; - } - .xterm-fg-33 { - color: #0087ff; - } - .xterm-fg-34 { - color: #00af00; - } - .xterm-fg-35 { - color: #00af5f; - } - .xterm-fg-36 { - color: #00af87; - } - .xterm-fg-37 { - color: #00afaf; - } - .xterm-fg-38 { - color: #00afd7; - } - .xterm-fg-39 { - color: #00afff; - } - .xterm-fg-40 { - color: #00d700; - } - .xterm-fg-41 { - color: #00d75f; - } - .xterm-fg-42 { - color: #00d787; - } - .xterm-fg-43 { - color: #00d7af; - } - .xterm-fg-44 { - color: #00d7d7; - } - .xterm-fg-45 { - color: #00d7ff; - } - .xterm-fg-46 { - color: #00ff00; - } - .xterm-fg-47 { - color: #00ff5f; - } - .xterm-fg-48 { - color: #00ff87; - } - .xterm-fg-49 { - color: #00ffaf; - } - .xterm-fg-50 { - color: #00ffd7; - } - .xterm-fg-51 { - color: #00ffff; - } - .xterm-fg-52 { - color: #5f0000; - } - .xterm-fg-53 { - color: #5f005f; - } - .xterm-fg-54 { - color: #5f0087; - } - .xterm-fg-55 { - color: #5f00af; - } - .xterm-fg-56 { - color: #5f00d7; - } - .xterm-fg-57 { - color: #5f00ff; - } - .xterm-fg-58 { - color: #5f5f00; - } - .xterm-fg-59 { - color: #5f5f5f; - } - .xterm-fg-60 { - color: #5f5f87; - } - .xterm-fg-61 { - color: #5f5faf; - } - .xterm-fg-62 { - color: #5f5fd7; - } - .xterm-fg-63 { - color: #5f5fff; - } - .xterm-fg-64 { - color: #5f8700; - } - .xterm-fg-65 { - color: #5f875f; - } - .xterm-fg-66 { - color: #5f8787; - } - .xterm-fg-67 { - color: #5f87af; - } - .xterm-fg-68 { - color: #5f87d7; - } - .xterm-fg-69 { - color: #5f87ff; - } - .xterm-fg-70 { - color: #5faf00; - } - .xterm-fg-71 { - color: #5faf5f; - } - .xterm-fg-72 { - color: #5faf87; - } - .xterm-fg-73 { - color: #5fafaf; - } - .xterm-fg-74 { - color: #5fafd7; - } - .xterm-fg-75 { - color: #5fafff; - } - .xterm-fg-76 { - color: #5fd700; - } - .xterm-fg-77 { - color: #5fd75f; - } - .xterm-fg-78 { - color: #5fd787; - } - .xterm-fg-79 { - color: #5fd7af; - } - .xterm-fg-80 { - color: #5fd7d7; - } - .xterm-fg-81 { - color: #5fd7ff; - } - .xterm-fg-82 { - color: #5fff00; - } - .xterm-fg-83 { - color: #5fff5f; - } - .xterm-fg-84 { - color: #5fff87; - } - .xterm-fg-85 { - color: #5fffaf; - } - .xterm-fg-86 { - color: #5fffd7; - } - .xterm-fg-87 { - color: #5fffff; - } - .xterm-fg-88 { - color: #870000; - } - .xterm-fg-89 { - color: #87005f; - } - .xterm-fg-90 { - color: #870087; - } - .xterm-fg-91 { - color: #8700af; - } - .xterm-fg-92 { - color: #8700d7; - } - .xterm-fg-93 { - color: #8700ff; - } - .xterm-fg-94 { - color: #875f00; - } - .xterm-fg-95 { - color: #875f5f; - } - .xterm-fg-96 { - color: #875f87; - } - .xterm-fg-97 { - color: #875faf; - } - .xterm-fg-98 { - color: #875fd7; - } - .xterm-fg-99 { - color: #875fff; - } - .xterm-fg-100 { - color: #878700; - } - .xterm-fg-101 { - color: #87875f; - } - .xterm-fg-102 { - color: #878787; - } - .xterm-fg-103 { - color: #8787af; - } - .xterm-fg-104 { - color: #8787d7; - } - .xterm-fg-105 { - color: #8787ff; - } - .xterm-fg-106 { - color: #87af00; - } - .xterm-fg-107 { - color: #87af5f; - } - .xterm-fg-108 { - color: #87af87; - } - .xterm-fg-109 { - color: #87afaf; - } - .xterm-fg-110 { - color: #87afd7; - } - .xterm-fg-111 { - color: #87afff; - } - .xterm-fg-112 { - color: #87d700; - } - .xterm-fg-113 { - color: #87d75f; - } - .xterm-fg-114 { - color: #87d787; - } - .xterm-fg-115 { - color: #87d7af; - } - .xterm-fg-116 { - color: #87d7d7; - } - .xterm-fg-117 { - color: #87d7ff; - } - .xterm-fg-118 { - color: #87ff00; - } - .xterm-fg-119 { - color: #87ff5f; - } - .xterm-fg-120 { - color: #87ff87; - } - .xterm-fg-121 { - color: #87ffaf; - } - .xterm-fg-122 { - color: #87ffd7; - } - .xterm-fg-123 { - color: #87ffff; - } - .xterm-fg-124 { - color: #af0000; - } - .xterm-fg-125 { - color: #af005f; - } - .xterm-fg-126 { - color: #af0087; - } - .xterm-fg-127 { - color: #af00af; - } - .xterm-fg-128 { - color: #af00d7; - } - .xterm-fg-129 { - color: #af00ff; - } - .xterm-fg-130 { - color: #af5f00; - } - .xterm-fg-131 { - color: #af5f5f; - } - .xterm-fg-132 { - color: #af5f87; - } - .xterm-fg-133 { - color: #af5faf; - } - .xterm-fg-134 { - color: #af5fd7; - } - .xterm-fg-135 { - color: #af5fff; - } - .xterm-fg-136 { - color: #af8700; - } - .xterm-fg-137 { - color: #af875f; - } - .xterm-fg-138 { - color: #af8787; - } - .xterm-fg-139 { - color: #af87af; - } - .xterm-fg-140 { - color: #af87d7; - } - .xterm-fg-141 { - color: #af87ff; - } - .xterm-fg-142 { - color: #afaf00; - } - .xterm-fg-143 { - color: #afaf5f; - } - .xterm-fg-144 { - color: #afaf87; - } - .xterm-fg-145 { - color: #afafaf; - } - .xterm-fg-146 { - color: #afafd7; - } - .xterm-fg-147 { - color: #afafff; - } - .xterm-fg-148 { - color: #afd700; - } - .xterm-fg-149 { - color: #afd75f; - } - .xterm-fg-150 { - color: #afd787; - } - .xterm-fg-151 { - color: #afd7af; - } - .xterm-fg-152 { - color: #afd7d7; - } - .xterm-fg-153 { - color: #afd7ff; - } - .xterm-fg-154 { - color: #afff00; - } - .xterm-fg-155 { - color: #afff5f; - } - .xterm-fg-156 { - color: #afff87; - } - .xterm-fg-157 { - color: #afffaf; - } - .xterm-fg-158 { - color: #afffd7; - } - .xterm-fg-159 { - color: #afffff; - } - .xterm-fg-160 { - color: #d70000; - } - .xterm-fg-161 { - color: #d7005f; - } - .xterm-fg-162 { - color: #d70087; - } - .xterm-fg-163 { - color: #d700af; - } - .xterm-fg-164 { - color: #d700d7; - } - .xterm-fg-165 { - color: #d700ff; - } - .xterm-fg-166 { - color: #d75f00; - } - .xterm-fg-167 { - color: #d75f5f; - } - .xterm-fg-168 { - color: #d75f87; - } - .xterm-fg-169 { - color: #d75faf; - } - .xterm-fg-170 { - color: #d75fd7; - } - .xterm-fg-171 { - color: #d75fff; - } - .xterm-fg-172 { - color: #d78700; - } - .xterm-fg-173 { - color: #d7875f; - } - .xterm-fg-174 { - color: #d78787; - } - .xterm-fg-175 { - color: #d787af; - } - .xterm-fg-176 { - color: #d787d7; - } - .xterm-fg-177 { - color: #d787ff; - } - .xterm-fg-178 { - color: #d7af00; - } - .xterm-fg-179 { - color: #d7af5f; - } - .xterm-fg-180 { - color: #d7af87; - } - .xterm-fg-181 { - color: #d7afaf; - } - .xterm-fg-182 { - color: #d7afd7; - } - .xterm-fg-183 { - color: #d7afff; - } - .xterm-fg-184 { - color: #d7d700; - } - .xterm-fg-185 { - color: #d7d75f; - } - .xterm-fg-186 { - color: #d7d787; - } - .xterm-fg-187 { - color: #d7d7af; - } - .xterm-fg-188 { - color: #d7d7d7; - } - .xterm-fg-189 { - color: #d7d7ff; - } - .xterm-fg-190 { - color: #d7ff00; - } - .xterm-fg-191 { - color: #d7ff5f; - } - .xterm-fg-192 { - color: #d7ff87; - } - .xterm-fg-193 { - color: #d7ffaf; - } - .xterm-fg-194 { - color: #d7ffd7; - } - .xterm-fg-195 { - color: #d7ffff; - } - .xterm-fg-196 { - color: #ff0000; - } - .xterm-fg-197 { - color: #ff005f; - } - .xterm-fg-198 { - color: #ff0087; - } - .xterm-fg-199 { - color: #ff00af; - } - .xterm-fg-200 { - color: #ff00d7; - } - .xterm-fg-201 { - color: #ff00ff; - } - .xterm-fg-202 { - color: #ff5f00; - } - .xterm-fg-203 { - color: #ff5f5f; - } - .xterm-fg-204 { - color: #ff5f87; - } - .xterm-fg-205 { - color: #ff5faf; - } - .xterm-fg-206 { - color: #ff5fd7; - } - .xterm-fg-207 { - color: #ff5fff; - } - .xterm-fg-208 { - color: #ff8700; - } - .xterm-fg-209 { - color: #ff875f; - } - .xterm-fg-210 { - color: #ff8787; - } - .xterm-fg-211 { - color: #ff87af; - } - .xterm-fg-212 { - color: #ff87d7; - } - .xterm-fg-213 { - color: #ff87ff; - } - .xterm-fg-214 { - color: #ffaf00; - } - .xterm-fg-215 { - color: #ffaf5f; - } - .xterm-fg-216 { - color: #ffaf87; - } - .xterm-fg-217 { - color: #ffafaf; - } - .xterm-fg-218 { - color: #ffafd7; - } - .xterm-fg-219 { - color: #ffafff; - } - .xterm-fg-220 { - color: #ffd700; - } - .xterm-fg-221 { - color: #ffd75f; - } - .xterm-fg-222 { - color: #ffd787; - } - .xterm-fg-223 { - color: #ffd7af; - } - .xterm-fg-224 { - color: #ffd7d7; - } - .xterm-fg-225 { - color: #ffd7ff; - } - .xterm-fg-226 { - color: #ffff00; - } - .xterm-fg-227 { - color: #ffff5f; - } - .xterm-fg-228 { - color: #ffff87; - } - .xterm-fg-229 { - color: #ffffaf; - } - .xterm-fg-230 { - color: #ffffd7; - } - .xterm-fg-231 { - color: #ffffff; - } - .xterm-fg-232 { - color: #080808; - } - .xterm-fg-233 { - color: #121212; - } - .xterm-fg-234 { - color: #1c1c1c; - } - .xterm-fg-235 { - color: #262626; - } - .xterm-fg-236 { - color: #303030; - } - .xterm-fg-237 { - color: #3a3a3a; - } - .xterm-fg-238 { - color: #444444; - } - .xterm-fg-239 { - color: #4e4e4e; - } - .xterm-fg-240 { - color: #585858; - } - .xterm-fg-241 { - color: #626262; - } - .xterm-fg-242 { - color: #6c6c6c; - } - .xterm-fg-243 { - color: #767676; - } - .xterm-fg-244 { - color: #808080; - } - .xterm-fg-245 { - color: #8a8a8a; - } - .xterm-fg-246 { - color: #949494; - } - .xterm-fg-247 { - color: #9e9e9e; - } - .xterm-fg-248 { - color: #a8a8a8; - } - .xterm-fg-249 { - color: #b2b2b2; - } - .xterm-fg-250 { - color: #bcbcbc; - } - .xterm-fg-251 { - color: #c6c6c6; - } - .xterm-fg-252 { - color: #d0d0d0; - } - .xterm-fg-253 { - color: #dadada; - } - .xterm-fg-254 { - color: #e4e4e4; - } - .xterm-fg-255 { - color: #eeeeee; - } -} diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss new file mode 100644 index 00000000000..74dc3e321c1 --- /dev/null +++ b/app/assets/stylesheets/pages/builds.scss @@ -0,0 +1,75 @@ +.build-page { + pre.trace { + background: #111111; + color: #fff; + font-family: $monospace_font; + white-space: pre; + white-space: pre-wrap; /* css-3 */ + white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + word-wrap: break-word; /* Internet Explorer 5.5+ */ + overflow: auto; + overflow-y: hidden; + font-size: 12px; + + .fa-refresh { + font-size: 24px; + margin-left: 20px; + } + } + + .autoscroll-container { + position: fixed; + bottom: 10px; + right: 20px; + z-index: 100; + } + + .scroll-controls { + position: fixed; + bottom: 10px; + left: 250px; + z-index: 100; + + a { + display: block; + margin-bottom: 5px; + } + } + + .page-sidebar-collapsed { + .scroll-controls { + left: 70px; + } + } + + .build-widget { + padding: 10px; + background: $background-color; + margin-bottom: 20px; + border-radius: 4px; + + .title { + margin-top: 0; + color: #666; + line-height: 1.5; + } + .attr-name { + color: #777; + } + } + + .alert-disabled { + background: $background-color; + + a { + color: #3084bb !important; + } + } + + .build-top-menu { + margin-top: 0; + margin-bottom: 2px; + } +} diff --git a/app/assets/stylesheets/pages/ci_projects.scss b/app/assets/stylesheets/pages/ci_projects.scss new file mode 100644 index 00000000000..8c5273abcda --- /dev/null +++ b/app/assets/stylesheets/pages/ci_projects.scss @@ -0,0 +1,59 @@ +.ci-body { + .project-title { + margin: 0; + color: #444; + font-size: 20px; + line-height: 1.5; + } + + .wide-table-holder { + margin-left: -$gl-padding; + margin-right: -$gl-padding; + } + + .builds, + .projects-table { + .light { + border-color: $border-color; + } + + th, td { + padding: 10px $gl-padding; + } + + td { + color: $gl-gray; + vertical-align: middle !important; + + a { + font-weight: normal; + text-decoration: none; + } + } + } + + .commit-info { + .attr-name { + margin-right: 5px; + } + + pre.commit-message { + background: none; + padding: 0; + margin: 0; + border: none; + margin: 20px 0; + border-radius: 0; + } + } + + .loading{ + font-size: 20px; + } + + .ci-charts { + fieldset { + margin-bottom: 16px; + } + } +} diff --git a/app/assets/stylesheets/pages/lint.scss b/app/assets/stylesheets/pages/lint.scss new file mode 100644 index 00000000000..6d2bd33b28b --- /dev/null +++ b/app/assets/stylesheets/pages/lint.scss @@ -0,0 +1,10 @@ +.ci-body { + .incorrect-syntax{ + font-size: 19px; + color: red; + } + .correct-syntax{ + font-size: 19px; + color: #47a447; + } +} diff --git a/app/assets/stylesheets/pages/runners.scss b/app/assets/stylesheets/pages/runners.scss new file mode 100644 index 00000000000..2b15ab83129 --- /dev/null +++ b/app/assets/stylesheets/pages/runners.scss @@ -0,0 +1,36 @@ +.ci-body { + .runner-state { + padding: 6px 12px; + margin-right: 10px; + color: #FFF; + + &.runner-state-shared { + background: #32b186; + } + &.runner-state-specific { + background: #3498db; + } + } + + .runner-status-online { + color: green; + } + + .runner-status-offline { + color: gray; + } + + .runner-status-paused { + color: red; + } + + .runner { + .btn { + padding: 1px 6px; + } + + h4 { + font-weight: normal; + } + } +} diff --git a/app/assets/stylesheets/pages/status.scss b/app/assets/stylesheets/pages/status.scss new file mode 100644 index 00000000000..a7d3b2197f1 --- /dev/null +++ b/app/assets/stylesheets/pages/status.scss @@ -0,0 +1,37 @@ +.ci-status { + padding: 2px 7px; + margin-right: 5px; + border: 1px solid #EEE; + white-space: nowrap; + @include border-radius(4px); + + &:hover { + text-decoration: none; + } + + &.ci-failed { + color: $gl-danger; + border-color: $gl-danger; + } + + &.ci-success { + color: $gl-success; + border-color: $gl-success; + } + + &.ci-info { + color: $gl-info; + border-color: $gl-info; + } + + &.ci-disabled { + color: $gl-gray; + border-color: $gl-gray; + } + + &.ci-pending, + &.ci-running { + color: $gl-warning; + border-color: $gl-warning; + } +} diff --git a/app/assets/stylesheets/pages/xterm.scss b/app/assets/stylesheets/pages/xterm.scss new file mode 100644 index 00000000000..9a50096c0d0 --- /dev/null +++ b/app/assets/stylesheets/pages/xterm.scss @@ -0,0 +1,906 @@ +.build-page { + // color codes are based on http://en.wikipedia.org/wiki/File:Xterm_256color_chart.svg + // see also: https://gist.github.com/jasonm23/2868981 + + $black: #000000; + $red: #cd0000; + $green: #00cd00; + $yellow: #cdcd00; + $blue: #0000ee; // according to wikipedia, this is the xterm standard + //$blue: #1e90ff; // this is used by all the terminals I tried (when configured with the xterm color profile) + $magenta: #cd00cd; + $cyan: #00cdcd; + $white: #e5e5e5; + $l-black: #7f7f7f; + $l-red: #ff0000; + $l-green: #00ff00; + $l-yellow: #ffff00; + $l-blue: #5c5cff; + $l-magenta: #ff00ff; + $l-cyan: #00ffff; + $l-white: #ffffff; + + .term-bold { + font-weight: bold; + } + .term-italic { + font-style: italic; + } + .term-conceal { + visibility: hidden; + } + .term-underline { + text-decoration: underline; + } + .term-cross { + text-decoration: line-through; + } + + .term-fg-black { + color: $black; + } + .term-fg-red { + color: $red; + } + .term-fg-green { + color: $green; + } + .term-fg-yellow { + color: $yellow; + } + .term-fg-blue { + color: $blue; + } + .term-fg-magenta { + color: $magenta; + } + .term-fg-cyan { + color: $cyan; + } + .term-fg-white { + color: $white; + } + .term-fg-l-black { + color: $l-black; + } + .term-fg-l-red { + color: $l-red; + } + .term-fg-l-green { + color: $l-green; + } + .term-fg-l-yellow { + color: $l-yellow; + } + .term-fg-l-blue { + color: $l-blue; + } + .term-fg-l-magenta { + color: $l-magenta; + } + .term-fg-l-cyan { + color: $l-cyan; + } + .term-fg-l-white { + color: $l-white; + } + + .term-bg-black { + background-color: $black; + } + .term-bg-red { + background-color: $red; + } + .term-bg-green { + background-color: $green; + } + .term-bg-yellow { + background-color: $yellow; + } + .term-bg-blue { + background-color: $blue; + } + .term-bg-magenta { + background-color: $magenta; + } + .term-bg-cyan { + background-color: $cyan; + } + .term-bg-white { + background-color: $white; + } + .term-bg-l-black { + background-color: $l-black; + } + .term-bg-l-red { + background-color: $l-red; + } + .term-bg-l-green { + background-color: $l-green; + } + .term-bg-l-yellow { + background-color: $l-yellow; + } + .term-bg-l-blue { + background-color: $l-blue; + } + .term-bg-l-magenta { + background-color: $l-magenta; + } + .term-bg-l-cyan { + background-color: $l-cyan; + } + .term-bg-l-white { + background-color: $l-white; + } + + + .xterm-fg-0 { + color: #000000; + } + .xterm-fg-1 { + color: #800000; + } + .xterm-fg-2 { + color: #008000; + } + .xterm-fg-3 { + color: #808000; + } + .xterm-fg-4 { + color: #000080; + } + .xterm-fg-5 { + color: #800080; + } + .xterm-fg-6 { + color: #008080; + } + .xterm-fg-7 { + color: #c0c0c0; + } + .xterm-fg-8 { + color: #808080; + } + .xterm-fg-9 { + color: #ff0000; + } + .xterm-fg-10 { + color: #00ff00; + } + .xterm-fg-11 { + color: #ffff00; + } + .xterm-fg-12 { + color: #0000ff; + } + .xterm-fg-13 { + color: #ff00ff; + } + .xterm-fg-14 { + color: #00ffff; + } + .xterm-fg-15 { + color: #ffffff; + } + .xterm-fg-16 { + color: #000000; + } + .xterm-fg-17 { + color: #00005f; + } + .xterm-fg-18 { + color: #000087; + } + .xterm-fg-19 { + color: #0000af; + } + .xterm-fg-20 { + color: #0000d7; + } + .xterm-fg-21 { + color: #0000ff; + } + .xterm-fg-22 { + color: #005f00; + } + .xterm-fg-23 { + color: #005f5f; + } + .xterm-fg-24 { + color: #005f87; + } + .xterm-fg-25 { + color: #005faf; + } + .xterm-fg-26 { + color: #005fd7; + } + .xterm-fg-27 { + color: #005fff; + } + .xterm-fg-28 { + color: #008700; + } + .xterm-fg-29 { + color: #00875f; + } + .xterm-fg-30 { + color: #008787; + } + .xterm-fg-31 { + color: #0087af; + } + .xterm-fg-32 { + color: #0087d7; + } + .xterm-fg-33 { + color: #0087ff; + } + .xterm-fg-34 { + color: #00af00; + } + .xterm-fg-35 { + color: #00af5f; + } + .xterm-fg-36 { + color: #00af87; + } + .xterm-fg-37 { + color: #00afaf; + } + .xterm-fg-38 { + color: #00afd7; + } + .xterm-fg-39 { + color: #00afff; + } + .xterm-fg-40 { + color: #00d700; + } + .xterm-fg-41 { + color: #00d75f; + } + .xterm-fg-42 { + color: #00d787; + } + .xterm-fg-43 { + color: #00d7af; + } + .xterm-fg-44 { + color: #00d7d7; + } + .xterm-fg-45 { + color: #00d7ff; + } + .xterm-fg-46 { + color: #00ff00; + } + .xterm-fg-47 { + color: #00ff5f; + } + .xterm-fg-48 { + color: #00ff87; + } + .xterm-fg-49 { + color: #00ffaf; + } + .xterm-fg-50 { + color: #00ffd7; + } + .xterm-fg-51 { + color: #00ffff; + } + .xterm-fg-52 { + color: #5f0000; + } + .xterm-fg-53 { + color: #5f005f; + } + .xterm-fg-54 { + color: #5f0087; + } + .xterm-fg-55 { + color: #5f00af; + } + .xterm-fg-56 { + color: #5f00d7; + } + .xterm-fg-57 { + color: #5f00ff; + } + .xterm-fg-58 { + color: #5f5f00; + } + .xterm-fg-59 { + color: #5f5f5f; + } + .xterm-fg-60 { + color: #5f5f87; + } + .xterm-fg-61 { + color: #5f5faf; + } + .xterm-fg-62 { + color: #5f5fd7; + } + .xterm-fg-63 { + color: #5f5fff; + } + .xterm-fg-64 { + color: #5f8700; + } + .xterm-fg-65 { + color: #5f875f; + } + .xterm-fg-66 { + color: #5f8787; + } + .xterm-fg-67 { + color: #5f87af; + } + .xterm-fg-68 { + color: #5f87d7; + } + .xterm-fg-69 { + color: #5f87ff; + } + .xterm-fg-70 { + color: #5faf00; + } + .xterm-fg-71 { + color: #5faf5f; + } + .xterm-fg-72 { + color: #5faf87; + } + .xterm-fg-73 { + color: #5fafaf; + } + .xterm-fg-74 { + color: #5fafd7; + } + .xterm-fg-75 { + color: #5fafff; + } + .xterm-fg-76 { + color: #5fd700; + } + .xterm-fg-77 { + color: #5fd75f; + } + .xterm-fg-78 { + color: #5fd787; + } + .xterm-fg-79 { + color: #5fd7af; + } + .xterm-fg-80 { + color: #5fd7d7; + } + .xterm-fg-81 { + color: #5fd7ff; + } + .xterm-fg-82 { + color: #5fff00; + } + .xterm-fg-83 { + color: #5fff5f; + } + .xterm-fg-84 { + color: #5fff87; + } + .xterm-fg-85 { + color: #5fffaf; + } + .xterm-fg-86 { + color: #5fffd7; + } + .xterm-fg-87 { + color: #5fffff; + } + .xterm-fg-88 { + color: #870000; + } + .xterm-fg-89 { + color: #87005f; + } + .xterm-fg-90 { + color: #870087; + } + .xterm-fg-91 { + color: #8700af; + } + .xterm-fg-92 { + color: #8700d7; + } + .xterm-fg-93 { + color: #8700ff; + } + .xterm-fg-94 { + color: #875f00; + } + .xterm-fg-95 { + color: #875f5f; + } + .xterm-fg-96 { + color: #875f87; + } + .xterm-fg-97 { + color: #875faf; + } + .xterm-fg-98 { + color: #875fd7; + } + .xterm-fg-99 { + color: #875fff; + } + .xterm-fg-100 { + color: #878700; + } + .xterm-fg-101 { + color: #87875f; + } + .xterm-fg-102 { + color: #878787; + } + .xterm-fg-103 { + color: #8787af; + } + .xterm-fg-104 { + color: #8787d7; + } + .xterm-fg-105 { + color: #8787ff; + } + .xterm-fg-106 { + color: #87af00; + } + .xterm-fg-107 { + color: #87af5f; + } + .xterm-fg-108 { + color: #87af87; + } + .xterm-fg-109 { + color: #87afaf; + } + .xterm-fg-110 { + color: #87afd7; + } + .xterm-fg-111 { + color: #87afff; + } + .xterm-fg-112 { + color: #87d700; + } + .xterm-fg-113 { + color: #87d75f; + } + .xterm-fg-114 { + color: #87d787; + } + .xterm-fg-115 { + color: #87d7af; + } + .xterm-fg-116 { + color: #87d7d7; + } + .xterm-fg-117 { + color: #87d7ff; + } + .xterm-fg-118 { + color: #87ff00; + } + .xterm-fg-119 { + color: #87ff5f; + } + .xterm-fg-120 { + color: #87ff87; + } + .xterm-fg-121 { + color: #87ffaf; + } + .xterm-fg-122 { + color: #87ffd7; + } + .xterm-fg-123 { + color: #87ffff; + } + .xterm-fg-124 { + color: #af0000; + } + .xterm-fg-125 { + color: #af005f; + } + .xterm-fg-126 { + color: #af0087; + } + .xterm-fg-127 { + color: #af00af; + } + .xterm-fg-128 { + color: #af00d7; + } + .xterm-fg-129 { + color: #af00ff; + } + .xterm-fg-130 { + color: #af5f00; + } + .xterm-fg-131 { + color: #af5f5f; + } + .xterm-fg-132 { + color: #af5f87; + } + .xterm-fg-133 { + color: #af5faf; + } + .xterm-fg-134 { + color: #af5fd7; + } + .xterm-fg-135 { + color: #af5fff; + } + .xterm-fg-136 { + color: #af8700; + } + .xterm-fg-137 { + color: #af875f; + } + .xterm-fg-138 { + color: #af8787; + } + .xterm-fg-139 { + color: #af87af; + } + .xterm-fg-140 { + color: #af87d7; + } + .xterm-fg-141 { + color: #af87ff; + } + .xterm-fg-142 { + color: #afaf00; + } + .xterm-fg-143 { + color: #afaf5f; + } + .xterm-fg-144 { + color: #afaf87; + } + .xterm-fg-145 { + color: #afafaf; + } + .xterm-fg-146 { + color: #afafd7; + } + .xterm-fg-147 { + color: #afafff; + } + .xterm-fg-148 { + color: #afd700; + } + .xterm-fg-149 { + color: #afd75f; + } + .xterm-fg-150 { + color: #afd787; + } + .xterm-fg-151 { + color: #afd7af; + } + .xterm-fg-152 { + color: #afd7d7; + } + .xterm-fg-153 { + color: #afd7ff; + } + .xterm-fg-154 { + color: #afff00; + } + .xterm-fg-155 { + color: #afff5f; + } + .xterm-fg-156 { + color: #afff87; + } + .xterm-fg-157 { + color: #afffaf; + } + .xterm-fg-158 { + color: #afffd7; + } + .xterm-fg-159 { + color: #afffff; + } + .xterm-fg-160 { + color: #d70000; + } + .xterm-fg-161 { + color: #d7005f; + } + .xterm-fg-162 { + color: #d70087; + } + .xterm-fg-163 { + color: #d700af; + } + .xterm-fg-164 { + color: #d700d7; + } + .xterm-fg-165 { + color: #d700ff; + } + .xterm-fg-166 { + color: #d75f00; + } + .xterm-fg-167 { + color: #d75f5f; + } + .xterm-fg-168 { + color: #d75f87; + } + .xterm-fg-169 { + color: #d75faf; + } + .xterm-fg-170 { + color: #d75fd7; + } + .xterm-fg-171 { + color: #d75fff; + } + .xterm-fg-172 { + color: #d78700; + } + .xterm-fg-173 { + color: #d7875f; + } + .xterm-fg-174 { + color: #d78787; + } + .xterm-fg-175 { + color: #d787af; + } + .xterm-fg-176 { + color: #d787d7; + } + .xterm-fg-177 { + color: #d787ff; + } + .xterm-fg-178 { + color: #d7af00; + } + .xterm-fg-179 { + color: #d7af5f; + } + .xterm-fg-180 { + color: #d7af87; + } + .xterm-fg-181 { + color: #d7afaf; + } + .xterm-fg-182 { + color: #d7afd7; + } + .xterm-fg-183 { + color: #d7afff; + } + .xterm-fg-184 { + color: #d7d700; + } + .xterm-fg-185 { + color: #d7d75f; + } + .xterm-fg-186 { + color: #d7d787; + } + .xterm-fg-187 { + color: #d7d7af; + } + .xterm-fg-188 { + color: #d7d7d7; + } + .xterm-fg-189 { + color: #d7d7ff; + } + .xterm-fg-190 { + color: #d7ff00; + } + .xterm-fg-191 { + color: #d7ff5f; + } + .xterm-fg-192 { + color: #d7ff87; + } + .xterm-fg-193 { + color: #d7ffaf; + } + .xterm-fg-194 { + color: #d7ffd7; + } + .xterm-fg-195 { + color: #d7ffff; + } + .xterm-fg-196 { + color: #ff0000; + } + .xterm-fg-197 { + color: #ff005f; + } + .xterm-fg-198 { + color: #ff0087; + } + .xterm-fg-199 { + color: #ff00af; + } + .xterm-fg-200 { + color: #ff00d7; + } + .xterm-fg-201 { + color: #ff00ff; + } + .xterm-fg-202 { + color: #ff5f00; + } + .xterm-fg-203 { + color: #ff5f5f; + } + .xterm-fg-204 { + color: #ff5f87; + } + .xterm-fg-205 { + color: #ff5faf; + } + .xterm-fg-206 { + color: #ff5fd7; + } + .xterm-fg-207 { + color: #ff5fff; + } + .xterm-fg-208 { + color: #ff8700; + } + .xterm-fg-209 { + color: #ff875f; + } + .xterm-fg-210 { + color: #ff8787; + } + .xterm-fg-211 { + color: #ff87af; + } + .xterm-fg-212 { + color: #ff87d7; + } + .xterm-fg-213 { + color: #ff87ff; + } + .xterm-fg-214 { + color: #ffaf00; + } + .xterm-fg-215 { + color: #ffaf5f; + } + .xterm-fg-216 { + color: #ffaf87; + } + .xterm-fg-217 { + color: #ffafaf; + } + .xterm-fg-218 { + color: #ffafd7; + } + .xterm-fg-219 { + color: #ffafff; + } + .xterm-fg-220 { + color: #ffd700; + } + .xterm-fg-221 { + color: #ffd75f; + } + .xterm-fg-222 { + color: #ffd787; + } + .xterm-fg-223 { + color: #ffd7af; + } + .xterm-fg-224 { + color: #ffd7d7; + } + .xterm-fg-225 { + color: #ffd7ff; + } + .xterm-fg-226 { + color: #ffff00; + } + .xterm-fg-227 { + color: #ffff5f; + } + .xterm-fg-228 { + color: #ffff87; + } + .xterm-fg-229 { + color: #ffffaf; + } + .xterm-fg-230 { + color: #ffffd7; + } + .xterm-fg-231 { + color: #ffffff; + } + .xterm-fg-232 { + color: #080808; + } + .xterm-fg-233 { + color: #121212; + } + .xterm-fg-234 { + color: #1c1c1c; + } + .xterm-fg-235 { + color: #262626; + } + .xterm-fg-236 { + color: #303030; + } + .xterm-fg-237 { + color: #3a3a3a; + } + .xterm-fg-238 { + color: #444444; + } + .xterm-fg-239 { + color: #4e4e4e; + } + .xterm-fg-240 { + color: #585858; + } + .xterm-fg-241 { + color: #626262; + } + .xterm-fg-242 { + color: #6c6c6c; + } + .xterm-fg-243 { + color: #767676; + } + .xterm-fg-244 { + color: #808080; + } + .xterm-fg-245 { + color: #8a8a8a; + } + .xterm-fg-246 { + color: #949494; + } + .xterm-fg-247 { + color: #9e9e9e; + } + .xterm-fg-248 { + color: #a8a8a8; + } + .xterm-fg-249 { + color: #b2b2b2; + } + .xterm-fg-250 { + color: #bcbcbc; + } + .xterm-fg-251 { + color: #c6c6c6; + } + .xterm-fg-252 { + color: #d0d0d0; + } + .xterm-fg-253 { + color: #dadada; + } + .xterm-fg-254 { + color: #e4e4e4; + } + .xterm-fg-255 { + color: #eeeeee; + } +} -- cgit v1.2.1 From bdd477a0f800328a527f2fad92d1303441689341 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 12 Oct 2015 15:00:04 +0200 Subject: Re-organize GitLab css into 2 directories: framework and page specific css Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/application.scss | 30 +- app/assets/stylesheets/base/fonts.scss | 25 -- app/assets/stylesheets/base/gl_bootstrap.scss | 273 -------------- app/assets/stylesheets/base/gl_variables.scss | 158 -------- app/assets/stylesheets/base/layout.scss | 27 -- app/assets/stylesheets/base/mixins.scss | 301 --------------- app/assets/stylesheets/base/variables.scss | 98 ----- app/assets/stylesheets/framework.scss | 32 ++ app/assets/stylesheets/framework/avatar.scss | 49 +++ app/assets/stylesheets/framework/blocks.scss | 62 ++++ app/assets/stylesheets/framework/buttons.scss | 163 +++++++++ app/assets/stylesheets/framework/calendar.scss | 90 +++++ app/assets/stylesheets/framework/callout.scss | 45 +++ app/assets/stylesheets/framework/common.scss | 404 +++++++++++++++++++++ app/assets/stylesheets/framework/files.scss | 171 +++++++++ app/assets/stylesheets/framework/filters.scss | 30 ++ app/assets/stylesheets/framework/flash.scss | 17 + app/assets/stylesheets/framework/fonts.scss | 25 ++ app/assets/stylesheets/framework/forms.scss | 94 +++++ app/assets/stylesheets/framework/gfm.scss | 25 ++ app/assets/stylesheets/framework/gitlab-theme.scss | 120 ++++++ app/assets/stylesheets/framework/gl_bootstrap.scss | 273 ++++++++++++++ app/assets/stylesheets/framework/gl_variables.scss | 158 ++++++++ app/assets/stylesheets/framework/header.scss | 169 +++++++++ app/assets/stylesheets/framework/highlight.scss | 70 ++++ app/assets/stylesheets/framework/issue_box.scss | 35 ++ app/assets/stylesheets/framework/jquery.scss | 55 +++ app/assets/stylesheets/framework/layout.scss | 27 ++ app/assets/stylesheets/framework/lists.scss | 125 +++++++ .../stylesheets/framework/markdown_area.scss | 115 ++++++ app/assets/stylesheets/framework/mixins.scss | 301 +++++++++++++++ app/assets/stylesheets/framework/mobile.scss | 139 +++++++ app/assets/stylesheets/framework/pagination.scss | 34 ++ app/assets/stylesheets/framework/selects.scss | 146 ++++++++ app/assets/stylesheets/framework/sidebar.scss | 267 ++++++++++++++ app/assets/stylesheets/framework/tables.scss | 20 + app/assets/stylesheets/framework/timeline.scss | 70 ++++ app/assets/stylesheets/framework/typography.scss | 130 +++++++ app/assets/stylesheets/framework/variables.scss | 98 +++++ app/assets/stylesheets/framework/zen.scss | 86 +++++ app/assets/stylesheets/generic/avatar.scss | 49 --- app/assets/stylesheets/generic/blocks.scss | 62 ---- app/assets/stylesheets/generic/buttons.scss | 163 --------- app/assets/stylesheets/generic/calendar.scss | 90 ----- app/assets/stylesheets/generic/callout.scss | 45 --- app/assets/stylesheets/generic/common.scss | 404 --------------------- app/assets/stylesheets/generic/files.scss | 171 --------- app/assets/stylesheets/generic/filters.scss | 30 -- app/assets/stylesheets/generic/flash.scss | 17 - app/assets/stylesheets/generic/forms.scss | 94 ----- app/assets/stylesheets/generic/gfm.scss | 25 -- app/assets/stylesheets/generic/header.scss | 169 --------- app/assets/stylesheets/generic/highlight.scss | 70 ---- app/assets/stylesheets/generic/issue_box.scss | 35 -- app/assets/stylesheets/generic/jquery.scss | 55 --- app/assets/stylesheets/generic/lists.scss | 125 ------- app/assets/stylesheets/generic/markdown_area.scss | 115 ------ app/assets/stylesheets/generic/mobile.scss | 139 ------- app/assets/stylesheets/generic/pagination.scss | 34 -- app/assets/stylesheets/generic/selects.scss | 146 -------- app/assets/stylesheets/generic/sidebar.scss | 267 -------------- app/assets/stylesheets/generic/tables.scss | 20 - app/assets/stylesheets/generic/timeline.scss | 70 ---- app/assets/stylesheets/generic/typography.scss | 130 ------- app/assets/stylesheets/generic/zen.scss | 86 ----- app/assets/stylesheets/themes/gitlab-theme.scss | 120 ------ 66 files changed, 3647 insertions(+), 3641 deletions(-) delete mode 100644 app/assets/stylesheets/base/fonts.scss delete mode 100644 app/assets/stylesheets/base/gl_bootstrap.scss delete mode 100644 app/assets/stylesheets/base/gl_variables.scss delete mode 100644 app/assets/stylesheets/base/layout.scss delete mode 100644 app/assets/stylesheets/base/mixins.scss delete mode 100644 app/assets/stylesheets/base/variables.scss create mode 100644 app/assets/stylesheets/framework.scss create mode 100644 app/assets/stylesheets/framework/avatar.scss create mode 100644 app/assets/stylesheets/framework/blocks.scss create mode 100644 app/assets/stylesheets/framework/buttons.scss create mode 100644 app/assets/stylesheets/framework/calendar.scss create mode 100644 app/assets/stylesheets/framework/callout.scss create mode 100644 app/assets/stylesheets/framework/common.scss create mode 100644 app/assets/stylesheets/framework/files.scss create mode 100644 app/assets/stylesheets/framework/filters.scss create mode 100644 app/assets/stylesheets/framework/flash.scss create mode 100644 app/assets/stylesheets/framework/fonts.scss create mode 100644 app/assets/stylesheets/framework/forms.scss create mode 100644 app/assets/stylesheets/framework/gfm.scss create mode 100644 app/assets/stylesheets/framework/gitlab-theme.scss create mode 100644 app/assets/stylesheets/framework/gl_bootstrap.scss create mode 100644 app/assets/stylesheets/framework/gl_variables.scss create mode 100644 app/assets/stylesheets/framework/header.scss create mode 100644 app/assets/stylesheets/framework/highlight.scss create mode 100644 app/assets/stylesheets/framework/issue_box.scss create mode 100644 app/assets/stylesheets/framework/jquery.scss create mode 100644 app/assets/stylesheets/framework/layout.scss create mode 100644 app/assets/stylesheets/framework/lists.scss create mode 100644 app/assets/stylesheets/framework/markdown_area.scss create mode 100644 app/assets/stylesheets/framework/mixins.scss create mode 100644 app/assets/stylesheets/framework/mobile.scss create mode 100644 app/assets/stylesheets/framework/pagination.scss create mode 100644 app/assets/stylesheets/framework/selects.scss create mode 100644 app/assets/stylesheets/framework/sidebar.scss create mode 100644 app/assets/stylesheets/framework/tables.scss create mode 100644 app/assets/stylesheets/framework/timeline.scss create mode 100644 app/assets/stylesheets/framework/typography.scss create mode 100644 app/assets/stylesheets/framework/variables.scss create mode 100644 app/assets/stylesheets/framework/zen.scss delete mode 100644 app/assets/stylesheets/generic/avatar.scss delete mode 100644 app/assets/stylesheets/generic/blocks.scss delete mode 100644 app/assets/stylesheets/generic/buttons.scss delete mode 100644 app/assets/stylesheets/generic/calendar.scss delete mode 100644 app/assets/stylesheets/generic/callout.scss delete mode 100644 app/assets/stylesheets/generic/common.scss delete mode 100644 app/assets/stylesheets/generic/files.scss delete mode 100644 app/assets/stylesheets/generic/filters.scss delete mode 100644 app/assets/stylesheets/generic/flash.scss delete mode 100644 app/assets/stylesheets/generic/forms.scss delete mode 100644 app/assets/stylesheets/generic/gfm.scss delete mode 100644 app/assets/stylesheets/generic/header.scss delete mode 100644 app/assets/stylesheets/generic/highlight.scss delete mode 100644 app/assets/stylesheets/generic/issue_box.scss delete mode 100644 app/assets/stylesheets/generic/jquery.scss delete mode 100644 app/assets/stylesheets/generic/lists.scss delete mode 100644 app/assets/stylesheets/generic/markdown_area.scss delete mode 100644 app/assets/stylesheets/generic/mobile.scss delete mode 100644 app/assets/stylesheets/generic/pagination.scss delete mode 100644 app/assets/stylesheets/generic/selects.scss delete mode 100644 app/assets/stylesheets/generic/sidebar.scss delete mode 100644 app/assets/stylesheets/generic/tables.scss delete mode 100644 app/assets/stylesheets/generic/timeline.scss delete mode 100644 app/assets/stylesheets/generic/typography.scss delete mode 100644 app/assets/stylesheets/generic/zen.scss delete mode 100644 app/assets/stylesheets/themes/gitlab-theme.scss diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index d9ede637944..233e01cc06b 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -11,18 +11,10 @@ *= require cal-heatmap */ - -@import "base/fonts"; -@import "base/variables"; -@import "base/mixins"; -@import "base/layout"; - - /** - * Customized Twitter bootstrap + * GitLab UI framework */ -@import 'base/gl_variables'; -@import 'base/gl_bootstrap'; +@import "framework"; /** * NProgress load bar css @@ -32,24 +24,12 @@ /** * Font icons - * */ @import "font-awesome"; -/** - * UI themes: - */ -@import "themes/**/*"; - -/** - * Generic css (forms, nav etc): - */ -@import "generic/**/*"; - /** * Page specific styles (issues, projects etc): */ - @import "pages/**/*"; /** @@ -61,9 +41,3 @@ * Styles for JS behaviors. */ @import "behaviors.scss"; - -/** - * CI specific styles: - */ -@import "ci/**/*"; - diff --git a/app/assets/stylesheets/base/fonts.scss b/app/assets/stylesheets/base/fonts.scss deleted file mode 100644 index e214567eca1..00000000000 --- a/app/assets/stylesheets/base/fonts.scss +++ /dev/null @@ -1,25 +0,0 @@ -/* latin-ext */ -@font-face { - font-family: 'Source Sans Pro'; - font-style: normal; - font-weight: 300; - src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), font-url('SourceSansPro-Light.ttf'); -} -@font-face { - font-family: 'Source Sans Pro'; - font-style: normal; - font-weight: 400; - src: local('Source Sans Pro'), local('SourceSansPro-Regular'), font-url('SourceSansPro-Regular.ttf'); -} -@font-face { - font-family: 'Source Sans Pro'; - font-style: normal; - font-weight: 600; - src: local('Source Sans Pro Semibold'), local('SourceSansPro-Semibold'), font-url('SourceSansPro-Semibold.ttf'); -} -@font-face { - font-family: 'Source Sans Pro'; - font-style: normal; - font-weight: 700; - src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'), font-url('SourceSansPro-Bold.ttf'); -} diff --git a/app/assets/stylesheets/base/gl_bootstrap.scss b/app/assets/stylesheets/base/gl_bootstrap.scss deleted file mode 100644 index eb8d23d6453..00000000000 --- a/app/assets/stylesheets/base/gl_bootstrap.scss +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Twitter bootstrap with GitLab customizations/additions - * - */ - -// Core variables and mixins -@import "bootstrap/variables"; -@import "bootstrap/mixins"; - -// Reset -@import "bootstrap/normalize"; -@import "bootstrap/print"; - -// Core CSS -@import "bootstrap/scaffolding"; -@import "bootstrap/type"; -@import "bootstrap/code"; -@import "bootstrap/grid"; -@import "bootstrap/tables"; -@import "bootstrap/forms"; -@import "bootstrap/buttons"; - -// Components -@import "bootstrap/component-animations"; -@import "bootstrap/dropdowns"; -@import "bootstrap/button-groups"; -@import "bootstrap/input-groups"; -@import "bootstrap/navs"; -@import "bootstrap/navbar"; -@import "bootstrap/breadcrumbs"; -@import "bootstrap/pagination"; -@import "bootstrap/pager"; -@import "bootstrap/labels"; -@import "bootstrap/badges"; -@import "bootstrap/jumbotron"; -@import "bootstrap/thumbnails"; -@import "bootstrap/alerts"; -@import "bootstrap/progress-bars"; -@import "bootstrap/list-group"; -@import "bootstrap/wells"; -@import "bootstrap/close"; -@import "bootstrap/panels"; - -// Components w/ JavaScript -@import "bootstrap/modals"; -@import "bootstrap/tooltip"; -@import "bootstrap/popovers"; -@import "bootstrap/carousel"; - -// Utility classes -.clearfix { - @include clearfix(); -} -.center-block { - @include center-block(); -} -.pull-right { - float: right !important; -} -.pull-left { - float: left !important; -} -.hide { - display: none; -} -.show { - display: block !important; -} -.invisible { - visibility: hidden; -} -.text-hide { - @include text-hide(); -} -.hidden { - display: none !important; - visibility: hidden !important; -} -.affix { - position: fixed; -} - -@import "bootstrap/responsive-utilities"; - -// Labels -.label { - padding: 2px 4px; - font-size: 13px; - font-style: normal; - font-weight: normal; - display: inline-block; - - &.label-gray { - background-color: #f8fafc; - color: $gl-gray; - text-shadow: none; - } - - &.label-inverse { - background-color: #333333; - } -} - -// Nav tabs -.nav.nav-tabs { - margin-bottom: 15px; - - li { - > a { - margin-right: 5px; - line-height: 20px; - border-color: #EEE; - color: #888; - border-bottom: 1px solid #ddd; - .badge { - background-color: #eee; - color: #888; - text-shadow: 0 1px 1px #fff; - } - i.fa { - line-height: 14px; - } - } - &.active { - > a { - border-color: #CCC; - border-bottom: 1px solid #fff; - color: #333; - font-weight: bold; - } - } - } -} - -.nav-tabs > li > a, -.nav-pills > li > a { - color: #666; -} - -.nav-pills > .active > a > span > .badge { - background-color: #fff; - color: $gl-primary; -} - - -/** - * fix to keep tooltips position in top navigation bar - * - */ -.navbar .nav > li { - position: relative; - white-space: nowrap; -} - -/** - * Add some extra stuff to panels - * - */ - -.container-blank .panel .panel-heading { - font-size: 17px; - line-height: 38px; -} - -.panel { - box-shadow: none; - - .panel-heading { - .panel-head-actions { - position: relative; - top: -5px; - float: right; - } - } - - .panel-body { - form { - margin: 0; - } - - .form-actions { - margin: -15px; - margin-top: 18px; - } - } - - .panel-footer { - .pagination { - margin: 0; - } - - .btn { - min-width: 124px; - } - } - - &.panel-small { - .panel-heading { - padding: 6px 15px; - font-size: 13px; - font-weight: normal; - a { - color: #777; - } - } - } -} - -.panel-succes .panel-heading, -.panel-info .panel-heading, -.panel-danger .panel-heading, -.panel-warning .panel-heading, -.panel-primary .panel-heading, -.alert { - a:not(.btn) { - @extend .alert-link; - color: #fff; - text-decoration: underline; - } -} - -.alert-help { - background-color: $background-color; - border: 1px solid $border-color; - color: $gl-gray; -} - -// Typography ================================================================= - -.text-primary, -.text-primary:hover { - color: $brand-primary; -} - -.text-success, -.text-success:hover { - color: $brand-success; -} - -.text-danger, -.text-danger:hover { - color: $brand-danger; -} - -.text-warning, -.text-warning:hover { - color: $brand-warning; -} - -.text-info, -.text-info:hover { - color: $brand-info; -} - -// Tables ===================================================================== - -table.table { - .dropdown-menu a { - text-decoration: none; - } - - .success, - .warning, - .danger, - .info { - color: #fff; - - a:not(.btn) { - text-decoration: underline; - color: #fff; - } - } -} diff --git a/app/assets/stylesheets/base/gl_variables.scss b/app/assets/stylesheets/base/gl_variables.scss deleted file mode 100644 index 18632da4f2a..00000000000 --- a/app/assets/stylesheets/base/gl_variables.scss +++ /dev/null @@ -1,158 +0,0 @@ -// Override Bootstrap variables here (defaults from bootstrap-sass v3.3.3): -// For all variables see https://github.com/twbs/bootstrap-sass/blob/master/templates/project/_bootstrap-variables.sass -// -// Variables -// -------------------------------------------------- - - -//== Colors -// -//## Gray and brand colors for use across Bootstrap. - -// $gray-base: #000 -// $gray-darker: lighten($gray-base, 13.5%) // #222 -// $gray-dark: lighten($gray-base, 20%) // #333 -// $gray: lighten($gray-base, 33.5%) // #555 -// $gray-light: lighten($gray-base, 46.7%) // #777 -// $gray-lighter: lighten($gray-base, 93.5%) // #eee - -$brand-primary: $gl-primary; -$brand-success: $gl-success; -$brand-info: $gl-info; -$brand-warning: $gl-warning; -$brand-danger: $gl-danger; - -$border-radius-base: 2px !default; -$border-radius-large: 2px !default; -$border-radius-small: 2px !default; - - -//== Scaffolding -// -$text-color: $gl-text-color; -$link-color: $gl-link-color; - - -//== Typography -// -//## Font, line-height, and color for body text, headings, and more. - -$font-family-sans-serif: $regular_font; -$font-family-monospace: $monospace_font; -$font-size-base: $gl-font-size; - - -//== Components -// -//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start). - -$padding-base-vertical: 9px; -$padding-base-horizontal: $gl-padding; -$component-active-color: #fff; -$component-active-bg: $brand-info; - -//== Forms -// -//## - -$input-color: $text-color; -$input-border: #e7e9ed; -$input-border-focus: #7F8FA4; -$legend-color: $text-color; - - -//== Pagination -// -//## - -$pagination-color: $gl-gray; -$pagination-bg: $background-color; -$pagination-border: transparent; - -$pagination-hover-color: #fff; -$pagination-hover-bg: $brand-info; -$pagination-hover-border: transparent; - -$pagination-active-color: #fff; -$pagination-active-bg: $brand-info; -$pagination-active-border: transparent; - -$pagination-disabled-color: #fff; -$pagination-disabled-bg: lighten($brand-info, 15%); -$pagination-disabled-border: transparent; - - -//== Form states and alerts -// -//## Define colors for form feedback states and, by default, alerts. - -$state-success-text: #fff; -$state-success-bg: $brand-success; -$state-success-border: $brand-success; - -$state-info-text: #fff; -$state-info-bg: $brand-info; -$state-info-border: $brand-info; - -$state-warning-text: #fff; -$state-warning-bg: $brand-warning; -$state-warning-border: $brand-warning; - -$state-danger-text: #fff; -$state-danger-bg: $brand-danger; -$state-danger-border: $brand-danger; - - -//== Alerts -// -//## Define alert colors, border radius, and padding. - -$alert-border-radius: 0; - - -//== Panels -// -//## - -$panel-border-radius: 2px; -$panel-default-text: $text-color; -$panel-default-border: $border-color; -$panel-default-heading-bg: $background-color; -$panel-footer-bg: $background-color; -$panel-inner-border: $border-color; - -//== Wells -// -//## - -$well-bg: #F9F9F9; -$well-border: #EEE; - -//== Code -// -//## - -$code-color: #c7254e; -$code-bg: #f9f2f4; - -$kbd-color: #fff; -$kbd-bg: #333; - -//== Buttons -// -//## -$btn-default-color: $gl-text-color; -$btn-default-bg: #fff; -$btn-default-border: #e7e9ed; - -//== Nav -// -//## -$nav-link-padding: 13px $gl-padding; - -//== Code -// -//## -$pre-bg: #f8fafc !default; -$pre-color: $gl-gray !default; -$pre-border-color: #e7e9ed; diff --git a/app/assets/stylesheets/base/layout.scss b/app/assets/stylesheets/base/layout.scss deleted file mode 100644 index c7b3b60e769..00000000000 --- a/app/assets/stylesheets/base/layout.scss +++ /dev/null @@ -1,27 +0,0 @@ -html { - overflow-y: scroll; - - &.touch .tooltip { display: none !important; } - - body { - padding-top: $header-height; - text-rendering: geometricPrecision; - } -} - -.container { - padding-top: 0; - z-index: 5; -} - -.container .content { - margin: 0 0; -} - -.navless-container { - margin-top: 30px; -} - -.container-limited { - max-width: $fixed-layout-width; -} diff --git a/app/assets/stylesheets/base/mixins.scss b/app/assets/stylesheets/base/mixins.scss deleted file mode 100644 index c74a6d39824..00000000000 --- a/app/assets/stylesheets/base/mixins.scss +++ /dev/null @@ -1,301 +0,0 @@ -/** - * Generic mixins - */ - @mixin box-shadow($shadow) { - -webkit-box-shadow: $shadow; - -moz-box-shadow: $shadow; - -ms-box-shadow: $shadow; - -o-box-shadow: $shadow; - box-shadow: $shadow; -} - -@mixin border-radius($radius) { - -webkit-border-radius: $radius; - -moz-border-radius: $radius; - -ms-border-radius: $radius; - -o-border-radius: $radius; - border-radius: $radius; -} - -@mixin border-radius-left($radius) { - @include border-radius($radius 0 0 $radius) -} - -@mixin border-radius-right($radius) { - @include border-radius(0 0 $radius $radius) -} - -@mixin linear-gradient($from, $to) { - background-image: -webkit-gradient(linear, 0 0, 0 100%, from($from), to($to)); - background-image: -webkit-linear-gradient($from, $to); - background-image: -moz-linear-gradient($from, $to); - background-image: -ms-linear-gradient($from, $to); - background-image: -o-linear-gradient($from, $to); -} - -@mixin transition($transition) { - -webkit-transition: $transition; - -moz-transition: $transition; - -ms-transition: $transition; - -o-transition: $transition; - transition: $transition; -} - -/** - * Prefilled mixins - * Mixins with fixed values - */ - -@mixin shade { - @include box-shadow(0 0 3px #ddd); -} - -@mixin solid-shade { - @include box-shadow(0 0 0 3px #f1f1f1); -} - -@mixin md-typography { - color: $md-text-color; - - a { - color: $md-link-color; - } - - img { - max-width: 100%; - } - - *:first-child { - margin-top: 0; - } - - code { - font-family: $monospace_font; - white-space: pre; - word-wrap: normal; - padding: 1px 2px; - } - - kbd { - display: inline-block; - padding: 3px 5px; - font-size: 11px; - line-height: 10px; - color: #555; - vertical-align: middle; - background-color: #FCFCFC; - border-width: 1px; - border-style: solid; - border-color: #CCC #CCC #BBB; - border-image: none; - border-radius: 3px; - box-shadow: 0px -1px 0px #BBB inset; - } - - h1 { - font-size: 1.3em; - font-weight: 600; - margin: 24px 0 12px 0; - padding: 0 0 10px 0; - border-bottom: 1px solid #e7e9ed; - color: #313236; - } - - h2 { - font-size: 1.2em; - font-weight: 600; - margin: 24px 0 12px 0; - color: #313236; - } - - h3 { - margin: 24px 0 12px 0; - font-size: 1.25em; - } - - h4 { - margin: 24px 0 12px 0; - font-size: 1.1em; - } - - h5 { - margin: 24px 0 12px 0; - font-size: 1em; - } - - h6 { - margin: 24px 0 12px 0; - font-size: 0.90em; - } - - blockquote { - padding: 8px 21px; - margin: 12px 0 12px; - border-left: 3px solid #e7e9ed; - } - - blockquote p { - color: #7f8fa4 !important; - font-size: 15px; - line-height: 1.5; - } - - p { - color:#5c5d5e; - margin:6px 0 0 0; - } - - table { - @extend .table; - @extend .table-bordered; - margin: 12px 0 12px 0; - color: #5c5d5e; - th { - background: #f8fafc; - } - } - - pre { - margin: 12px 0 12px 0 !important; - background-color: #f8fafc !important; - font-size: 13px !important; - color: #5b6169 !important; - line-height: 1.6em !important; - @include border-radius(2px); - } - - p > code { - font-weight: inherit; - } - - - ul { - color: #5c5d5e; - } - - li { - line-height: 1.6em; - } - - a[href*="/uploads/"], a[href*="storage.googleapis.com/google-code-attachments/"] { - &:before { - margin-right: 4px; - - font: normal normal normal 14px/1 FontAwesome; - font-size: inherit; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - content: "\f0c6"; - } - - &:hover:before { - text-decoration: none; - } - } -} - - -@mixin str-truncated($max_width: 82%) { - display: inline-block; - overflow: hidden; - text-overflow: ellipsis; - vertical-align: top; - white-space: nowrap; - max-width: $max_width; -} - -/* - * Base mixin for lists in GitLab - */ -@mixin basic-list { - margin: 5px 0px; - padding: 0px; - list-style: none; - - > li { - padding: 10px 0; - border-bottom: 1px solid #EEE; - overflow: hidden; - display: block; - margin: 0px; - - &:last-child { - border-bottom: none; - } - - &.active { - background: #f9f9f9; - a { - font-weight: 600; - } - } - - &.hide { - display: none; - } - - &.light { - a { - color: $gl-gray; - } - } - } -} - -@mixin input-big { - height: 36px; - padding: 5px 10px; - font-size: 16px; - line-height: 24px; - color: #7f8fa4; - background-color: #fff; - border-color: #e7e9ed; -} - -@mixin btn-big { - height: 36px; - padding: 5px 10px; - font-size: 16px; - line-height: 24px; -} - -@mixin nav-menu { - padding: 0; - margin: 0; - list-style: none; - margin-top: 5px; - height: 56px; - - li { - display: inline-block; - - a { - padding: 14px; - font-size: 17px; - line-height: 28px; - color: #7f8fa4; - border-bottom: 2px solid transparent; - - &:hover, &:active, &:focus { - text-decoration: none; - } - } - - &.active a { - color: #4c4e54; - border-bottom: 2px solid #1cacfc; - } - - .badge { - font-weight: normal; - background-color: #fff; - background-color: #eee; - color: #78a; - } - } -} - -.fa-align { - top: 20px; - position: relative; -} diff --git a/app/assets/stylesheets/base/variables.scss b/app/assets/stylesheets/base/variables.scss deleted file mode 100644 index eb9a2966389..00000000000 --- a/app/assets/stylesheets/base/variables.scss +++ /dev/null @@ -1,98 +0,0 @@ -$hover: #FFFAF1; -$gl-text-color: #54565B; -$gl-text-green: #4A2; -$gl-text-red: #D12F19; -$gl-text-orange: #D90; -$gl-header-color: #4c4e54; -$gl-link-color: #333c48; -$md-text-color: #444; -$md-link-color: #3084bb; -$nprogress-color: #c0392b; -$gl-font-size: 15px; -$list-font-size: 15px; -$sidebar_collapsed_width: 62px; -$sidebar_width: 230px; -$avatar_radius: 50%; -$code_font_size: 13px; -$code_line_height: 1.5; -$border-color: #dce0e6; -$background-color: #F7F8FA; -$header-height: 58px; -$fixed-layout-width: 1200px; -$gl-gray: #7f8fa4; -$gl-padding: 16px; -$gl-avatar-size: 46px; - -/* - * Color schema - */ - -$white-light: #FFFFFF; -$white-normal: #DCE0E5; -$white-dark: #E4E7ED; - -$gray-light: #F0F2F5; -$gray-normal: #DCE0E5; -$gray-dark: #E4E7ED; - -$green-light: #31AF64; -$green-normal: #2FAA60; -$green-dark: #2CA05B; - -$blue-light: #2EA8E5; -$blue-normal: #2D9FD8; -$blue-dark: #2897CE; - -$orange-light: #FC6443; -$orange-normal: #E75E40; -$orange-dark: #CE5237; - -$red-light: #F43263; -$red-normal: #E52C5A; -$red-dark: #D22852; - -$border-white-light: #E3E7EC; -$border-white-normal: #D6DAE2; -$border-white-dark: #C6CACF; - -$border-gray-light: #DCE0E5; -$border-gray-normal: #D6DAE2; -$border-gray-dark: #C6CACF; - -$border-green-light: #2FAA60; -$border-green-normal: #2CA05B; -$border-green-dark: #279654; - -$border-blue-light: #2D9FD8; -$border-blue-normal: #2897CE; -$border-blue-dark: #258DC1; - -$border-orange-light: #ED5C3D; -$border-orange-normal: #CE5237; -$border-orange-dark: #C14E35; - -$border-red-light: #E52C5A; -$border-red-normal: #D22852; -$border-red-dark: #CA264F; - - -/* - * State colors: - */ -$gl-primary: $blue-normal; -$gl-success: $green-normal; -$gl-info: $blue-normal; -$gl-warning: $orange-normal; -$gl-danger: $red-normal; - -/* - * Commit Diff Colors - */ -$added: #63c363; -$deleted: #f77; - -/* - * Fonts - */ -$monospace_font: 'Menlo', 'Liberation Mono', 'Consolas', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Courier New', 'andale mono', 'lucida console', monospace; -$regular_font: 'Source Sans Pro', "Helvetica Neue", Helvetica, Arial, sans-serif; diff --git a/app/assets/stylesheets/framework.scss b/app/assets/stylesheets/framework.scss new file mode 100644 index 00000000000..c5e23c1c328 --- /dev/null +++ b/app/assets/stylesheets/framework.scss @@ -0,0 +1,32 @@ +@import "framework/fonts"; +@import "framework/variables"; +@import "framework/mixins"; +@import "framework/layout"; +@import 'framework/gl_variables'; +@import 'framework/gl_bootstrap'; +@import "framework/avatar.scss"; +@import "framework/blocks.scss"; +@import "framework/buttons.scss"; +@import "framework/calendar.scss"; +@import "framework/callout.scss"; +@import "framework/common.scss"; +@import "framework/files.scss"; +@import "framework/filters.scss"; +@import "framework/flash.scss"; +@import "framework/forms.scss"; +@import "framework/gfm.scss"; +@import "framework/gitlab-theme.scss"; +@import "framework/header.scss"; +@import "framework/highlight.scss"; +@import "framework/issue_box.scss"; +@import "framework/jquery.scss"; +@import "framework/lists.scss"; +@import "framework/markdown_area.scss"; +@import "framework/mobile.scss"; +@import "framework/pagination.scss"; +@import "framework/selects.scss"; +@import "framework/sidebar.scss"; +@import "framework/tables.scss"; +@import "framework/timeline.scss"; +@import "framework/typography.scss"; +@import "framework/zen.scss"; diff --git a/app/assets/stylesheets/framework/avatar.scss b/app/assets/stylesheets/framework/avatar.scss new file mode 100644 index 00000000000..36e582d4854 --- /dev/null +++ b/app/assets/stylesheets/framework/avatar.scss @@ -0,0 +1,49 @@ +.avatar { + float: left; + margin-right: 12px; + width: 40px; + height: 40px; + padding: 0; + @include border-radius($avatar_radius); + + &.avatar-inline { + float: none; + margin-left: 4px; + margin-bottom: 2px; + + &.s16 { margin-right: 4px; } + &.s24 { margin-right: 4px; } + } + + &.group-avatar, &.project-avatar, &.avatar-tile { + @include border-radius(0px); + } + + &.s16 { width: 16px; height: 16px; margin-right: 6px; } + &.s24 { width: 24px; height: 24px; margin-right: 8px; } + &.s26 { width: 26px; height: 26px; margin-right: 8px; } + &.s32 { width: 32px; height: 32px; margin-right: 10px; } + &.s36 { width: 36px; height: 36px; margin-right: 10px; } + &.s46 { width: 46px; height: 46px; margin-right: 15px; } + &.s48 { width: 48px; height: 48px; margin-right: 10px; } + &.s60 { width: 60px; height: 60px; margin-right: 12px; } + &.s90 { width: 90px; height: 90px; margin-right: 15px; } + &.s110 { width: 110px; height: 110px; margin-right: 15px; } + &.s140 { width: 140px; height: 140px; margin-right: 20px; } + &.s160 { width: 160px; height: 160px; margin-right: 20px; } +} + +.identicon { + text-align: center; + vertical-align: top; + + &.s16 { font-size: 12px; line-height: 1.33; } + &.s24 { font-size: 14px; line-height: 1.8; } + &.s26 { font-size: 20px; line-height: 1.33; } + &.s32 { font-size: 22px; line-height: 32px; } + &.s60 { font-size: 32px; line-height: 60px; } + &.s90 { font-size: 36px; line-height: 90px; } + &.s110 { font-size: 40px; line-height: 112px; font-weight: 300; } + &.s140 { font-size: 72px; line-height: 140px; } + &.s160 { font-size: 96px; line-height: 160px; } +} diff --git a/app/assets/stylesheets/framework/blocks.scss b/app/assets/stylesheets/framework/blocks.scss new file mode 100644 index 00000000000..6ce34b5c3e8 --- /dev/null +++ b/app/assets/stylesheets/framework/blocks.scss @@ -0,0 +1,62 @@ +.light-well { + background-color: #f8fafc; + padding: 15px; +} + +.centered-light-block { + text-align: center; + color: $gl-gray; + margin: 20px; +} + +.nothing-here-block { + text-align: center; + padding: 20px; + color: $gl-gray; + font-weight: normal; + font-size: 16px; + line-height: 36px; +} + +.gray-content-block { + margin: -$gl-padding; + background-color: $background-color; + padding: $gl-padding; + margin-bottom: 0px; + border-top: 1px solid $border-color; + border-bottom: 1px solid $border-color; + color: $gl-gray; + + &.top-block { + border-top: none; + } + + &.middle-block { + margin-top: 0; + margin-bottom: 0; + } + + &.clear-block { + margin-bottom: $gl-padding - 1px; + padding-bottom: $gl-padding; + } + + &.second-block { + margin-top: -1px; + margin-bottom: 0; + } + + &.footer-block { + margin-top: 0; + border-bottom: none; + margin-bottom: -$gl-padding; + } + + .title { + color: $gl-text-color; + } + + .oneline { + line-height: 42px; + } +} diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss new file mode 100644 index 00000000000..11acbe3adfa --- /dev/null +++ b/app/assets/stylesheets/framework/buttons.scss @@ -0,0 +1,163 @@ +@mixin btn-default { + @include border-radius(2px); + border-width: 1px; + border-style: solid; + text-transform: uppercase; + font-size: 13px; + font-weight: 600; + line-height: 18px; + padding: 11px 16px; + letter-spacing: .4px; + + &:focus, + &:active { + outline: none; + @include box-shadow(inset 0 0 4px rgba(0, 0, 0, 0.12)); + } +} + +@mixin btn-middle { + @include btn-default; + @include border-radius(2px); + padding: 11px 24px; +} + +@mixin btn-color($light, $border-light, $normal, $border-normal, $dark, $border-dark, $color) { + background-color: $light; + border-color: $border-light; + color: $color; + + &:hover, + &:focus { + background-color: $normal; + border-color: $border-normal; + color: $color; + } + + &:active { + @include box-shadow (inset 0 0 4px rgba(0, 0, 0, 0.12)); + + background-color: $dark; + border-color: $border-dark; + color: $color; + } +} + +@mixin btn-green { + @include btn-color($green-light, $border-green-light, $green-normal, $border-green-normal, $green-dark, $border-green-dark, #FFFFFF); +} + +@mixin btn-blue { + @include btn-color($blue-light, $border-blue-light, $blue-normal, $border-blue-normal, $blue-dark, $border-blue-dark, #FFFFFF); +} + +@mixin btn-orange { + @include btn-color($orange-light, $border-orange-light, $orange-normal, $border-orange-normal, $orange-dark, $border-orange-dark, #FFFFFF); +} + +@mixin btn-red { + @include btn-color($red-light, $border-red-light, $red-normal, $border-red-normal, $red-dark, $border-red-dark, #FFFFFF); +} + +@mixin btn-gray { + @include btn-color($gray-light, $border-gray-light, $gray-normal, $border-gray-normal, $gray-dark, $border-gray-dark, #313236); +} + +@mixin btn-white { + @include btn-color($white-light, $border-white-light, $white-normal, $border-white-normal, $white-dark, $border-white-dark, #313236); +} + +.btn { + @include btn-default; + @include btn-white; + + &.btn-success, + &.btn-new, + &.btn-create, + &.btn-save, + &.btn-green { + @include btn-green; + } + + &.btn-gray { + @include btn-gray; + } + + &.btn-primary, + &.btn-info { + @include btn-blue; + } + + &.btn-warning { + @include btn-orange; + } + + &.btn-danger, + &.btn-remove, + &.btn-red { + @include btn-red; + } + + &.btn-cancel { + float: right; + } + + &.btn-close { + color: $gl-danger; + border-color: $gl-danger; + &:hover { + color: #B94A48; + } + } + + &.btn-reopen { + color: $gl-success; + border-color: $gl-success; + &:hover { + color: #468847; + } + } + + &.btn-grouped { + margin-right: 7px; + float: left; + &:last-child { + margin-right: 0px; + } + } +} + +.btn-block { + width: 100%; + margin: 0; + margin-bottom: 15px; + &.btn { + padding: 6px 0; + } +} + +.btn-group { + &.btn-grouped { + margin-right: 7px; + float: left; + &:last-child { + margin-right: 0px; + } + } +} + +.btn-group-next { + .btn { + padding: 9px 0px; + font-size: 15px; + color: #7f8fa4; + border-color: #e7e9ed; + width: 140px; + + &.active { + border-color: $gl-info; + background: $gl-info; + color: #fff; + } + } +} diff --git a/app/assets/stylesheets/framework/calendar.scss b/app/assets/stylesheets/framework/calendar.scss new file mode 100644 index 00000000000..a36fefe22c5 --- /dev/null +++ b/app/assets/stylesheets/framework/calendar.scss @@ -0,0 +1,90 @@ +.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; + } + } +} +/** +* This overwrites the default values of the cal-heatmap gem +*/ +.calendar { + .qi { + background-color: #999; + fill: #fff; + } + + .q1 { + background-color: #dae289; + fill: #ededed; + } + + .q2 { + background-color: #cedb9c; + fill: #ACD5F2; + } + + .q3 { + background-color: #b5cf6b; + fill: #7FA8D1; + } + + .q4 { + background-color: #637939; + fill: #49729B; + } + + .q5 { + background-color: #3b6427; + fill: #254E77; + } + + .domain-background { + fill: none; + shape-rendering: crispedges; + } + + .ch-tooltip { + position: absolute; + display: none; + margin-top: 22px; + margin-left: 1px; + font-size: 13px; + padding: 3px; + font-weight: 550; + background-color: #222; + span { + position: absolute; + width: 200px; + text-align: center; + visibility: hidden; + border-radius: 10px; + &:after { + content: ''; + position: absolute; + top: 100%; + left: 50%; + margin-left: -8px; + width: 0; + height: 0; + border-top: 8px solid #000000; + border-right: 8px solid transparent; + border-left: 8px solid transparent; + } + } + } +} diff --git a/app/assets/stylesheets/framework/callout.scss b/app/assets/stylesheets/framework/callout.scss new file mode 100644 index 00000000000..f1699d21c9b --- /dev/null +++ b/app/assets/stylesheets/framework/callout.scss @@ -0,0 +1,45 @@ +/* + * Callouts from Bootstrap3 docs + * + * Not quite alerts, but custom and helpful notes for folks reading the docs. + * Requires a base and modifier class. + */ + +/* Common styles for all types */ +.bs-callout { + margin: 20px 0; + padding: 20px; + border-left: 3px solid #eee; + color: #666; + background: #f9f9f9; +} +.bs-callout h4 { + margin-top: 0; + margin-bottom: 5px; +} +.bs-callout p:last-child { + margin-bottom: 0; +} + +/* Variations */ +.bs-callout-danger { + background-color: #fdf7f7; + border-color: #eed3d7; + color: #b94a48; +} +.bs-callout-warning { + background-color: #faf8f0; + border-color: #faebcc; + color: #8a6d3b; +} +.bs-callout-info { + background-color: #f4f8fa; + border-color: #bce8f1; + color: #34789a; +} +.bs-callout-success { + background-color: #dff0d8; + border-color: #5cA64d; + color: #3c763d; +} + diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss new file mode 100644 index 00000000000..03919f15f1f --- /dev/null +++ b/app/assets/stylesheets/framework/common.scss @@ -0,0 +1,404 @@ +/** COLORS **/ +.cgray { color: $gl-gray; } +.clgray { color: #BBB } +.cred { color: $gl-text-red; } +.cgreen { color: $gl-text-green; } +.cdark { color: #444 } + +/** COMMON CLASSES **/ +.prepend-top-10 { margin-top:10px } +.prepend-top-default { margin-top: $gl-padding; } +.prepend-top-20 { margin-top:20px } +.prepend-left-10 { margin-left:10px } +.prepend-left-20 { margin-left:20px } +.append-right-10 { margin-right:10px } +.append-right-20 { margin-right:20px } +.append-bottom-10 { margin-bottom:10px } +.append-bottom-15 { margin-bottom:15px } +.append-bottom-20 { margin-bottom:20px } +.inline { display: inline-block } +.center { text-align: center } + +.underlined-link { text-decoration: underline; } +.hint { font-style: italic; color: #999; } +.light { color: $gl-gray; } + +.slead { + color: $gl-gray; + font-size: 15px; + margin-bottom: 12px; + font-weight: normal; + line-height: 24px; +} + +.tab-content { + overflow: visible; +} + +pre { + &.clean { + background: none; + border: none; + margin: 0; + padding: 0; + } + + &.well-pre { + border: 1px solid #EEE; + background: #f9f9f9; + border-radius: 0; + color: #555; + } +} + +.dropdown-menu > li > a { + text-shadow: none; +} + +.dropdown-menu-align-right { + left: auto; + right: 0px; +} + +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + background: $gl-primary; + color: #FFF +} + +.str-truncated { + @include str-truncated; +} + +/** FLASH message **/ +.author_link { + color: $gl-link-color; +} + +.back-link { + font-size: 14px; +} + +table a code { + position: relative; + top: -2px; + margin-right: 3px; +} + +.loading { + margin: 20px auto; + height: 40px; + color: #555; + font-size: 32px; + text-align: center; +} + +span.update-author { + display: block; + color: #999; + font-weight: normal; + font-style: italic; + strong { + font-weight: bold; + font-style: normal; + } +} + +.user-mention { + color: #2FA0BB; + font-weight: bold; +} + +.field_with_errors { + display: inline; +} + +.line_holder { + &:hover { + td { + background: #FFFFCF !important; + } + } +} + +p.time { + color: #999; + font-size: 90%; + margin: 30px 3px 3px 2px; +} + +.highlight { + text-shadow: none; +} + +.thin_area{ + height: 150px; +} + +// Fixes alignment on notes. +.new_note { + label { + text-align: left; + } +} + +// Fix issue with notes & lists creating a bunch of bottom borders. +li.note { + img { max-width:100% } + .note-title { + li { + border-bottom:none !important; + } + } +} + +.markdown { + img { + max-width: 100%; + } +} + +.wiki_content code, .readme code{ + background-color: inherit; +} + +.project_member_show { + td:first-child { + color: #aaa; + } +} + +.rss-icon { + img { + width: 24px; + vertical-align: top; + } + + strong { + line-height: 24px; + } +} + +.show-suppressed-diff, +.show-all-commits { + cursor: pointer; +} + +.git_error_tips { + @extend .col-md-6; + text-align: left; + margin-top: 40px; + pre { + background: white; + border: none; + font-size: 12px; + } +} + +.error-message { + padding: 10px; + background: #C67; + margin: 0; + color: #FFF; + + a { + color: #fff; + text-decoration: underline; + } +} + +.browser-alert { + padding: 10px; + text-align: center; + background: #C67; + color: #fff; + font-weight: bold; + a { + color: #fff; + text-decoration: underline; + } +} + +.warning_message { + border-left: 4px solid #ed9; + color: #b90; + padding: 10px; + margin-bottom: 10px; + background: #ffffe6; + padding-left: 20px; + + &.centered { + text-align: center; + } +} + +.gitlab-promo { + a { + color: #aaa; + margin-right: 30px; + } +} + +.milestone { + &.milestone-closed { + background: #f9f9f9; + } + .progress { + margin-bottom: 0; + margin-top: 4px; + } +} + +.control-group { + .controls { + span { + &.descr { + position: relative; + top: 2px; + left: 5px; + color: #666; + } + } + } +} + +img.emoji { + height: 20px; + vertical-align: middle; + width: 20px; +} + +.chart { + overflow: hidden; + height: 220px; +} + +.description-block { + @extend .light-well; + @extend .light; + margin-bottom: 10px; +} + +table { + td.permission-x { + background: #D9EDF7 !important; + text-align: center; + } +} + +.dashboard-intro-icon { + float: left; + text-align: center; + font-size: 32px; + color: #AAA; + width: 60px; +} + +.dashboard-intro-text { + display: inline-block; + margin-left: -60px; + padding-left: 60px; + width: 100%; +} + +.btn-sign-in { + margin-top: 8px; + text-shadow: none; +} + +.side-filters { + fieldset { + margin-bottom: 15px; + } +} + +.wiki .highlight, .note-body .highlight { + margin: 12px 0 12px 0; +} + +.wiki .code { + overflow-x: auto; +} + +.footer-links { + margin-bottom: 20px; + a { + margin-right: 15px; + } +} + +.search_box { + @extend .well; + text-align: center; +} + +.task-status { + margin-left: 10px; +} + +#nprogress .spinner { + top: 15px !important; + right: 10px !important; +} + +.header-with-avatar { + h3 { + margin: 0; + font-weight: bold; + } + + .username { + font-size: 18px; + color: #666; + margin-top: 8px; + } + + .description { + font-size: $gl-font-size; + color: #666; + margin-top: 8px; + } +} + +.profiler-results { + top: 73px !important; + + .profiler-button, + .profiler-controls { + border-color: #EEE !important; + } +} + +.center-top-menu { + @include nav-menu; + text-align: center; + margin-top: 5px; + margin-bottom: $gl-padding; + height: 56px; + margin-top: -$gl-padding; + padding-top: $gl-padding; + + &.no-bottom { + margin-bottom: 0; + } + + &.no-top { + margin-top: 0; + } +} + +.dropzone .dz-preview .dz-progress { + border-color: $border-color !important; +} + +.dropzone .dz-preview .dz-progress .dz-upload { + background: $gl-success !important; +} + +.space-right { + margin-right: 10px; +} + +.in-line { + display: inline-block; +} diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss new file mode 100644 index 00000000000..9dd77747884 --- /dev/null +++ b/app/assets/stylesheets/framework/files.scss @@ -0,0 +1,171 @@ +/** + * File content holder + * + */ +.file-holder { + margin-left: -$gl-padding; + margin-right: -$gl-padding; + border: none; + border-top: 1px solid #E7E9EE; + border-bottom: 1px solid #E7E9EE; + margin-bottom: 1em; + + table { + @extend .table; + } + + .file-title { + position: relative; + background: $background-color; + border-bottom: 1px solid $border-color; + text-shadow: 0 1px 1px #fff; + margin: 0; + text-align: left; + padding: 10px 15px; + + .file-actions { + float: right; + position: absolute; + top: 5px; + right: 15px; + + .btn { + padding: 0px 10px; + font-size: 13px; + line-height: 28px; + } + } + + .left-options { + margin-top: -3px; + } + } + .file-content { + background: #fff; + + &.image_file { + background: #eee; + text-align: center; + img { + padding: 100px; + max-width: 50%; + } + } + + &.wiki { + padding: $gl-padding; + + .highlight { + margin-bottom: 9px; + + > pre { + margin: 0; + } + } + } + + &.blob_file { + + } + + &.blob-no-preview { + background: #eee; + text-shadow: 0 1px 2px #FFF; + padding: 100px 0; + } + + /** + * Blame file + */ + &.blame { + table { + border: none; + box-shadow: none; + margin: 0; + } + tr { + border-bottom: 1px solid #eee; + } + td { + &:first-child { + border-left: none; + } + &:last-child { + border-right: none; + } + background: #fff; + padding: 10px $gl-padding; + } + .lines { + pre { + padding: 0; + margin: 0; + background: none; + border: none; + } + } + img.avatar { + border: 0 none; + float: none; + margin: 0; + padding: 0; + } + td.blame-commit { + background: #f9f9f9; + min-width: 350px; + + .commit-author-link { + color: #888; + } + } + td.blame-numbers { + pre { + color: #AAA; + white-space: pre; + } + background: #f1f1f1; + border-left: 1px solid #DDD; + } + td.lines { + code { + font-family: $monospace_font; + } + } + } + + &.logs { + background: #eee; + max-height: 700px; + overflow-y: auto; + + ol { + margin-left: 40px; + padding: 10px 0; + border-left: 1px solid $border-color; + margin-bottom: 0; + background: white; + li { + color: #888; + p { + margin: 0; + color: #333; + line-height: 24px; + padding-left: 10px; + } + + &:hover { + background: $hover; + } + } + } + } + + /** + * Code file + */ + &.code { + padding: 0; + } + } +} + diff --git a/app/assets/stylesheets/framework/filters.scss b/app/assets/stylesheets/framework/filters.scss new file mode 100644 index 00000000000..8e6922c9231 --- /dev/null +++ b/app/assets/stylesheets/framework/filters.scss @@ -0,0 +1,30 @@ +.filter-item { + margin-right: 15px; +} + +@media (min-width: 800px) { + .issues-filters, + .issues_bulk_update { + select, .select2-container { + width: 120px !important; + display: inline-block; + } + } +} + +@media (min-width: 1200px) { + .issues-filters, + .issues_bulk_update { + select, .select2-container { + width: 150px !important; + display: inline-block; + } + } +} + +.issues-filters, +.issues_bulk_update { + .select2-container .select2-choice { + color: #444 !important; + } +} diff --git a/app/assets/stylesheets/framework/flash.scss b/app/assets/stylesheets/framework/flash.scss new file mode 100644 index 00000000000..82eb50ad4be --- /dev/null +++ b/app/assets/stylesheets/framework/flash.scss @@ -0,0 +1,17 @@ +.flash-container { + cursor: pointer; + margin: 0; + font-size: 14px; + width: 100%; + z-index: 100; + + .flash-notice { + @extend .alert; + @extend .alert-info; + } + + .flash-alert { + @extend .alert; + @extend .alert-danger; + } +} diff --git a/app/assets/stylesheets/framework/fonts.scss b/app/assets/stylesheets/framework/fonts.scss new file mode 100644 index 00000000000..e214567eca1 --- /dev/null +++ b/app/assets/stylesheets/framework/fonts.scss @@ -0,0 +1,25 @@ +/* latin-ext */ +@font-face { + font-family: 'Source Sans Pro'; + font-style: normal; + font-weight: 300; + src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), font-url('SourceSansPro-Light.ttf'); +} +@font-face { + font-family: 'Source Sans Pro'; + font-style: normal; + font-weight: 400; + src: local('Source Sans Pro'), local('SourceSansPro-Regular'), font-url('SourceSansPro-Regular.ttf'); +} +@font-face { + font-family: 'Source Sans Pro'; + font-style: normal; + font-weight: 600; + src: local('Source Sans Pro Semibold'), local('SourceSansPro-Semibold'), font-url('SourceSansPro-Semibold.ttf'); +} +@font-face { + font-family: 'Source Sans Pro'; + font-style: normal; + font-weight: 700; + src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'), font-url('SourceSansPro-Bold.ttf'); +} diff --git a/app/assets/stylesheets/framework/forms.scss b/app/assets/stylesheets/framework/forms.scss new file mode 100644 index 00000000000..0edfe24f195 --- /dev/null +++ b/app/assets/stylesheets/framework/forms.scss @@ -0,0 +1,94 @@ +textarea { + resize: vertical; +} + +input[type='search'].search-text-input { + background-image: image-url("icon-search.png"); + background-repeat: no-repeat; + background-position: 10px; + padding-left: 25px; +} + +input[type='text'].danger { + background: #F2DEDE!important; + border-color: #D66; + text-shadow: 0 1px 1px #fff +} + +.datetime-controls { + select { + width: 100px; + } +} + +.form-actions { + padding: 17px 20px 18px; + margin-top: 18px; + margin-bottom: 18px; + background-color: $background-color; + border-top: 1px solid $border-color; +} + +label { + &.control-label { + @extend .col-sm-2; + } + + &.inline-label { + margin: 0; + } +} + +.inline-input-group { + width: 250px; +} + +.custom-form-control { + width: 150px; +} + +@media (min-width: $screen-sm-min) { + .custom-form-control { + width: 150px; + } +} + +/* Medium devices (desktops, 992px and up) */ +@media (min-width: $screen-md-min) { + .custom-form-control { + width: 170px; + } +} + +/* Large devices (large desktops, 1200px and up) */ +@media (min-width: $screen-lg-min) { + .custom-form-control { + width: 200px; + } +} + +.fieldset-form fieldset { + margin-bottom: 20px; +} + +.form-control { + @include box-shadow(none); +} + +.wiki-content { + margin-top: 35px; +} + +.form-group .control-label { + font-weight: normal; +} + +.form-control::-webkit-input-placeholder { + color: #7f8fa4; +} + +.input-group { + .input-group-addon { + background-color: #f7f8fa; + } +} diff --git a/app/assets/stylesheets/framework/gfm.scss b/app/assets/stylesheets/framework/gfm.scss new file mode 100644 index 00000000000..bd9200ace23 --- /dev/null +++ b/app/assets/stylesheets/framework/gfm.scss @@ -0,0 +1,25 @@ +/** + * Styles that apply to all GFM related forms. + */ +.issue-form, .merge-request-form, .wiki-form { + .description { + height: 16em; + border-top-left-radius: 0; + } +} + +.wiki-form { + .description { + height: 26em; + } +} + +.milestone-form { + .description { + height: 14em; + } +} + +.gfm-commit, .gfm-commit_range { + font-family: $monospace_font; +} diff --git a/app/assets/stylesheets/framework/gitlab-theme.scss b/app/assets/stylesheets/framework/gitlab-theme.scss new file mode 100644 index 00000000000..8d9a0aae568 --- /dev/null +++ b/app/assets/stylesheets/framework/gitlab-theme.scss @@ -0,0 +1,120 @@ +/** + * Styles the GitLab application with a specific color theme + * + * $color-light - + * $color - + * $color-darker - + * $color-dark - + */ +@mixin gitlab-theme($color-light, $color, $color-darker, $color-dark) { + .page-with-sidebar { + .header-logo { + background-color: $color; + border-color: $color; + + a { + color: $color-light; + + h3 { + color: $color-light; + } + } + + &:hover { + background-color: $color-darker; + a { + color: #FFF; + } + } + } + + .collapse-nav a { + color: #FFF; + background: $color; + } + + .sidebar-wrapper { + background: $color-darker; + + .sidebar-user { + background: $color-darker; + color: $color-light; + + &:hover { + background-color: $color-dark; + color: #FFF; + text-decoration: none; + } + } + } + + .nav-sidebar li { + a { + color: $color-light; + + &:hover, &:focus, &:active { + background: $color-dark; + } + + i { + color: $color-light; + } + + .count { + color: $color-light; + background: $color-dark; + } + } + + &.separate-item { + border-top: 1px solid $color; + } + + &.active a { + color: #FFF; + background: $color-dark; + + &.no-highlight { + border: none; + } + + i { + color: #FFF + } + } + } + } +} + +$theme-blue: #2980B9; +$theme-charcoal: #333c47; +$theme-graphite: #888888; +$theme-gray: #373737; +$theme-green: #019875; +$theme-violet: #554488; + +body { + &.ui_blue { + @include gitlab-theme(#BECDE9, $theme-blue, #1970A9, #096099); + } + + &.ui_charcoal { + @include gitlab-theme(#c5d0de, $theme-charcoal, #2b333d, #24272D); + } + + &.ui_graphite { + @include gitlab-theme(#CCCCCC, $theme-graphite, #777777, #666666); + } + + &.ui_gray { + @include gitlab-theme(#979797, $theme-gray, #272727, #222222); + } + + &.ui_green { + @include gitlab-theme(#AADDCC, $theme-green, #018865, #017855); + } + + &.ui_violet { + @include gitlab-theme(#9988CC, $theme-violet, #443366, #332255); + } +} diff --git a/app/assets/stylesheets/framework/gl_bootstrap.scss b/app/assets/stylesheets/framework/gl_bootstrap.scss new file mode 100644 index 00000000000..eb8d23d6453 --- /dev/null +++ b/app/assets/stylesheets/framework/gl_bootstrap.scss @@ -0,0 +1,273 @@ +/* + * Twitter bootstrap with GitLab customizations/additions + * + */ + +// Core variables and mixins +@import "bootstrap/variables"; +@import "bootstrap/mixins"; + +// Reset +@import "bootstrap/normalize"; +@import "bootstrap/print"; + +// Core CSS +@import "bootstrap/scaffolding"; +@import "bootstrap/type"; +@import "bootstrap/code"; +@import "bootstrap/grid"; +@import "bootstrap/tables"; +@import "bootstrap/forms"; +@import "bootstrap/buttons"; + +// Components +@import "bootstrap/component-animations"; +@import "bootstrap/dropdowns"; +@import "bootstrap/button-groups"; +@import "bootstrap/input-groups"; +@import "bootstrap/navs"; +@import "bootstrap/navbar"; +@import "bootstrap/breadcrumbs"; +@import "bootstrap/pagination"; +@import "bootstrap/pager"; +@import "bootstrap/labels"; +@import "bootstrap/badges"; +@import "bootstrap/jumbotron"; +@import "bootstrap/thumbnails"; +@import "bootstrap/alerts"; +@import "bootstrap/progress-bars"; +@import "bootstrap/list-group"; +@import "bootstrap/wells"; +@import "bootstrap/close"; +@import "bootstrap/panels"; + +// Components w/ JavaScript +@import "bootstrap/modals"; +@import "bootstrap/tooltip"; +@import "bootstrap/popovers"; +@import "bootstrap/carousel"; + +// Utility classes +.clearfix { + @include clearfix(); +} +.center-block { + @include center-block(); +} +.pull-right { + float: right !important; +} +.pull-left { + float: left !important; +} +.hide { + display: none; +} +.show { + display: block !important; +} +.invisible { + visibility: hidden; +} +.text-hide { + @include text-hide(); +} +.hidden { + display: none !important; + visibility: hidden !important; +} +.affix { + position: fixed; +} + +@import "bootstrap/responsive-utilities"; + +// Labels +.label { + padding: 2px 4px; + font-size: 13px; + font-style: normal; + font-weight: normal; + display: inline-block; + + &.label-gray { + background-color: #f8fafc; + color: $gl-gray; + text-shadow: none; + } + + &.label-inverse { + background-color: #333333; + } +} + +// Nav tabs +.nav.nav-tabs { + margin-bottom: 15px; + + li { + > a { + margin-right: 5px; + line-height: 20px; + border-color: #EEE; + color: #888; + border-bottom: 1px solid #ddd; + .badge { + background-color: #eee; + color: #888; + text-shadow: 0 1px 1px #fff; + } + i.fa { + line-height: 14px; + } + } + &.active { + > a { + border-color: #CCC; + border-bottom: 1px solid #fff; + color: #333; + font-weight: bold; + } + } + } +} + +.nav-tabs > li > a, +.nav-pills > li > a { + color: #666; +} + +.nav-pills > .active > a > span > .badge { + background-color: #fff; + color: $gl-primary; +} + + +/** + * fix to keep tooltips position in top navigation bar + * + */ +.navbar .nav > li { + position: relative; + white-space: nowrap; +} + +/** + * Add some extra stuff to panels + * + */ + +.container-blank .panel .panel-heading { + font-size: 17px; + line-height: 38px; +} + +.panel { + box-shadow: none; + + .panel-heading { + .panel-head-actions { + position: relative; + top: -5px; + float: right; + } + } + + .panel-body { + form { + margin: 0; + } + + .form-actions { + margin: -15px; + margin-top: 18px; + } + } + + .panel-footer { + .pagination { + margin: 0; + } + + .btn { + min-width: 124px; + } + } + + &.panel-small { + .panel-heading { + padding: 6px 15px; + font-size: 13px; + font-weight: normal; + a { + color: #777; + } + } + } +} + +.panel-succes .panel-heading, +.panel-info .panel-heading, +.panel-danger .panel-heading, +.panel-warning .panel-heading, +.panel-primary .panel-heading, +.alert { + a:not(.btn) { + @extend .alert-link; + color: #fff; + text-decoration: underline; + } +} + +.alert-help { + background-color: $background-color; + border: 1px solid $border-color; + color: $gl-gray; +} + +// Typography ================================================================= + +.text-primary, +.text-primary:hover { + color: $brand-primary; +} + +.text-success, +.text-success:hover { + color: $brand-success; +} + +.text-danger, +.text-danger:hover { + color: $brand-danger; +} + +.text-warning, +.text-warning:hover { + color: $brand-warning; +} + +.text-info, +.text-info:hover { + color: $brand-info; +} + +// Tables ===================================================================== + +table.table { + .dropdown-menu a { + text-decoration: none; + } + + .success, + .warning, + .danger, + .info { + color: #fff; + + a:not(.btn) { + text-decoration: underline; + color: #fff; + } + } +} diff --git a/app/assets/stylesheets/framework/gl_variables.scss b/app/assets/stylesheets/framework/gl_variables.scss new file mode 100644 index 00000000000..18632da4f2a --- /dev/null +++ b/app/assets/stylesheets/framework/gl_variables.scss @@ -0,0 +1,158 @@ +// Override Bootstrap variables here (defaults from bootstrap-sass v3.3.3): +// For all variables see https://github.com/twbs/bootstrap-sass/blob/master/templates/project/_bootstrap-variables.sass +// +// Variables +// -------------------------------------------------- + + +//== Colors +// +//## Gray and brand colors for use across Bootstrap. + +// $gray-base: #000 +// $gray-darker: lighten($gray-base, 13.5%) // #222 +// $gray-dark: lighten($gray-base, 20%) // #333 +// $gray: lighten($gray-base, 33.5%) // #555 +// $gray-light: lighten($gray-base, 46.7%) // #777 +// $gray-lighter: lighten($gray-base, 93.5%) // #eee + +$brand-primary: $gl-primary; +$brand-success: $gl-success; +$brand-info: $gl-info; +$brand-warning: $gl-warning; +$brand-danger: $gl-danger; + +$border-radius-base: 2px !default; +$border-radius-large: 2px !default; +$border-radius-small: 2px !default; + + +//== Scaffolding +// +$text-color: $gl-text-color; +$link-color: $gl-link-color; + + +//== Typography +// +//## Font, line-height, and color for body text, headings, and more. + +$font-family-sans-serif: $regular_font; +$font-family-monospace: $monospace_font; +$font-size-base: $gl-font-size; + + +//== Components +// +//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start). + +$padding-base-vertical: 9px; +$padding-base-horizontal: $gl-padding; +$component-active-color: #fff; +$component-active-bg: $brand-info; + +//== Forms +// +//## + +$input-color: $text-color; +$input-border: #e7e9ed; +$input-border-focus: #7F8FA4; +$legend-color: $text-color; + + +//== Pagination +// +//## + +$pagination-color: $gl-gray; +$pagination-bg: $background-color; +$pagination-border: transparent; + +$pagination-hover-color: #fff; +$pagination-hover-bg: $brand-info; +$pagination-hover-border: transparent; + +$pagination-active-color: #fff; +$pagination-active-bg: $brand-info; +$pagination-active-border: transparent; + +$pagination-disabled-color: #fff; +$pagination-disabled-bg: lighten($brand-info, 15%); +$pagination-disabled-border: transparent; + + +//== Form states and alerts +// +//## Define colors for form feedback states and, by default, alerts. + +$state-success-text: #fff; +$state-success-bg: $brand-success; +$state-success-border: $brand-success; + +$state-info-text: #fff; +$state-info-bg: $brand-info; +$state-info-border: $brand-info; + +$state-warning-text: #fff; +$state-warning-bg: $brand-warning; +$state-warning-border: $brand-warning; + +$state-danger-text: #fff; +$state-danger-bg: $brand-danger; +$state-danger-border: $brand-danger; + + +//== Alerts +// +//## Define alert colors, border radius, and padding. + +$alert-border-radius: 0; + + +//== Panels +// +//## + +$panel-border-radius: 2px; +$panel-default-text: $text-color; +$panel-default-border: $border-color; +$panel-default-heading-bg: $background-color; +$panel-footer-bg: $background-color; +$panel-inner-border: $border-color; + +//== Wells +// +//## + +$well-bg: #F9F9F9; +$well-border: #EEE; + +//== Code +// +//## + +$code-color: #c7254e; +$code-bg: #f9f2f4; + +$kbd-color: #fff; +$kbd-bg: #333; + +//== Buttons +// +//## +$btn-default-color: $gl-text-color; +$btn-default-bg: #fff; +$btn-default-border: #e7e9ed; + +//== Nav +// +//## +$nav-link-padding: 13px $gl-padding; + +//== Code +// +//## +$pre-bg: #f8fafc !default; +$pre-color: $gl-gray !default; +$pre-border-color: #e7e9ed; diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss new file mode 100644 index 00000000000..91e6975e269 --- /dev/null +++ b/app/assets/stylesheets/framework/header.scss @@ -0,0 +1,169 @@ +/* + * Application Header + * + */ +header { + transition-duration: .3s; + + &.navbar-empty { + background: #FFF; + border-bottom: 1px solid #EEE; + + .center-logo { + margin: 8px 0; + text-align: center; + + img { + height: 32px; + } + } + } + + &.navbar-gitlab { + padding: 0 20px; + z-index: 100; + margin-bottom: 0; + min-height: $header-height; + background-color: #fff; + border: none; + + .container-fluid { + width: 100% !important; + filter: none; + padding: 0; + + .nav > li > a { + color: #7f8fa4; + font-size: 18px; + padding: 0; + margin: ($header-height - 28) / 2 0; + margin-left: 10px; + height: 28px; + width: 28px; + line-height: 28px; + text-align: center; + + &:hover, &:focus, &:active { + background-color: #FFF; + } + } + + .navbar-toggle { + color: #666; + margin: 6px 0; + border-radius: 0; + position: absolute; + right: 2px; + + &:hover { + background-color: #EEE; + } + &.active { + color: #7f8fa4; + } + } + } + } + + .header-content { + height: $header-height; + + .title { + margin: 0; + overflow: hidden; + font-size: 19px; + line-height: $header-height; + font-weight: normal; + color: #4c4e54; + text-overflow: ellipsis; + vertical-align: top; + white-space: nowrap; + + a { + color: #4c4e54; + &:hover { + text-decoration: underline; + } + } + } + + .navbar-collapse { + float: right; + border-top: none; + } + } + + .search { + margin-right: 10px; + margin-left: 10px; + margin-top: ($header-height - 36) / 2; + + form { + margin: 0; + padding: 0; + } + + .search-input { + width: 220px; + background-image: image-url("icon-search.png"); + background-repeat: no-repeat; + background-position: 195px; + @include input-big; + + &:focus { + @include box-shadow(none); + outline: none; + border-color: #DDD; + background-color: #FFF; + } + } + } +} + +@mixin collapsed-header { + margin-left: $sidebar_collapsed_width; +} + +@media (max-width: $screen-md-max) { + .header-collapsed, .header-expanded { + @include collapsed-header; + } +} + +@media(min-width: $screen-md-max) { + .header-collapsed { + @include collapsed-header; + } + + .header-expanded { + margin-left: $sidebar_width; + } +} + +@media (max-width: $screen-xs-max) { + header .container-fluid { + font-size: 18px; + + .navbar-nav { + margin: 0px; + float: none !important; + + .visible-xs, .visable-sm { + display: table-cell !important; + } + } + + .navbar-collapse { + padding-left: 5px; + + li { + display: table-cell; + width: 1%; + + a { + margin-left: 8px !important; + } + } + } + } +} diff --git a/app/assets/stylesheets/framework/highlight.scss b/app/assets/stylesheets/framework/highlight.scss new file mode 100644 index 00000000000..2e13ee842e0 --- /dev/null +++ b/app/assets/stylesheets/framework/highlight.scss @@ -0,0 +1,70 @@ +.file-content.code { + border: none; + box-shadow: none; + margin: 0px; + padding: 0px; + table-layout: fixed; + + pre { + padding: 10px; + border: none; + border-radius: 0; + font-family: $monospace_font; + font-size: $code_font_size !important; + line-height: $code_line_height !important; + margin: 0; + overflow: auto; + overflow-y: hidden; + white-space: pre; + word-wrap: normal; + + code { + font-family: $monospace_font; + white-space: pre; + word-wrap: normal; + padding: 0; + + .line { + display: inline; + } + } + } + + .line-numbers { + padding: 10px; + text-align: right; + float: left; + + a { + font-family: $monospace_font; + display: block; + font-size: $code_font_size !important; + line-height: $code_line_height !important; + white-space: nowrap; + + i { + visibility: hidden; + @extend .pull-left; + } + + &:hover i { + visibility: visible; + } + } + } +} + +.note-text .code { + border: none; + box-shadow: none; + background: $background-color; + padding: 1em; + overflow-x: auto; + + code { + font-family: $monospace_font; + white-space: pre; + word-wrap: normal; + padding: 0; + } +} diff --git a/app/assets/stylesheets/framework/issue_box.scss b/app/assets/stylesheets/framework/issue_box.scss new file mode 100644 index 00000000000..93377e45e70 --- /dev/null +++ b/app/assets/stylesheets/framework/issue_box.scss @@ -0,0 +1,35 @@ +/** + * Issue box for showing Open/Closed state: + * Used for Issue#show page, MergeRequest#show page etc + * + */ + +.issue-box { + @include border-radius(2px); + + display: inline-block; + padding: 10px $gl-padding; + font-weight: normal; + margin-right: 10px; + font-size: $gl-font-size; + + &.issue-box-closed { + background-color: $gl-danger; + color: #FFF; + } + + &.issue-box-merged { + background-color: $gl-primary; + color: #FFF; + } + + &.issue-box-open { + background-color: #019875; + color: #FFF; + } + + &.issue-box-expired { + background: #cea61b; + color: #FFF; + } +} diff --git a/app/assets/stylesheets/framework/jquery.scss b/app/assets/stylesheets/framework/jquery.scss new file mode 100644 index 00000000000..871b808bad4 --- /dev/null +++ b/app/assets/stylesheets/framework/jquery.scss @@ -0,0 +1,55 @@ +.ui-widget { + font-family: $regular_font; + font-size: $font-size-base; + + &.ui-datepicker-inline { + border: 1px solid #DDD; + padding: 10px; + width: 270px; + + .ui-datepicker-header { + background: #FFF; + border-color: #DDD; + } + + .ui-datepicker-calendar td a { + padding: 5px; + text-align: center; + } + } + + &.ui-autocomplete { + border-color: #DDD; + padding: 0; + margin-top: 2px; + z-index: 1001; + + .ui-menu-item a { + padding: 4px 10px; + } + } + + .ui-state-default { + border: 1px solid #FFF; + background: #FFF; + color: #777; + } + + .ui-state-highlight { + border: 1px solid #EEE; + background: #EEE; + } + + .ui-state-active { + border: 1px solid $gl-primary; + background: $gl-primary; + color: #FFF; + } + + .ui-state-hover, + .ui-state-focus { + border: 1px solid $hover; + background: $hover; + color: #333; + } +} diff --git a/app/assets/stylesheets/framework/layout.scss b/app/assets/stylesheets/framework/layout.scss new file mode 100644 index 00000000000..c7b3b60e769 --- /dev/null +++ b/app/assets/stylesheets/framework/layout.scss @@ -0,0 +1,27 @@ +html { + overflow-y: scroll; + + &.touch .tooltip { display: none !important; } + + body { + padding-top: $header-height; + text-rendering: geometricPrecision; + } +} + +.container { + padding-top: 0; + z-index: 5; +} + +.container .content { + margin: 0 0; +} + +.navless-container { + margin-top: 30px; +} + +.container-limited { + max-width: $fixed-layout-width; +} diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss new file mode 100644 index 00000000000..3bfed8de772 --- /dev/null +++ b/app/assets/stylesheets/framework/lists.scss @@ -0,0 +1,125 @@ +/** + * Well styled list + * + */ +.well-list { + margin: 0; + padding: 0; + list-style: none; + + li { + padding: 10px 15px; + min-height: 20px; + border-bottom: 1px solid #eee; + border-bottom: 1px solid rgba(0, 0, 0, 0.05); + + &:after { + content: " "; + display: table; + clear: both; + } + + &.disabled { + color: #888; + } + + &.unstyled { + &:hover { + background: none; + } + } + + &.warning-row { + background-color: #fcf8e3; + border-color: #faebcc; + color: #8a6d3b; + } + + &.smoke { background-color: $background-color; } + + &:hover { + background: $hover; + } + + &:last-child { + border-bottom: none; + + &.bottom { + background: $background-color; + } + } + + .list-item-name { + float: left; + position: relative; + top: 3px; + } + + p { + padding-top: 1px; + margin: 0; + color: $gray-dark; + img { + position: relative; + top: 3px; + } + } + + .well-title { + font-size: $list-font-size; + line-height: 18px; + } + } +} + +ol, ul { + &.styled { + li { + padding: 2px; + } + } +} + +/** light list with border-bottom between li **/ +ul.bordered-list { + @include basic-list; + + &.top-list { + li:first-child { + padding-top: 0; + + h4, h5 { + margin-top: 0; + } + } + } +} + +li.task-list-item { + list-style-type: none; +} + +ul.content-list { + @include basic-list; + + margin: 0; + padding: 0; + + > li { + padding: $gl-padding; + border-color: #f1f2f4; + margin-left: -$gl-padding; + margin-right: -$gl-padding; + color: $gl-gray; + + .avatar { + margin-right: 15px; + } + + .controls { + padding-top: 10px; + float: right; + } + } +} + diff --git a/app/assets/stylesheets/framework/markdown_area.scss b/app/assets/stylesheets/framework/markdown_area.scss new file mode 100644 index 00000000000..ed0333d2336 --- /dev/null +++ b/app/assets/stylesheets/framework/markdown_area.scss @@ -0,0 +1,115 @@ +.div-dropzone-wrapper { + .div-dropzone { + position: relative; + padding: 0; + border: 0; + margin-bottom: 5px; + + .div-dropzone-focus { + border-color: #66afe9 !important; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6) !important; + outline: 0 !important; + } + + .div-dropzone-hover { + position: absolute; + top: 50%; + left: 50%; + margin-top: -0.5em; + margin-left: -0.6em; + opacity: 0; + font-size: 50px; + transition: opacity 200ms ease-in-out; + pointer-events: none; + } + + .div-dropzone-spinner { + position: absolute; + top: 100%; + left: 100%; + margin-top: -1.1em; + margin-left: -1.1em; + opacity: 0; + font-size: 30px; + transition: opacity 200ms ease-in-out; + } + + .div-dropzone-icon { + display: block; + text-align: center; + font-size: inherit; + } + + .div-dropzone-progress { + position: absolute; + top: 7px; + left: -40px; + width: 35px; + font-size: 13px; + text-align: right; + } + + .dz-preview { + display: none; + } + } +} + +.div-dropzone-alert { + margin-top: 5px; + margin-bottom: 0; + transition: opacity 200ms ease-in-out; +} + +.md-area { + position: relative; +} + +.md-header { + ul { + float: left; + margin-bottom: 1px; + } +} + +.referenced-users { + padding: 10px 0; + color: #999; + margin-left: 10px; + margin-top: 1px; + margin-right: 130px; +} + +.md-preview-holder { + background: #FFF; + border: 1px solid #ddd; + min-height: 169px; + padding: 5px; + box-shadow: none; +} + +.new_note, +.edit_note, +.issuable-description, +.milestone-description, +.wiki-content, +.merge-request-form { + .nav-tabs { + margin-bottom: 0; + border: none; + + li a, + li.active a { + border: 1px solid #DDD; + } + } +} + +.markdown-area { + background: #FFF; + border: 1px solid #ddd; + min-height: 140px; + padding: 5px; + box-shadow: none; + width: 100%; +} diff --git a/app/assets/stylesheets/framework/mixins.scss b/app/assets/stylesheets/framework/mixins.scss new file mode 100644 index 00000000000..c74a6d39824 --- /dev/null +++ b/app/assets/stylesheets/framework/mixins.scss @@ -0,0 +1,301 @@ +/** + * Generic mixins + */ + @mixin box-shadow($shadow) { + -webkit-box-shadow: $shadow; + -moz-box-shadow: $shadow; + -ms-box-shadow: $shadow; + -o-box-shadow: $shadow; + box-shadow: $shadow; +} + +@mixin border-radius($radius) { + -webkit-border-radius: $radius; + -moz-border-radius: $radius; + -ms-border-radius: $radius; + -o-border-radius: $radius; + border-radius: $radius; +} + +@mixin border-radius-left($radius) { + @include border-radius($radius 0 0 $radius) +} + +@mixin border-radius-right($radius) { + @include border-radius(0 0 $radius $radius) +} + +@mixin linear-gradient($from, $to) { + background-image: -webkit-gradient(linear, 0 0, 0 100%, from($from), to($to)); + background-image: -webkit-linear-gradient($from, $to); + background-image: -moz-linear-gradient($from, $to); + background-image: -ms-linear-gradient($from, $to); + background-image: -o-linear-gradient($from, $to); +} + +@mixin transition($transition) { + -webkit-transition: $transition; + -moz-transition: $transition; + -ms-transition: $transition; + -o-transition: $transition; + transition: $transition; +} + +/** + * Prefilled mixins + * Mixins with fixed values + */ + +@mixin shade { + @include box-shadow(0 0 3px #ddd); +} + +@mixin solid-shade { + @include box-shadow(0 0 0 3px #f1f1f1); +} + +@mixin md-typography { + color: $md-text-color; + + a { + color: $md-link-color; + } + + img { + max-width: 100%; + } + + *:first-child { + margin-top: 0; + } + + code { + font-family: $monospace_font; + white-space: pre; + word-wrap: normal; + padding: 1px 2px; + } + + kbd { + display: inline-block; + padding: 3px 5px; + font-size: 11px; + line-height: 10px; + color: #555; + vertical-align: middle; + background-color: #FCFCFC; + border-width: 1px; + border-style: solid; + border-color: #CCC #CCC #BBB; + border-image: none; + border-radius: 3px; + box-shadow: 0px -1px 0px #BBB inset; + } + + h1 { + font-size: 1.3em; + font-weight: 600; + margin: 24px 0 12px 0; + padding: 0 0 10px 0; + border-bottom: 1px solid #e7e9ed; + color: #313236; + } + + h2 { + font-size: 1.2em; + font-weight: 600; + margin: 24px 0 12px 0; + color: #313236; + } + + h3 { + margin: 24px 0 12px 0; + font-size: 1.25em; + } + + h4 { + margin: 24px 0 12px 0; + font-size: 1.1em; + } + + h5 { + margin: 24px 0 12px 0; + font-size: 1em; + } + + h6 { + margin: 24px 0 12px 0; + font-size: 0.90em; + } + + blockquote { + padding: 8px 21px; + margin: 12px 0 12px; + border-left: 3px solid #e7e9ed; + } + + blockquote p { + color: #7f8fa4 !important; + font-size: 15px; + line-height: 1.5; + } + + p { + color:#5c5d5e; + margin:6px 0 0 0; + } + + table { + @extend .table; + @extend .table-bordered; + margin: 12px 0 12px 0; + color: #5c5d5e; + th { + background: #f8fafc; + } + } + + pre { + margin: 12px 0 12px 0 !important; + background-color: #f8fafc !important; + font-size: 13px !important; + color: #5b6169 !important; + line-height: 1.6em !important; + @include border-radius(2px); + } + + p > code { + font-weight: inherit; + } + + + ul { + color: #5c5d5e; + } + + li { + line-height: 1.6em; + } + + a[href*="/uploads/"], a[href*="storage.googleapis.com/google-code-attachments/"] { + &:before { + margin-right: 4px; + + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + content: "\f0c6"; + } + + &:hover:before { + text-decoration: none; + } + } +} + + +@mixin str-truncated($max_width: 82%) { + display: inline-block; + overflow: hidden; + text-overflow: ellipsis; + vertical-align: top; + white-space: nowrap; + max-width: $max_width; +} + +/* + * Base mixin for lists in GitLab + */ +@mixin basic-list { + margin: 5px 0px; + padding: 0px; + list-style: none; + + > li { + padding: 10px 0; + border-bottom: 1px solid #EEE; + overflow: hidden; + display: block; + margin: 0px; + + &:last-child { + border-bottom: none; + } + + &.active { + background: #f9f9f9; + a { + font-weight: 600; + } + } + + &.hide { + display: none; + } + + &.light { + a { + color: $gl-gray; + } + } + } +} + +@mixin input-big { + height: 36px; + padding: 5px 10px; + font-size: 16px; + line-height: 24px; + color: #7f8fa4; + background-color: #fff; + border-color: #e7e9ed; +} + +@mixin btn-big { + height: 36px; + padding: 5px 10px; + font-size: 16px; + line-height: 24px; +} + +@mixin nav-menu { + padding: 0; + margin: 0; + list-style: none; + margin-top: 5px; + height: 56px; + + li { + display: inline-block; + + a { + padding: 14px; + font-size: 17px; + line-height: 28px; + color: #7f8fa4; + border-bottom: 2px solid transparent; + + &:hover, &:active, &:focus { + text-decoration: none; + } + } + + &.active a { + color: #4c4e54; + border-bottom: 2px solid #1cacfc; + } + + .badge { + font-weight: normal; + background-color: #fff; + background-color: #eee; + color: #78a; + } + } +} + +.fa-align { + top: 20px; + position: relative; +} diff --git a/app/assets/stylesheets/framework/mobile.scss b/app/assets/stylesheets/framework/mobile.scss new file mode 100644 index 00000000000..36ae126f865 --- /dev/null +++ b/app/assets/stylesheets/framework/mobile.scss @@ -0,0 +1,139 @@ +/** Common mobile (screen XS, SM) styles **/ +@media (max-width: $screen-xs-max) { + .container .content { + margin-top: 20px; + } + + .container-fluid { + padding-left: 5px; + padding-right: 5px; + } + + .nav.nav-tabs > li > a { + padding: 10px; + font-size: 12px; + margin-right: 3px; + + .badge { + display: none; + } + } + + .referenced-users { + margin-right: 0; + } + + .issues-filters, + .dash-projects-filters, + .check-all-holder { + display: none; + } + + .rss-btn { + display: none !important; + } + + .project-home-links { + display: none; + } + + .project-avatar { + display: none; + } + + .project-home-panel { + padding-left: 0 !important; + + .project-avatar { + display: block; + } + + .project-home-desc { + font-size: 21px; + } + + .project-repo-buttons, + .git-clone-holder { + display: none; + } + } + + .project-stats { + display: none; + } + + .container .title { + padding-left: 15px !important; + } + + .issue-info, .merge-request-info { + display: none; + } + + .issue-details { + .creator, + .page-title .btn-close { + display: none; + } + } + + %ul.notes .note-role, .note-actions { + display: none; + } + + .center-top-menu { + height: 45px; + + li a { + font-size: 14px; + padding: 19px 10px; + } + } + + .projects-search-form { + margin: 0 -5px !important; + + .btn { + display: none; + } + } +} + +@media (max-width: $screen-sm-max) { + .issues-filters { + .milestone-filter, .labels-filter { + display: none; + } + } + + .page-title { + .note_created_ago, .new-issue-link { + display: none; + } + } + + .issue_edited_ago, .note_edited_ago { + display: none; + } + + aside { + display: none; + } + + .show-aside { + display: block !important; + } +} + +.show-aside { + display: none; + position: fixed; + right: 0px; + top: 30%; + padding: 5px 15px; + background: #EEE; + font-size: 20px; + color: #777; + z-index: 100; + @include box-shadow(0 1px 2px #DDD); +} diff --git a/app/assets/stylesheets/framework/pagination.scss b/app/assets/stylesheets/framework/pagination.scss new file mode 100644 index 00000000000..6677f94dafd --- /dev/null +++ b/app/assets/stylesheets/framework/pagination.scss @@ -0,0 +1,34 @@ +.gl-pagination { + border-top: 1px solid $border-color; + background-color: $background-color; + margin: -$gl-padding; + margin-top: 0; + + .pagination { + padding: 0; + margin: 0; + display: block; + + li.first, + li.last, + li.next, + li.prev { + > a { + color: $link-color; + + &:hover { + color: #fff; + } + } + } + + li > a, + li > span { + border: none; + margin: 0; + @include border-radius(0 !important); + padding: 13px 19px; + border-right: 1px solid $border-color; + } + } +} diff --git a/app/assets/stylesheets/framework/selects.scss b/app/assets/stylesheets/framework/selects.scss new file mode 100644 index 00000000000..cba621635b6 --- /dev/null +++ b/app/assets/stylesheets/framework/selects.scss @@ -0,0 +1,146 @@ +/** Select2 selectbox style override **/ +.select2-container, .select2-container.select2-drop-above { + .select2-choice { + background: #FFF; + border-color: #DDD; + height: 42px; + padding: 8px $gl-padding; + font-size: $gl-font-size; + line-height: 1.42857143; + + @include border-radius(2px); + + .select2-arrow { + background: #FFF; + border-left: none; + padding-top: 5px; + } + } +} + +.select2-container .select2-choice, .select2-container.select2-drop-above .select2-choice{ + color: #7f8fa4; + border: 1px solid #e7e9ed; +} + +.select2-drop { + @include box-shadow(rgba(76, 86, 103, 0.247059) 0px 0px 1px 0px, rgba(31, 37, 50, 0.317647) 0px 2px 18px 0px); + @include border-radius (0px); + + padding: 16px; + border: none !important; +} + +.select2-results .select2-result-label { + padding: 16px; +} + +.select2-drop{ + color: #7f8fa4; +} + +.select2-highlighted { + background: #3084bb !important; +} + +.select2-results li.select2-result-with-children > .select2-result-label { + font-weight: 600; + color: #313236; +} + + +.select2-container-multi .select2-choices { + @include border-radius(2px); + border-color: #CCC; +} + +.select2-container-multi .select2-choices .select2-search-field input { + padding: 8px 14px; + font-size: 13px; + line-height: 18px; + height: auto; +} + +.select2-drop-active { + border: 1px solid #BBB !important; + margin-top: 4px; + font-size: 13px; + + &.select2-drop-above { + margin-bottom: 8px; + } + + .select2-search input { + background: #fafafa; + border-color: #DDD; + } + + .select2-results { + max-height: 350px; + .select2-highlighted { + background: $gl-primary; + } + } +} + +.select2-container { + width: 100% !important; +} + +/** Branch/tag selector **/ +.project-refs-form .select2-container { + width: 160px !important; +} + +.ajax-users-dropdown, .ajax-project-users-dropdown { + .select2-search { + padding-top: 2px; + } +} + +.ajax-users-select { + width: 400px; + + &.input-large { + width: 210px; + } + + &.input-clamp { + max-width: 100%; + } +} + +.group-result { + .group-image { + float: left; + } + .group-name { + font-weight: bold; + } + .group-path { + color: #999; + } +} + +.user-result { + .user-image { + float: left; + } + .user-name { + } +} + +.namespace-result { + .namespace-kind { + color: #AAA; + font-weight: normal; + } + .namespace-path { + margin-left: 10px; + font-weight: bolder; + } +} + +.ajax-users-dropdown { + min-width: 250px !important; +} diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss new file mode 100644 index 00000000000..c5ea3aca7ca --- /dev/null +++ b/app/assets/stylesheets/framework/sidebar.scss @@ -0,0 +1,267 @@ +.page-with-sidebar { + .sidebar-wrapper { + position: fixed; + top: 0; + bottom: 0; + overflow-y: auto; + overflow-x: hidden; + left: 0; + height: 100%; + transition-duration: .3s; + } +} + +.sidebar-wrapper { + z-index: 99; + background: $background-color; + transition-duration: .3s; +} + +.content-wrapper { + min-height: 100vh; + width: 100%; + padding: 20px; + background: #EAEBEC; + + .container-fluid { + background: #FFF; + padding: $gl-padding; + min-height: 90vh; + + &.container-blank { + background: none; + padding: 0; + border: none; + } + } +} + +.nav-sidebar { + margin-top: 14 + $header-height; + margin-bottom: 100px; + transition-duration: .3s; + list-style: none; + overflow: hidden; + + &.navbar-collapse { + padding: 0px !important; + } + + li { + width: $sidebar_width; + + &.separate-item { + padding-top: 10px; + margin-top: 10px; + } + + a { + padding: 7px 15px; + font-size: $gl-font-size; + line-height: 24px; + color: $gray; + display: block; + text-decoration: none; + padding-left: 22px; + font-weight: normal; + + &:hover { + text-decoration: none; + } + + &:active, &:focus { + text-decoration: none; + } + + i { + width: 16px; + color: $gray-light; + margin-right: 13px; + } + + .count { + float: right; + background: #eee; + padding: 0px 8px; + @include border-radius(6px); + } + } + } +} + +.sidebar-subnav { + margin-left: 0px; + padding-left: 0px; + + li { + list-style: none; + } +} + +@mixin expanded-sidebar { + padding-left: $sidebar_width; + transition-duration: .3s; + + .sidebar-wrapper { + width: $sidebar_width; + + .nav-sidebar { + width: $sidebar_width; + } + + .nav-sidebar li a{ + width: 230px; + + &.back-link { + i { + visibility: hidden; + } + } + } + } +} + +@mixin folded-sidebar { + padding-left: 60px; + transition-duration: .3s; + + .sidebar-wrapper { + width: $sidebar_collapsed_width; + + .header-logo { + width: $sidebar_collapsed_width; + + a { + padding-left: 12px; + + .gitlab-text-container { + display: none; + } + } + } + + .nav-sidebar { + width: $sidebar_collapsed_width; + + li a { + span { + display: none; + } + } + } + + .collapse-nav a { + width: $sidebar_collapsed_width; + } + + .sidebar-user { + padding-left: 12px; + width: $sidebar_collapsed_width; + + .username { + display: none; + } + } + } +} + +.collapse-nav a { + width: $sidebar_width; + position: fixed; + bottom: 0; + left: 0; + font-size: 13px; + background: transparent; + height: 40px; + text-align: center; + line-height: 40px; + transition-duration: .3s; +} + +.collapse-nav a:hover { + text-decoration: none; + background: #f2f6f7; +} + +@media (max-width: $screen-md-max) { + .page-sidebar-collapsed { + @include folded-sidebar; + } + + .page-sidebar-expanded { + @include folded-sidebar; + } + + .collapse-nav { + display: none; + } +} + +@media(min-width: $screen-md-max) { + .page-sidebar-collapsed { + @include folded-sidebar; + } + + .page-sidebar-expanded { + @include expanded-sidebar; + } +} + +.sidebar-user { + padding: 9px 22px; + position: fixed; + bottom: 40px; + width: $sidebar_width; + overflow: hidden; + transition-duration: .3s; + + .username { + margin-left: 10px; + width: $sidebar_width - 2 * 10px; + font-size: 16px; + line-height: 34px; + } +} + +.sidebar-wrapper { + .header-logo { + border-bottom: 1px solid transparent; + float: left; + height: $header-height; + width: $sidebar_width; + overflow: hidden; + transition-duration: .3s; + + a { + float: left; + height: $header-height; + width: 100%; + padding: 10px 22px; + overflow: hidden; + + img { + width: 36px; + height: 36px; + float: left; + } + + .gitlab-text-container { + width: 230px; + + h3 { + width: 158px; + float: left; + margin: 0; + margin-left: 14px; + font-size: 19px; + line-height: 41px; + font-weight: normal; + } + } + } + + &:hover { + background-color: #EEE; + } + } +} diff --git a/app/assets/stylesheets/framework/tables.scss b/app/assets/stylesheets/framework/tables.scss new file mode 100644 index 00000000000..a66e45577de --- /dev/null +++ b/app/assets/stylesheets/framework/tables.scss @@ -0,0 +1,20 @@ +table { + &.table { + tr { + td, th { + padding: 8px 10px; + line-height: 20px; + vertical-align: middle; + } + th { + font-weight: normal; + font-size: 15px; + border-bottom: 1px solid $border-color !important; + } + td { + border-color: #F1F1F1 !important; + border-bottom: 1px solid; + } + } + } +} diff --git a/app/assets/stylesheets/framework/timeline.scss b/app/assets/stylesheets/framework/timeline.scss new file mode 100644 index 00000000000..bf21d7fce76 --- /dev/null +++ b/app/assets/stylesheets/framework/timeline.scss @@ -0,0 +1,70 @@ +.timeline { + @include basic-list; + + margin: 0; + padding: 0; + + .timeline-entry { + padding: $gl-padding; + border-color: #f1f2f4; + margin-left: -$gl-padding; + margin-right: -$gl-padding; + color: $gl-gray; + border-bottom: 1px solid #ECEEF1; + border-right: 1px solid #ECEEF1; + + &:last-child { + border-bottom: none; + } + + .avatar { + margin-right: 15px; + } + + .controls { + padding-top: 10px; + float: right; + } + } + + .note-text { + p:last-child { + margin-bottom: 0; + } + } + + .system-note { + .note-text { + color: $gl-gray !important; + } + } + + .diff-file { + border: 1px solid $border-color; + border-bottom: none; + margin-left: 0; + margin-right: 0; + } +} + +@media (max-width: $screen-xs-max) { + .timeline { + &:before { + background: none; + } + .timeline-entry .timeline-entry-inner { + .timeline-icon { + display: none; + } + + .timeline-content { + margin-left: 0; + } + } + } +} + +.discussion .timeline-entry { + margin: 0; + border-right: none; +} diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss new file mode 100644 index 00000000000..6a3cb49baae --- /dev/null +++ b/app/assets/stylesheets/framework/typography.scss @@ -0,0 +1,130 @@ +/** + * Headers + * + */ +body { + text-rendering:optimizeLegibility; + -webkit-text-shadow: rgba(255,255,255,0.01) 0 0 1px; +} + +.page-title { + margin-top: 0px; + line-height: 1.3; + font-size: 1.25em; + font-weight: 600; +} + +.page-title-empty { + margin-top: 0px; + line-height: 1.3; + font-size: 1.25em; + font-weight: 600; + margin: 12px 7px 12px 7px; +} + +h1, h2, h3, h4, h5, h6 { + color: $gl-header-color; + font-weight: 500; +} + +/** CODE **/ +pre { + font-family: $monospace_font; + + &.dark { + background: #333; + color: $background-color; + } + + &.plain-readme { + background: none; + border: none; + padding: 0; + margin: 0; + font-size: 14px; + } +} + +.monospace { + font-family: $monospace_font; +} + +code { + &.key-fingerprint { + background: $body-bg; + color: $text-color; + } +} + +a > code { + color: $link-color; +} + +/** + * Wiki typography + * + */ +.wiki { + @include md-typography; + + word-wrap: break-word; + padding: 7px; + + /* Link to current header. */ + h1, h2, h3, h4, h5, h6 { + position: relative; + + a.anchor { + // Setting `display: none` would prevent the anchor being scrolled to, so + // instead we set the height to 0 and it gets updated on hover. + height: 0; + } + + &:hover > a.anchor { + $size: 16px; + position: absolute; + right: 100%; + top: 50%; + margin-top: -$size/2; + margin-right: 0px; + padding-right: 20px; + display: inline-block; + width: $size; + height: $size; + background-image: image-url("icon-link.png"); + background-size: contain; + background-repeat: no-repeat; + } + } + + ul,ol { + padding: 0; + margin: 6px 0 6px 18px !important; + } + ol { + color: #5c5d5e; + } +} + +.md-area { + @include md-typography; +} + +.md { + @include md-typography; +} + +/** + * Textareas intended for GFM + * + */ +textarea.js-gfm-input { + font-family: $monospace_font; +} + +.md-preview { +} + +.strikethrough { + text-decoration: line-through; +} \ No newline at end of file diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss new file mode 100644 index 00000000000..eb9a2966389 --- /dev/null +++ b/app/assets/stylesheets/framework/variables.scss @@ -0,0 +1,98 @@ +$hover: #FFFAF1; +$gl-text-color: #54565B; +$gl-text-green: #4A2; +$gl-text-red: #D12F19; +$gl-text-orange: #D90; +$gl-header-color: #4c4e54; +$gl-link-color: #333c48; +$md-text-color: #444; +$md-link-color: #3084bb; +$nprogress-color: #c0392b; +$gl-font-size: 15px; +$list-font-size: 15px; +$sidebar_collapsed_width: 62px; +$sidebar_width: 230px; +$avatar_radius: 50%; +$code_font_size: 13px; +$code_line_height: 1.5; +$border-color: #dce0e6; +$background-color: #F7F8FA; +$header-height: 58px; +$fixed-layout-width: 1200px; +$gl-gray: #7f8fa4; +$gl-padding: 16px; +$gl-avatar-size: 46px; + +/* + * Color schema + */ + +$white-light: #FFFFFF; +$white-normal: #DCE0E5; +$white-dark: #E4E7ED; + +$gray-light: #F0F2F5; +$gray-normal: #DCE0E5; +$gray-dark: #E4E7ED; + +$green-light: #31AF64; +$green-normal: #2FAA60; +$green-dark: #2CA05B; + +$blue-light: #2EA8E5; +$blue-normal: #2D9FD8; +$blue-dark: #2897CE; + +$orange-light: #FC6443; +$orange-normal: #E75E40; +$orange-dark: #CE5237; + +$red-light: #F43263; +$red-normal: #E52C5A; +$red-dark: #D22852; + +$border-white-light: #E3E7EC; +$border-white-normal: #D6DAE2; +$border-white-dark: #C6CACF; + +$border-gray-light: #DCE0E5; +$border-gray-normal: #D6DAE2; +$border-gray-dark: #C6CACF; + +$border-green-light: #2FAA60; +$border-green-normal: #2CA05B; +$border-green-dark: #279654; + +$border-blue-light: #2D9FD8; +$border-blue-normal: #2897CE; +$border-blue-dark: #258DC1; + +$border-orange-light: #ED5C3D; +$border-orange-normal: #CE5237; +$border-orange-dark: #C14E35; + +$border-red-light: #E52C5A; +$border-red-normal: #D22852; +$border-red-dark: #CA264F; + + +/* + * State colors: + */ +$gl-primary: $blue-normal; +$gl-success: $green-normal; +$gl-info: $blue-normal; +$gl-warning: $orange-normal; +$gl-danger: $red-normal; + +/* + * Commit Diff Colors + */ +$added: #63c363; +$deleted: #f77; + +/* + * Fonts + */ +$monospace_font: 'Menlo', 'Liberation Mono', 'Consolas', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Courier New', 'andale mono', 'lucida console', monospace; +$regular_font: 'Source Sans Pro', "Helvetica Neue", Helvetica, Arial, sans-serif; diff --git a/app/assets/stylesheets/framework/zen.scss b/app/assets/stylesheets/framework/zen.scss new file mode 100644 index 00000000000..32e2c020e06 --- /dev/null +++ b/app/assets/stylesheets/framework/zen.scss @@ -0,0 +1,86 @@ +.zennable { + .zen-toggle-comment { + display: none; + } + + .zen-enter-link { + color: $gl-gray; + position: absolute; + top: 0px; + right: 4px; + line-height: 40px; + } + + .zen-leave-link { + display: none; + color: $gl-text-color; + position: absolute; + top: 10px; + right: 10px; + padding: 5px; + font-size: 36px; + + &:hover { + color: #111; + } + } + + // Hide the Enter link when we're in Zen mode + input:checked ~ .zen-backdrop .zen-enter-link { + display: none; + } + + // Show the Leave link when we're in Zen mode + input:checked ~ .zen-backdrop .zen-leave-link { + display: block; + position: absolute; + top: 0; + } + + input:checked ~ .zen-backdrop { + background-color: white; + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + z-index: 1031; + + textarea { + border: none; + box-shadow: none; + border-radius: 0; + color: #000; + font-size: 20px; + line-height: 26px; + padding: 30px; + display: block; + outline: none; + resize: none; + height: 100vh; + max-width: 900px; + margin: 0 auto; + } + } + + // Make the color of the placeholder text in the Zenned-out textarea darker, + // so it becomes visible + + input:checked ~ .zen-backdrop textarea::-webkit-input-placeholder { + color: #A8A8A8; + } + + input:checked ~ .zen-backdrop textarea:-moz-placeholder { + color: #A8A8A8; + opacity: 1; + } + + input:checked ~ .zen-backdrop textarea::-moz-placeholder { + color: #A8A8A8; + opacity: 1; + } + + input:checked ~ .zen-backdrop textarea:-ms-input-placeholder { + color: #A8A8A8; + } +} diff --git a/app/assets/stylesheets/generic/avatar.scss b/app/assets/stylesheets/generic/avatar.scss deleted file mode 100644 index 36e582d4854..00000000000 --- a/app/assets/stylesheets/generic/avatar.scss +++ /dev/null @@ -1,49 +0,0 @@ -.avatar { - float: left; - margin-right: 12px; - width: 40px; - height: 40px; - padding: 0; - @include border-radius($avatar_radius); - - &.avatar-inline { - float: none; - margin-left: 4px; - margin-bottom: 2px; - - &.s16 { margin-right: 4px; } - &.s24 { margin-right: 4px; } - } - - &.group-avatar, &.project-avatar, &.avatar-tile { - @include border-radius(0px); - } - - &.s16 { width: 16px; height: 16px; margin-right: 6px; } - &.s24 { width: 24px; height: 24px; margin-right: 8px; } - &.s26 { width: 26px; height: 26px; margin-right: 8px; } - &.s32 { width: 32px; height: 32px; margin-right: 10px; } - &.s36 { width: 36px; height: 36px; margin-right: 10px; } - &.s46 { width: 46px; height: 46px; margin-right: 15px; } - &.s48 { width: 48px; height: 48px; margin-right: 10px; } - &.s60 { width: 60px; height: 60px; margin-right: 12px; } - &.s90 { width: 90px; height: 90px; margin-right: 15px; } - &.s110 { width: 110px; height: 110px; margin-right: 15px; } - &.s140 { width: 140px; height: 140px; margin-right: 20px; } - &.s160 { width: 160px; height: 160px; margin-right: 20px; } -} - -.identicon { - text-align: center; - vertical-align: top; - - &.s16 { font-size: 12px; line-height: 1.33; } - &.s24 { font-size: 14px; line-height: 1.8; } - &.s26 { font-size: 20px; line-height: 1.33; } - &.s32 { font-size: 22px; line-height: 32px; } - &.s60 { font-size: 32px; line-height: 60px; } - &.s90 { font-size: 36px; line-height: 90px; } - &.s110 { font-size: 40px; line-height: 112px; font-weight: 300; } - &.s140 { font-size: 72px; line-height: 140px; } - &.s160 { font-size: 96px; line-height: 160px; } -} diff --git a/app/assets/stylesheets/generic/blocks.scss b/app/assets/stylesheets/generic/blocks.scss deleted file mode 100644 index 6ce34b5c3e8..00000000000 --- a/app/assets/stylesheets/generic/blocks.scss +++ /dev/null @@ -1,62 +0,0 @@ -.light-well { - background-color: #f8fafc; - padding: 15px; -} - -.centered-light-block { - text-align: center; - color: $gl-gray; - margin: 20px; -} - -.nothing-here-block { - text-align: center; - padding: 20px; - color: $gl-gray; - font-weight: normal; - font-size: 16px; - line-height: 36px; -} - -.gray-content-block { - margin: -$gl-padding; - background-color: $background-color; - padding: $gl-padding; - margin-bottom: 0px; - border-top: 1px solid $border-color; - border-bottom: 1px solid $border-color; - color: $gl-gray; - - &.top-block { - border-top: none; - } - - &.middle-block { - margin-top: 0; - margin-bottom: 0; - } - - &.clear-block { - margin-bottom: $gl-padding - 1px; - padding-bottom: $gl-padding; - } - - &.second-block { - margin-top: -1px; - margin-bottom: 0; - } - - &.footer-block { - margin-top: 0; - border-bottom: none; - margin-bottom: -$gl-padding; - } - - .title { - color: $gl-text-color; - } - - .oneline { - line-height: 42px; - } -} diff --git a/app/assets/stylesheets/generic/buttons.scss b/app/assets/stylesheets/generic/buttons.scss deleted file mode 100644 index 11acbe3adfa..00000000000 --- a/app/assets/stylesheets/generic/buttons.scss +++ /dev/null @@ -1,163 +0,0 @@ -@mixin btn-default { - @include border-radius(2px); - border-width: 1px; - border-style: solid; - text-transform: uppercase; - font-size: 13px; - font-weight: 600; - line-height: 18px; - padding: 11px 16px; - letter-spacing: .4px; - - &:focus, - &:active { - outline: none; - @include box-shadow(inset 0 0 4px rgba(0, 0, 0, 0.12)); - } -} - -@mixin btn-middle { - @include btn-default; - @include border-radius(2px); - padding: 11px 24px; -} - -@mixin btn-color($light, $border-light, $normal, $border-normal, $dark, $border-dark, $color) { - background-color: $light; - border-color: $border-light; - color: $color; - - &:hover, - &:focus { - background-color: $normal; - border-color: $border-normal; - color: $color; - } - - &:active { - @include box-shadow (inset 0 0 4px rgba(0, 0, 0, 0.12)); - - background-color: $dark; - border-color: $border-dark; - color: $color; - } -} - -@mixin btn-green { - @include btn-color($green-light, $border-green-light, $green-normal, $border-green-normal, $green-dark, $border-green-dark, #FFFFFF); -} - -@mixin btn-blue { - @include btn-color($blue-light, $border-blue-light, $blue-normal, $border-blue-normal, $blue-dark, $border-blue-dark, #FFFFFF); -} - -@mixin btn-orange { - @include btn-color($orange-light, $border-orange-light, $orange-normal, $border-orange-normal, $orange-dark, $border-orange-dark, #FFFFFF); -} - -@mixin btn-red { - @include btn-color($red-light, $border-red-light, $red-normal, $border-red-normal, $red-dark, $border-red-dark, #FFFFFF); -} - -@mixin btn-gray { - @include btn-color($gray-light, $border-gray-light, $gray-normal, $border-gray-normal, $gray-dark, $border-gray-dark, #313236); -} - -@mixin btn-white { - @include btn-color($white-light, $border-white-light, $white-normal, $border-white-normal, $white-dark, $border-white-dark, #313236); -} - -.btn { - @include btn-default; - @include btn-white; - - &.btn-success, - &.btn-new, - &.btn-create, - &.btn-save, - &.btn-green { - @include btn-green; - } - - &.btn-gray { - @include btn-gray; - } - - &.btn-primary, - &.btn-info { - @include btn-blue; - } - - &.btn-warning { - @include btn-orange; - } - - &.btn-danger, - &.btn-remove, - &.btn-red { - @include btn-red; - } - - &.btn-cancel { - float: right; - } - - &.btn-close { - color: $gl-danger; - border-color: $gl-danger; - &:hover { - color: #B94A48; - } - } - - &.btn-reopen { - color: $gl-success; - border-color: $gl-success; - &:hover { - color: #468847; - } - } - - &.btn-grouped { - margin-right: 7px; - float: left; - &:last-child { - margin-right: 0px; - } - } -} - -.btn-block { - width: 100%; - margin: 0; - margin-bottom: 15px; - &.btn { - padding: 6px 0; - } -} - -.btn-group { - &.btn-grouped { - margin-right: 7px; - float: left; - &:last-child { - margin-right: 0px; - } - } -} - -.btn-group-next { - .btn { - padding: 9px 0px; - font-size: 15px; - color: #7f8fa4; - border-color: #e7e9ed; - width: 140px; - - &.active { - border-color: $gl-info; - background: $gl-info; - color: #fff; - } - } -} diff --git a/app/assets/stylesheets/generic/calendar.scss b/app/assets/stylesheets/generic/calendar.scss deleted file mode 100644 index a36fefe22c5..00000000000 --- a/app/assets/stylesheets/generic/calendar.scss +++ /dev/null @@ -1,90 +0,0 @@ -.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; - } - } -} -/** -* This overwrites the default values of the cal-heatmap gem -*/ -.calendar { - .qi { - background-color: #999; - fill: #fff; - } - - .q1 { - background-color: #dae289; - fill: #ededed; - } - - .q2 { - background-color: #cedb9c; - fill: #ACD5F2; - } - - .q3 { - background-color: #b5cf6b; - fill: #7FA8D1; - } - - .q4 { - background-color: #637939; - fill: #49729B; - } - - .q5 { - background-color: #3b6427; - fill: #254E77; - } - - .domain-background { - fill: none; - shape-rendering: crispedges; - } - - .ch-tooltip { - position: absolute; - display: none; - margin-top: 22px; - margin-left: 1px; - font-size: 13px; - padding: 3px; - font-weight: 550; - background-color: #222; - span { - position: absolute; - width: 200px; - text-align: center; - visibility: hidden; - border-radius: 10px; - &:after { - content: ''; - position: absolute; - top: 100%; - left: 50%; - margin-left: -8px; - width: 0; - height: 0; - border-top: 8px solid #000000; - border-right: 8px solid transparent; - border-left: 8px solid transparent; - } - } - } -} diff --git a/app/assets/stylesheets/generic/callout.scss b/app/assets/stylesheets/generic/callout.scss deleted file mode 100644 index f1699d21c9b..00000000000 --- a/app/assets/stylesheets/generic/callout.scss +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Callouts from Bootstrap3 docs - * - * Not quite alerts, but custom and helpful notes for folks reading the docs. - * Requires a base and modifier class. - */ - -/* Common styles for all types */ -.bs-callout { - margin: 20px 0; - padding: 20px; - border-left: 3px solid #eee; - color: #666; - background: #f9f9f9; -} -.bs-callout h4 { - margin-top: 0; - margin-bottom: 5px; -} -.bs-callout p:last-child { - margin-bottom: 0; -} - -/* Variations */ -.bs-callout-danger { - background-color: #fdf7f7; - border-color: #eed3d7; - color: #b94a48; -} -.bs-callout-warning { - background-color: #faf8f0; - border-color: #faebcc; - color: #8a6d3b; -} -.bs-callout-info { - background-color: #f4f8fa; - border-color: #bce8f1; - color: #34789a; -} -.bs-callout-success { - background-color: #dff0d8; - border-color: #5cA64d; - color: #3c763d; -} - diff --git a/app/assets/stylesheets/generic/common.scss b/app/assets/stylesheets/generic/common.scss deleted file mode 100644 index 03919f15f1f..00000000000 --- a/app/assets/stylesheets/generic/common.scss +++ /dev/null @@ -1,404 +0,0 @@ -/** COLORS **/ -.cgray { color: $gl-gray; } -.clgray { color: #BBB } -.cred { color: $gl-text-red; } -.cgreen { color: $gl-text-green; } -.cdark { color: #444 } - -/** COMMON CLASSES **/ -.prepend-top-10 { margin-top:10px } -.prepend-top-default { margin-top: $gl-padding; } -.prepend-top-20 { margin-top:20px } -.prepend-left-10 { margin-left:10px } -.prepend-left-20 { margin-left:20px } -.append-right-10 { margin-right:10px } -.append-right-20 { margin-right:20px } -.append-bottom-10 { margin-bottom:10px } -.append-bottom-15 { margin-bottom:15px } -.append-bottom-20 { margin-bottom:20px } -.inline { display: inline-block } -.center { text-align: center } - -.underlined-link { text-decoration: underline; } -.hint { font-style: italic; color: #999; } -.light { color: $gl-gray; } - -.slead { - color: $gl-gray; - font-size: 15px; - margin-bottom: 12px; - font-weight: normal; - line-height: 24px; -} - -.tab-content { - overflow: visible; -} - -pre { - &.clean { - background: none; - border: none; - margin: 0; - padding: 0; - } - - &.well-pre { - border: 1px solid #EEE; - background: #f9f9f9; - border-radius: 0; - color: #555; - } -} - -.dropdown-menu > li > a { - text-shadow: none; -} - -.dropdown-menu-align-right { - left: auto; - right: 0px; -} - -.dropdown-menu > li > a:hover, -.dropdown-menu > li > a:focus { - background: $gl-primary; - color: #FFF -} - -.str-truncated { - @include str-truncated; -} - -/** FLASH message **/ -.author_link { - color: $gl-link-color; -} - -.back-link { - font-size: 14px; -} - -table a code { - position: relative; - top: -2px; - margin-right: 3px; -} - -.loading { - margin: 20px auto; - height: 40px; - color: #555; - font-size: 32px; - text-align: center; -} - -span.update-author { - display: block; - color: #999; - font-weight: normal; - font-style: italic; - strong { - font-weight: bold; - font-style: normal; - } -} - -.user-mention { - color: #2FA0BB; - font-weight: bold; -} - -.field_with_errors { - display: inline; -} - -.line_holder { - &:hover { - td { - background: #FFFFCF !important; - } - } -} - -p.time { - color: #999; - font-size: 90%; - margin: 30px 3px 3px 2px; -} - -.highlight { - text-shadow: none; -} - -.thin_area{ - height: 150px; -} - -// Fixes alignment on notes. -.new_note { - label { - text-align: left; - } -} - -// Fix issue with notes & lists creating a bunch of bottom borders. -li.note { - img { max-width:100% } - .note-title { - li { - border-bottom:none !important; - } - } -} - -.markdown { - img { - max-width: 100%; - } -} - -.wiki_content code, .readme code{ - background-color: inherit; -} - -.project_member_show { - td:first-child { - color: #aaa; - } -} - -.rss-icon { - img { - width: 24px; - vertical-align: top; - } - - strong { - line-height: 24px; - } -} - -.show-suppressed-diff, -.show-all-commits { - cursor: pointer; -} - -.git_error_tips { - @extend .col-md-6; - text-align: left; - margin-top: 40px; - pre { - background: white; - border: none; - font-size: 12px; - } -} - -.error-message { - padding: 10px; - background: #C67; - margin: 0; - color: #FFF; - - a { - color: #fff; - text-decoration: underline; - } -} - -.browser-alert { - padding: 10px; - text-align: center; - background: #C67; - color: #fff; - font-weight: bold; - a { - color: #fff; - text-decoration: underline; - } -} - -.warning_message { - border-left: 4px solid #ed9; - color: #b90; - padding: 10px; - margin-bottom: 10px; - background: #ffffe6; - padding-left: 20px; - - &.centered { - text-align: center; - } -} - -.gitlab-promo { - a { - color: #aaa; - margin-right: 30px; - } -} - -.milestone { - &.milestone-closed { - background: #f9f9f9; - } - .progress { - margin-bottom: 0; - margin-top: 4px; - } -} - -.control-group { - .controls { - span { - &.descr { - position: relative; - top: 2px; - left: 5px; - color: #666; - } - } - } -} - -img.emoji { - height: 20px; - vertical-align: middle; - width: 20px; -} - -.chart { - overflow: hidden; - height: 220px; -} - -.description-block { - @extend .light-well; - @extend .light; - margin-bottom: 10px; -} - -table { - td.permission-x { - background: #D9EDF7 !important; - text-align: center; - } -} - -.dashboard-intro-icon { - float: left; - text-align: center; - font-size: 32px; - color: #AAA; - width: 60px; -} - -.dashboard-intro-text { - display: inline-block; - margin-left: -60px; - padding-left: 60px; - width: 100%; -} - -.btn-sign-in { - margin-top: 8px; - text-shadow: none; -} - -.side-filters { - fieldset { - margin-bottom: 15px; - } -} - -.wiki .highlight, .note-body .highlight { - margin: 12px 0 12px 0; -} - -.wiki .code { - overflow-x: auto; -} - -.footer-links { - margin-bottom: 20px; - a { - margin-right: 15px; - } -} - -.search_box { - @extend .well; - text-align: center; -} - -.task-status { - margin-left: 10px; -} - -#nprogress .spinner { - top: 15px !important; - right: 10px !important; -} - -.header-with-avatar { - h3 { - margin: 0; - font-weight: bold; - } - - .username { - font-size: 18px; - color: #666; - margin-top: 8px; - } - - .description { - font-size: $gl-font-size; - color: #666; - margin-top: 8px; - } -} - -.profiler-results { - top: 73px !important; - - .profiler-button, - .profiler-controls { - border-color: #EEE !important; - } -} - -.center-top-menu { - @include nav-menu; - text-align: center; - margin-top: 5px; - margin-bottom: $gl-padding; - height: 56px; - margin-top: -$gl-padding; - padding-top: $gl-padding; - - &.no-bottom { - margin-bottom: 0; - } - - &.no-top { - margin-top: 0; - } -} - -.dropzone .dz-preview .dz-progress { - border-color: $border-color !important; -} - -.dropzone .dz-preview .dz-progress .dz-upload { - background: $gl-success !important; -} - -.space-right { - margin-right: 10px; -} - -.in-line { - display: inline-block; -} diff --git a/app/assets/stylesheets/generic/files.scss b/app/assets/stylesheets/generic/files.scss deleted file mode 100644 index 9dd77747884..00000000000 --- a/app/assets/stylesheets/generic/files.scss +++ /dev/null @@ -1,171 +0,0 @@ -/** - * File content holder - * - */ -.file-holder { - margin-left: -$gl-padding; - margin-right: -$gl-padding; - border: none; - border-top: 1px solid #E7E9EE; - border-bottom: 1px solid #E7E9EE; - margin-bottom: 1em; - - table { - @extend .table; - } - - .file-title { - position: relative; - background: $background-color; - border-bottom: 1px solid $border-color; - text-shadow: 0 1px 1px #fff; - margin: 0; - text-align: left; - padding: 10px 15px; - - .file-actions { - float: right; - position: absolute; - top: 5px; - right: 15px; - - .btn { - padding: 0px 10px; - font-size: 13px; - line-height: 28px; - } - } - - .left-options { - margin-top: -3px; - } - } - .file-content { - background: #fff; - - &.image_file { - background: #eee; - text-align: center; - img { - padding: 100px; - max-width: 50%; - } - } - - &.wiki { - padding: $gl-padding; - - .highlight { - margin-bottom: 9px; - - > pre { - margin: 0; - } - } - } - - &.blob_file { - - } - - &.blob-no-preview { - background: #eee; - text-shadow: 0 1px 2px #FFF; - padding: 100px 0; - } - - /** - * Blame file - */ - &.blame { - table { - border: none; - box-shadow: none; - margin: 0; - } - tr { - border-bottom: 1px solid #eee; - } - td { - &:first-child { - border-left: none; - } - &:last-child { - border-right: none; - } - background: #fff; - padding: 10px $gl-padding; - } - .lines { - pre { - padding: 0; - margin: 0; - background: none; - border: none; - } - } - img.avatar { - border: 0 none; - float: none; - margin: 0; - padding: 0; - } - td.blame-commit { - background: #f9f9f9; - min-width: 350px; - - .commit-author-link { - color: #888; - } - } - td.blame-numbers { - pre { - color: #AAA; - white-space: pre; - } - background: #f1f1f1; - border-left: 1px solid #DDD; - } - td.lines { - code { - font-family: $monospace_font; - } - } - } - - &.logs { - background: #eee; - max-height: 700px; - overflow-y: auto; - - ol { - margin-left: 40px; - padding: 10px 0; - border-left: 1px solid $border-color; - margin-bottom: 0; - background: white; - li { - color: #888; - p { - margin: 0; - color: #333; - line-height: 24px; - padding-left: 10px; - } - - &:hover { - background: $hover; - } - } - } - } - - /** - * Code file - */ - &.code { - padding: 0; - } - } -} - diff --git a/app/assets/stylesheets/generic/filters.scss b/app/assets/stylesheets/generic/filters.scss deleted file mode 100644 index 8e6922c9231..00000000000 --- a/app/assets/stylesheets/generic/filters.scss +++ /dev/null @@ -1,30 +0,0 @@ -.filter-item { - margin-right: 15px; -} - -@media (min-width: 800px) { - .issues-filters, - .issues_bulk_update { - select, .select2-container { - width: 120px !important; - display: inline-block; - } - } -} - -@media (min-width: 1200px) { - .issues-filters, - .issues_bulk_update { - select, .select2-container { - width: 150px !important; - display: inline-block; - } - } -} - -.issues-filters, -.issues_bulk_update { - .select2-container .select2-choice { - color: #444 !important; - } -} diff --git a/app/assets/stylesheets/generic/flash.scss b/app/assets/stylesheets/generic/flash.scss deleted file mode 100644 index 82eb50ad4be..00000000000 --- a/app/assets/stylesheets/generic/flash.scss +++ /dev/null @@ -1,17 +0,0 @@ -.flash-container { - cursor: pointer; - margin: 0; - font-size: 14px; - width: 100%; - z-index: 100; - - .flash-notice { - @extend .alert; - @extend .alert-info; - } - - .flash-alert { - @extend .alert; - @extend .alert-danger; - } -} diff --git a/app/assets/stylesheets/generic/forms.scss b/app/assets/stylesheets/generic/forms.scss deleted file mode 100644 index 0edfe24f195..00000000000 --- a/app/assets/stylesheets/generic/forms.scss +++ /dev/null @@ -1,94 +0,0 @@ -textarea { - resize: vertical; -} - -input[type='search'].search-text-input { - background-image: image-url("icon-search.png"); - background-repeat: no-repeat; - background-position: 10px; - padding-left: 25px; -} - -input[type='text'].danger { - background: #F2DEDE!important; - border-color: #D66; - text-shadow: 0 1px 1px #fff -} - -.datetime-controls { - select { - width: 100px; - } -} - -.form-actions { - padding: 17px 20px 18px; - margin-top: 18px; - margin-bottom: 18px; - background-color: $background-color; - border-top: 1px solid $border-color; -} - -label { - &.control-label { - @extend .col-sm-2; - } - - &.inline-label { - margin: 0; - } -} - -.inline-input-group { - width: 250px; -} - -.custom-form-control { - width: 150px; -} - -@media (min-width: $screen-sm-min) { - .custom-form-control { - width: 150px; - } -} - -/* Medium devices (desktops, 992px and up) */ -@media (min-width: $screen-md-min) { - .custom-form-control { - width: 170px; - } -} - -/* Large devices (large desktops, 1200px and up) */ -@media (min-width: $screen-lg-min) { - .custom-form-control { - width: 200px; - } -} - -.fieldset-form fieldset { - margin-bottom: 20px; -} - -.form-control { - @include box-shadow(none); -} - -.wiki-content { - margin-top: 35px; -} - -.form-group .control-label { - font-weight: normal; -} - -.form-control::-webkit-input-placeholder { - color: #7f8fa4; -} - -.input-group { - .input-group-addon { - background-color: #f7f8fa; - } -} diff --git a/app/assets/stylesheets/generic/gfm.scss b/app/assets/stylesheets/generic/gfm.scss deleted file mode 100644 index bd9200ace23..00000000000 --- a/app/assets/stylesheets/generic/gfm.scss +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Styles that apply to all GFM related forms. - */ -.issue-form, .merge-request-form, .wiki-form { - .description { - height: 16em; - border-top-left-radius: 0; - } -} - -.wiki-form { - .description { - height: 26em; - } -} - -.milestone-form { - .description { - height: 14em; - } -} - -.gfm-commit, .gfm-commit_range { - font-family: $monospace_font; -} diff --git a/app/assets/stylesheets/generic/header.scss b/app/assets/stylesheets/generic/header.scss deleted file mode 100644 index 91e6975e269..00000000000 --- a/app/assets/stylesheets/generic/header.scss +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Application Header - * - */ -header { - transition-duration: .3s; - - &.navbar-empty { - background: #FFF; - border-bottom: 1px solid #EEE; - - .center-logo { - margin: 8px 0; - text-align: center; - - img { - height: 32px; - } - } - } - - &.navbar-gitlab { - padding: 0 20px; - z-index: 100; - margin-bottom: 0; - min-height: $header-height; - background-color: #fff; - border: none; - - .container-fluid { - width: 100% !important; - filter: none; - padding: 0; - - .nav > li > a { - color: #7f8fa4; - font-size: 18px; - padding: 0; - margin: ($header-height - 28) / 2 0; - margin-left: 10px; - height: 28px; - width: 28px; - line-height: 28px; - text-align: center; - - &:hover, &:focus, &:active { - background-color: #FFF; - } - } - - .navbar-toggle { - color: #666; - margin: 6px 0; - border-radius: 0; - position: absolute; - right: 2px; - - &:hover { - background-color: #EEE; - } - &.active { - color: #7f8fa4; - } - } - } - } - - .header-content { - height: $header-height; - - .title { - margin: 0; - overflow: hidden; - font-size: 19px; - line-height: $header-height; - font-weight: normal; - color: #4c4e54; - text-overflow: ellipsis; - vertical-align: top; - white-space: nowrap; - - a { - color: #4c4e54; - &:hover { - text-decoration: underline; - } - } - } - - .navbar-collapse { - float: right; - border-top: none; - } - } - - .search { - margin-right: 10px; - margin-left: 10px; - margin-top: ($header-height - 36) / 2; - - form { - margin: 0; - padding: 0; - } - - .search-input { - width: 220px; - background-image: image-url("icon-search.png"); - background-repeat: no-repeat; - background-position: 195px; - @include input-big; - - &:focus { - @include box-shadow(none); - outline: none; - border-color: #DDD; - background-color: #FFF; - } - } - } -} - -@mixin collapsed-header { - margin-left: $sidebar_collapsed_width; -} - -@media (max-width: $screen-md-max) { - .header-collapsed, .header-expanded { - @include collapsed-header; - } -} - -@media(min-width: $screen-md-max) { - .header-collapsed { - @include collapsed-header; - } - - .header-expanded { - margin-left: $sidebar_width; - } -} - -@media (max-width: $screen-xs-max) { - header .container-fluid { - font-size: 18px; - - .navbar-nav { - margin: 0px; - float: none !important; - - .visible-xs, .visable-sm { - display: table-cell !important; - } - } - - .navbar-collapse { - padding-left: 5px; - - li { - display: table-cell; - width: 1%; - - a { - margin-left: 8px !important; - } - } - } - } -} diff --git a/app/assets/stylesheets/generic/highlight.scss b/app/assets/stylesheets/generic/highlight.scss deleted file mode 100644 index 2e13ee842e0..00000000000 --- a/app/assets/stylesheets/generic/highlight.scss +++ /dev/null @@ -1,70 +0,0 @@ -.file-content.code { - border: none; - box-shadow: none; - margin: 0px; - padding: 0px; - table-layout: fixed; - - pre { - padding: 10px; - border: none; - border-radius: 0; - font-family: $monospace_font; - font-size: $code_font_size !important; - line-height: $code_line_height !important; - margin: 0; - overflow: auto; - overflow-y: hidden; - white-space: pre; - word-wrap: normal; - - code { - font-family: $monospace_font; - white-space: pre; - word-wrap: normal; - padding: 0; - - .line { - display: inline; - } - } - } - - .line-numbers { - padding: 10px; - text-align: right; - float: left; - - a { - font-family: $monospace_font; - display: block; - font-size: $code_font_size !important; - line-height: $code_line_height !important; - white-space: nowrap; - - i { - visibility: hidden; - @extend .pull-left; - } - - &:hover i { - visibility: visible; - } - } - } -} - -.note-text .code { - border: none; - box-shadow: none; - background: $background-color; - padding: 1em; - overflow-x: auto; - - code { - font-family: $monospace_font; - white-space: pre; - word-wrap: normal; - padding: 0; - } -} diff --git a/app/assets/stylesheets/generic/issue_box.scss b/app/assets/stylesheets/generic/issue_box.scss deleted file mode 100644 index 93377e45e70..00000000000 --- a/app/assets/stylesheets/generic/issue_box.scss +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Issue box for showing Open/Closed state: - * Used for Issue#show page, MergeRequest#show page etc - * - */ - -.issue-box { - @include border-radius(2px); - - display: inline-block; - padding: 10px $gl-padding; - font-weight: normal; - margin-right: 10px; - font-size: $gl-font-size; - - &.issue-box-closed { - background-color: $gl-danger; - color: #FFF; - } - - &.issue-box-merged { - background-color: $gl-primary; - color: #FFF; - } - - &.issue-box-open { - background-color: #019875; - color: #FFF; - } - - &.issue-box-expired { - background: #cea61b; - color: #FFF; - } -} diff --git a/app/assets/stylesheets/generic/jquery.scss b/app/assets/stylesheets/generic/jquery.scss deleted file mode 100644 index 871b808bad4..00000000000 --- a/app/assets/stylesheets/generic/jquery.scss +++ /dev/null @@ -1,55 +0,0 @@ -.ui-widget { - font-family: $regular_font; - font-size: $font-size-base; - - &.ui-datepicker-inline { - border: 1px solid #DDD; - padding: 10px; - width: 270px; - - .ui-datepicker-header { - background: #FFF; - border-color: #DDD; - } - - .ui-datepicker-calendar td a { - padding: 5px; - text-align: center; - } - } - - &.ui-autocomplete { - border-color: #DDD; - padding: 0; - margin-top: 2px; - z-index: 1001; - - .ui-menu-item a { - padding: 4px 10px; - } - } - - .ui-state-default { - border: 1px solid #FFF; - background: #FFF; - color: #777; - } - - .ui-state-highlight { - border: 1px solid #EEE; - background: #EEE; - } - - .ui-state-active { - border: 1px solid $gl-primary; - background: $gl-primary; - color: #FFF; - } - - .ui-state-hover, - .ui-state-focus { - border: 1px solid $hover; - background: $hover; - color: #333; - } -} diff --git a/app/assets/stylesheets/generic/lists.scss b/app/assets/stylesheets/generic/lists.scss deleted file mode 100644 index 3bfed8de772..00000000000 --- a/app/assets/stylesheets/generic/lists.scss +++ /dev/null @@ -1,125 +0,0 @@ -/** - * Well styled list - * - */ -.well-list { - margin: 0; - padding: 0; - list-style: none; - - li { - padding: 10px 15px; - min-height: 20px; - border-bottom: 1px solid #eee; - border-bottom: 1px solid rgba(0, 0, 0, 0.05); - - &:after { - content: " "; - display: table; - clear: both; - } - - &.disabled { - color: #888; - } - - &.unstyled { - &:hover { - background: none; - } - } - - &.warning-row { - background-color: #fcf8e3; - border-color: #faebcc; - color: #8a6d3b; - } - - &.smoke { background-color: $background-color; } - - &:hover { - background: $hover; - } - - &:last-child { - border-bottom: none; - - &.bottom { - background: $background-color; - } - } - - .list-item-name { - float: left; - position: relative; - top: 3px; - } - - p { - padding-top: 1px; - margin: 0; - color: $gray-dark; - img { - position: relative; - top: 3px; - } - } - - .well-title { - font-size: $list-font-size; - line-height: 18px; - } - } -} - -ol, ul { - &.styled { - li { - padding: 2px; - } - } -} - -/** light list with border-bottom between li **/ -ul.bordered-list { - @include basic-list; - - &.top-list { - li:first-child { - padding-top: 0; - - h4, h5 { - margin-top: 0; - } - } - } -} - -li.task-list-item { - list-style-type: none; -} - -ul.content-list { - @include basic-list; - - margin: 0; - padding: 0; - - > li { - padding: $gl-padding; - border-color: #f1f2f4; - margin-left: -$gl-padding; - margin-right: -$gl-padding; - color: $gl-gray; - - .avatar { - margin-right: 15px; - } - - .controls { - padding-top: 10px; - float: right; - } - } -} - diff --git a/app/assets/stylesheets/generic/markdown_area.scss b/app/assets/stylesheets/generic/markdown_area.scss deleted file mode 100644 index ed0333d2336..00000000000 --- a/app/assets/stylesheets/generic/markdown_area.scss +++ /dev/null @@ -1,115 +0,0 @@ -.div-dropzone-wrapper { - .div-dropzone { - position: relative; - padding: 0; - border: 0; - margin-bottom: 5px; - - .div-dropzone-focus { - border-color: #66afe9 !important; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6) !important; - outline: 0 !important; - } - - .div-dropzone-hover { - position: absolute; - top: 50%; - left: 50%; - margin-top: -0.5em; - margin-left: -0.6em; - opacity: 0; - font-size: 50px; - transition: opacity 200ms ease-in-out; - pointer-events: none; - } - - .div-dropzone-spinner { - position: absolute; - top: 100%; - left: 100%; - margin-top: -1.1em; - margin-left: -1.1em; - opacity: 0; - font-size: 30px; - transition: opacity 200ms ease-in-out; - } - - .div-dropzone-icon { - display: block; - text-align: center; - font-size: inherit; - } - - .div-dropzone-progress { - position: absolute; - top: 7px; - left: -40px; - width: 35px; - font-size: 13px; - text-align: right; - } - - .dz-preview { - display: none; - } - } -} - -.div-dropzone-alert { - margin-top: 5px; - margin-bottom: 0; - transition: opacity 200ms ease-in-out; -} - -.md-area { - position: relative; -} - -.md-header { - ul { - float: left; - margin-bottom: 1px; - } -} - -.referenced-users { - padding: 10px 0; - color: #999; - margin-left: 10px; - margin-top: 1px; - margin-right: 130px; -} - -.md-preview-holder { - background: #FFF; - border: 1px solid #ddd; - min-height: 169px; - padding: 5px; - box-shadow: none; -} - -.new_note, -.edit_note, -.issuable-description, -.milestone-description, -.wiki-content, -.merge-request-form { - .nav-tabs { - margin-bottom: 0; - border: none; - - li a, - li.active a { - border: 1px solid #DDD; - } - } -} - -.markdown-area { - background: #FFF; - border: 1px solid #ddd; - min-height: 140px; - padding: 5px; - box-shadow: none; - width: 100%; -} diff --git a/app/assets/stylesheets/generic/mobile.scss b/app/assets/stylesheets/generic/mobile.scss deleted file mode 100644 index 36ae126f865..00000000000 --- a/app/assets/stylesheets/generic/mobile.scss +++ /dev/null @@ -1,139 +0,0 @@ -/** Common mobile (screen XS, SM) styles **/ -@media (max-width: $screen-xs-max) { - .container .content { - margin-top: 20px; - } - - .container-fluid { - padding-left: 5px; - padding-right: 5px; - } - - .nav.nav-tabs > li > a { - padding: 10px; - font-size: 12px; - margin-right: 3px; - - .badge { - display: none; - } - } - - .referenced-users { - margin-right: 0; - } - - .issues-filters, - .dash-projects-filters, - .check-all-holder { - display: none; - } - - .rss-btn { - display: none !important; - } - - .project-home-links { - display: none; - } - - .project-avatar { - display: none; - } - - .project-home-panel { - padding-left: 0 !important; - - .project-avatar { - display: block; - } - - .project-home-desc { - font-size: 21px; - } - - .project-repo-buttons, - .git-clone-holder { - display: none; - } - } - - .project-stats { - display: none; - } - - .container .title { - padding-left: 15px !important; - } - - .issue-info, .merge-request-info { - display: none; - } - - .issue-details { - .creator, - .page-title .btn-close { - display: none; - } - } - - %ul.notes .note-role, .note-actions { - display: none; - } - - .center-top-menu { - height: 45px; - - li a { - font-size: 14px; - padding: 19px 10px; - } - } - - .projects-search-form { - margin: 0 -5px !important; - - .btn { - display: none; - } - } -} - -@media (max-width: $screen-sm-max) { - .issues-filters { - .milestone-filter, .labels-filter { - display: none; - } - } - - .page-title { - .note_created_ago, .new-issue-link { - display: none; - } - } - - .issue_edited_ago, .note_edited_ago { - display: none; - } - - aside { - display: none; - } - - .show-aside { - display: block !important; - } -} - -.show-aside { - display: none; - position: fixed; - right: 0px; - top: 30%; - padding: 5px 15px; - background: #EEE; - font-size: 20px; - color: #777; - z-index: 100; - @include box-shadow(0 1px 2px #DDD); -} diff --git a/app/assets/stylesheets/generic/pagination.scss b/app/assets/stylesheets/generic/pagination.scss deleted file mode 100644 index 6677f94dafd..00000000000 --- a/app/assets/stylesheets/generic/pagination.scss +++ /dev/null @@ -1,34 +0,0 @@ -.gl-pagination { - border-top: 1px solid $border-color; - background-color: $background-color; - margin: -$gl-padding; - margin-top: 0; - - .pagination { - padding: 0; - margin: 0; - display: block; - - li.first, - li.last, - li.next, - li.prev { - > a { - color: $link-color; - - &:hover { - color: #fff; - } - } - } - - li > a, - li > span { - border: none; - margin: 0; - @include border-radius(0 !important); - padding: 13px 19px; - border-right: 1px solid $border-color; - } - } -} diff --git a/app/assets/stylesheets/generic/selects.scss b/app/assets/stylesheets/generic/selects.scss deleted file mode 100644 index cba621635b6..00000000000 --- a/app/assets/stylesheets/generic/selects.scss +++ /dev/null @@ -1,146 +0,0 @@ -/** Select2 selectbox style override **/ -.select2-container, .select2-container.select2-drop-above { - .select2-choice { - background: #FFF; - border-color: #DDD; - height: 42px; - padding: 8px $gl-padding; - font-size: $gl-font-size; - line-height: 1.42857143; - - @include border-radius(2px); - - .select2-arrow { - background: #FFF; - border-left: none; - padding-top: 5px; - } - } -} - -.select2-container .select2-choice, .select2-container.select2-drop-above .select2-choice{ - color: #7f8fa4; - border: 1px solid #e7e9ed; -} - -.select2-drop { - @include box-shadow(rgba(76, 86, 103, 0.247059) 0px 0px 1px 0px, rgba(31, 37, 50, 0.317647) 0px 2px 18px 0px); - @include border-radius (0px); - - padding: 16px; - border: none !important; -} - -.select2-results .select2-result-label { - padding: 16px; -} - -.select2-drop{ - color: #7f8fa4; -} - -.select2-highlighted { - background: #3084bb !important; -} - -.select2-results li.select2-result-with-children > .select2-result-label { - font-weight: 600; - color: #313236; -} - - -.select2-container-multi .select2-choices { - @include border-radius(2px); - border-color: #CCC; -} - -.select2-container-multi .select2-choices .select2-search-field input { - padding: 8px 14px; - font-size: 13px; - line-height: 18px; - height: auto; -} - -.select2-drop-active { - border: 1px solid #BBB !important; - margin-top: 4px; - font-size: 13px; - - &.select2-drop-above { - margin-bottom: 8px; - } - - .select2-search input { - background: #fafafa; - border-color: #DDD; - } - - .select2-results { - max-height: 350px; - .select2-highlighted { - background: $gl-primary; - } - } -} - -.select2-container { - width: 100% !important; -} - -/** Branch/tag selector **/ -.project-refs-form .select2-container { - width: 160px !important; -} - -.ajax-users-dropdown, .ajax-project-users-dropdown { - .select2-search { - padding-top: 2px; - } -} - -.ajax-users-select { - width: 400px; - - &.input-large { - width: 210px; - } - - &.input-clamp { - max-width: 100%; - } -} - -.group-result { - .group-image { - float: left; - } - .group-name { - font-weight: bold; - } - .group-path { - color: #999; - } -} - -.user-result { - .user-image { - float: left; - } - .user-name { - } -} - -.namespace-result { - .namespace-kind { - color: #AAA; - font-weight: normal; - } - .namespace-path { - margin-left: 10px; - font-weight: bolder; - } -} - -.ajax-users-dropdown { - min-width: 250px !important; -} diff --git a/app/assets/stylesheets/generic/sidebar.scss b/app/assets/stylesheets/generic/sidebar.scss deleted file mode 100644 index c5ea3aca7ca..00000000000 --- a/app/assets/stylesheets/generic/sidebar.scss +++ /dev/null @@ -1,267 +0,0 @@ -.page-with-sidebar { - .sidebar-wrapper { - position: fixed; - top: 0; - bottom: 0; - overflow-y: auto; - overflow-x: hidden; - left: 0; - height: 100%; - transition-duration: .3s; - } -} - -.sidebar-wrapper { - z-index: 99; - background: $background-color; - transition-duration: .3s; -} - -.content-wrapper { - min-height: 100vh; - width: 100%; - padding: 20px; - background: #EAEBEC; - - .container-fluid { - background: #FFF; - padding: $gl-padding; - min-height: 90vh; - - &.container-blank { - background: none; - padding: 0; - border: none; - } - } -} - -.nav-sidebar { - margin-top: 14 + $header-height; - margin-bottom: 100px; - transition-duration: .3s; - list-style: none; - overflow: hidden; - - &.navbar-collapse { - padding: 0px !important; - } - - li { - width: $sidebar_width; - - &.separate-item { - padding-top: 10px; - margin-top: 10px; - } - - a { - padding: 7px 15px; - font-size: $gl-font-size; - line-height: 24px; - color: $gray; - display: block; - text-decoration: none; - padding-left: 22px; - font-weight: normal; - - &:hover { - text-decoration: none; - } - - &:active, &:focus { - text-decoration: none; - } - - i { - width: 16px; - color: $gray-light; - margin-right: 13px; - } - - .count { - float: right; - background: #eee; - padding: 0px 8px; - @include border-radius(6px); - } - } - } -} - -.sidebar-subnav { - margin-left: 0px; - padding-left: 0px; - - li { - list-style: none; - } -} - -@mixin expanded-sidebar { - padding-left: $sidebar_width; - transition-duration: .3s; - - .sidebar-wrapper { - width: $sidebar_width; - - .nav-sidebar { - width: $sidebar_width; - } - - .nav-sidebar li a{ - width: 230px; - - &.back-link { - i { - visibility: hidden; - } - } - } - } -} - -@mixin folded-sidebar { - padding-left: 60px; - transition-duration: .3s; - - .sidebar-wrapper { - width: $sidebar_collapsed_width; - - .header-logo { - width: $sidebar_collapsed_width; - - a { - padding-left: 12px; - - .gitlab-text-container { - display: none; - } - } - } - - .nav-sidebar { - width: $sidebar_collapsed_width; - - li a { - span { - display: none; - } - } - } - - .collapse-nav a { - width: $sidebar_collapsed_width; - } - - .sidebar-user { - padding-left: 12px; - width: $sidebar_collapsed_width; - - .username { - display: none; - } - } - } -} - -.collapse-nav a { - width: $sidebar_width; - position: fixed; - bottom: 0; - left: 0; - font-size: 13px; - background: transparent; - height: 40px; - text-align: center; - line-height: 40px; - transition-duration: .3s; -} - -.collapse-nav a:hover { - text-decoration: none; - background: #f2f6f7; -} - -@media (max-width: $screen-md-max) { - .page-sidebar-collapsed { - @include folded-sidebar; - } - - .page-sidebar-expanded { - @include folded-sidebar; - } - - .collapse-nav { - display: none; - } -} - -@media(min-width: $screen-md-max) { - .page-sidebar-collapsed { - @include folded-sidebar; - } - - .page-sidebar-expanded { - @include expanded-sidebar; - } -} - -.sidebar-user { - padding: 9px 22px; - position: fixed; - bottom: 40px; - width: $sidebar_width; - overflow: hidden; - transition-duration: .3s; - - .username { - margin-left: 10px; - width: $sidebar_width - 2 * 10px; - font-size: 16px; - line-height: 34px; - } -} - -.sidebar-wrapper { - .header-logo { - border-bottom: 1px solid transparent; - float: left; - height: $header-height; - width: $sidebar_width; - overflow: hidden; - transition-duration: .3s; - - a { - float: left; - height: $header-height; - width: 100%; - padding: 10px 22px; - overflow: hidden; - - img { - width: 36px; - height: 36px; - float: left; - } - - .gitlab-text-container { - width: 230px; - - h3 { - width: 158px; - float: left; - margin: 0; - margin-left: 14px; - font-size: 19px; - line-height: 41px; - font-weight: normal; - } - } - } - - &:hover { - background-color: #EEE; - } - } -} diff --git a/app/assets/stylesheets/generic/tables.scss b/app/assets/stylesheets/generic/tables.scss deleted file mode 100644 index a66e45577de..00000000000 --- a/app/assets/stylesheets/generic/tables.scss +++ /dev/null @@ -1,20 +0,0 @@ -table { - &.table { - tr { - td, th { - padding: 8px 10px; - line-height: 20px; - vertical-align: middle; - } - th { - font-weight: normal; - font-size: 15px; - border-bottom: 1px solid $border-color !important; - } - td { - border-color: #F1F1F1 !important; - border-bottom: 1px solid; - } - } - } -} diff --git a/app/assets/stylesheets/generic/timeline.scss b/app/assets/stylesheets/generic/timeline.scss deleted file mode 100644 index bf21d7fce76..00000000000 --- a/app/assets/stylesheets/generic/timeline.scss +++ /dev/null @@ -1,70 +0,0 @@ -.timeline { - @include basic-list; - - margin: 0; - padding: 0; - - .timeline-entry { - padding: $gl-padding; - border-color: #f1f2f4; - margin-left: -$gl-padding; - margin-right: -$gl-padding; - color: $gl-gray; - border-bottom: 1px solid #ECEEF1; - border-right: 1px solid #ECEEF1; - - &:last-child { - border-bottom: none; - } - - .avatar { - margin-right: 15px; - } - - .controls { - padding-top: 10px; - float: right; - } - } - - .note-text { - p:last-child { - margin-bottom: 0; - } - } - - .system-note { - .note-text { - color: $gl-gray !important; - } - } - - .diff-file { - border: 1px solid $border-color; - border-bottom: none; - margin-left: 0; - margin-right: 0; - } -} - -@media (max-width: $screen-xs-max) { - .timeline { - &:before { - background: none; - } - .timeline-entry .timeline-entry-inner { - .timeline-icon { - display: none; - } - - .timeline-content { - margin-left: 0; - } - } - } -} - -.discussion .timeline-entry { - margin: 0; - border-right: none; -} diff --git a/app/assets/stylesheets/generic/typography.scss b/app/assets/stylesheets/generic/typography.scss deleted file mode 100644 index 6a3cb49baae..00000000000 --- a/app/assets/stylesheets/generic/typography.scss +++ /dev/null @@ -1,130 +0,0 @@ -/** - * Headers - * - */ -body { - text-rendering:optimizeLegibility; - -webkit-text-shadow: rgba(255,255,255,0.01) 0 0 1px; -} - -.page-title { - margin-top: 0px; - line-height: 1.3; - font-size: 1.25em; - font-weight: 600; -} - -.page-title-empty { - margin-top: 0px; - line-height: 1.3; - font-size: 1.25em; - font-weight: 600; - margin: 12px 7px 12px 7px; -} - -h1, h2, h3, h4, h5, h6 { - color: $gl-header-color; - font-weight: 500; -} - -/** CODE **/ -pre { - font-family: $monospace_font; - - &.dark { - background: #333; - color: $background-color; - } - - &.plain-readme { - background: none; - border: none; - padding: 0; - margin: 0; - font-size: 14px; - } -} - -.monospace { - font-family: $monospace_font; -} - -code { - &.key-fingerprint { - background: $body-bg; - color: $text-color; - } -} - -a > code { - color: $link-color; -} - -/** - * Wiki typography - * - */ -.wiki { - @include md-typography; - - word-wrap: break-word; - padding: 7px; - - /* Link to current header. */ - h1, h2, h3, h4, h5, h6 { - position: relative; - - a.anchor { - // Setting `display: none` would prevent the anchor being scrolled to, so - // instead we set the height to 0 and it gets updated on hover. - height: 0; - } - - &:hover > a.anchor { - $size: 16px; - position: absolute; - right: 100%; - top: 50%; - margin-top: -$size/2; - margin-right: 0px; - padding-right: 20px; - display: inline-block; - width: $size; - height: $size; - background-image: image-url("icon-link.png"); - background-size: contain; - background-repeat: no-repeat; - } - } - - ul,ol { - padding: 0; - margin: 6px 0 6px 18px !important; - } - ol { - color: #5c5d5e; - } -} - -.md-area { - @include md-typography; -} - -.md { - @include md-typography; -} - -/** - * Textareas intended for GFM - * - */ -textarea.js-gfm-input { - font-family: $monospace_font; -} - -.md-preview { -} - -.strikethrough { - text-decoration: line-through; -} \ No newline at end of file diff --git a/app/assets/stylesheets/generic/zen.scss b/app/assets/stylesheets/generic/zen.scss deleted file mode 100644 index 32e2c020e06..00000000000 --- a/app/assets/stylesheets/generic/zen.scss +++ /dev/null @@ -1,86 +0,0 @@ -.zennable { - .zen-toggle-comment { - display: none; - } - - .zen-enter-link { - color: $gl-gray; - position: absolute; - top: 0px; - right: 4px; - line-height: 40px; - } - - .zen-leave-link { - display: none; - color: $gl-text-color; - position: absolute; - top: 10px; - right: 10px; - padding: 5px; - font-size: 36px; - - &:hover { - color: #111; - } - } - - // Hide the Enter link when we're in Zen mode - input:checked ~ .zen-backdrop .zen-enter-link { - display: none; - } - - // Show the Leave link when we're in Zen mode - input:checked ~ .zen-backdrop .zen-leave-link { - display: block; - position: absolute; - top: 0; - } - - input:checked ~ .zen-backdrop { - background-color: white; - position: fixed; - top: 0; - bottom: 0; - left: 0; - right: 0; - z-index: 1031; - - textarea { - border: none; - box-shadow: none; - border-radius: 0; - color: #000; - font-size: 20px; - line-height: 26px; - padding: 30px; - display: block; - outline: none; - resize: none; - height: 100vh; - max-width: 900px; - margin: 0 auto; - } - } - - // Make the color of the placeholder text in the Zenned-out textarea darker, - // so it becomes visible - - input:checked ~ .zen-backdrop textarea::-webkit-input-placeholder { - color: #A8A8A8; - } - - input:checked ~ .zen-backdrop textarea:-moz-placeholder { - color: #A8A8A8; - opacity: 1; - } - - input:checked ~ .zen-backdrop textarea::-moz-placeholder { - color: #A8A8A8; - opacity: 1; - } - - input:checked ~ .zen-backdrop textarea:-ms-input-placeholder { - color: #A8A8A8; - } -} diff --git a/app/assets/stylesheets/themes/gitlab-theme.scss b/app/assets/stylesheets/themes/gitlab-theme.scss deleted file mode 100644 index 8d9a0aae568..00000000000 --- a/app/assets/stylesheets/themes/gitlab-theme.scss +++ /dev/null @@ -1,120 +0,0 @@ -/** - * Styles the GitLab application with a specific color theme - * - * $color-light - - * $color - - * $color-darker - - * $color-dark - - */ -@mixin gitlab-theme($color-light, $color, $color-darker, $color-dark) { - .page-with-sidebar { - .header-logo { - background-color: $color; - border-color: $color; - - a { - color: $color-light; - - h3 { - color: $color-light; - } - } - - &:hover { - background-color: $color-darker; - a { - color: #FFF; - } - } - } - - .collapse-nav a { - color: #FFF; - background: $color; - } - - .sidebar-wrapper { - background: $color-darker; - - .sidebar-user { - background: $color-darker; - color: $color-light; - - &:hover { - background-color: $color-dark; - color: #FFF; - text-decoration: none; - } - } - } - - .nav-sidebar li { - a { - color: $color-light; - - &:hover, &:focus, &:active { - background: $color-dark; - } - - i { - color: $color-light; - } - - .count { - color: $color-light; - background: $color-dark; - } - } - - &.separate-item { - border-top: 1px solid $color; - } - - &.active a { - color: #FFF; - background: $color-dark; - - &.no-highlight { - border: none; - } - - i { - color: #FFF - } - } - } - } -} - -$theme-blue: #2980B9; -$theme-charcoal: #333c47; -$theme-graphite: #888888; -$theme-gray: #373737; -$theme-green: #019875; -$theme-violet: #554488; - -body { - &.ui_blue { - @include gitlab-theme(#BECDE9, $theme-blue, #1970A9, #096099); - } - - &.ui_charcoal { - @include gitlab-theme(#c5d0de, $theme-charcoal, #2b333d, #24272D); - } - - &.ui_graphite { - @include gitlab-theme(#CCCCCC, $theme-graphite, #777777, #666666); - } - - &.ui_gray { - @include gitlab-theme(#979797, $theme-gray, #272727, #222222); - } - - &.ui_green { - @include gitlab-theme(#AADDCC, $theme-green, #018865, #017855); - } - - &.ui_violet { - @include gitlab-theme(#9988CC, $theme-violet, #443366, #332255); - } -} -- cgit v1.2.1 From c42d35b7214348e5c31014b3d3d54e59f6030ddc Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 12 Oct 2015 15:08:33 +0200 Subject: Add css welcome notice Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/application.scss | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 233e01cc06b..65f775ca3f3 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -11,33 +11,41 @@ *= require cal-heatmap */ -/** +/* + * Welcome to GitLab css! + * If you need to add or modify UI component that is commont for many pages + * like table or typography then make changes in framework/ directory. + * If you need to add uniq style that should affect only one page - use pages/ + * directory. + */ + +/* * GitLab UI framework */ @import "framework"; -/** +/* * NProgress load bar css */ @import 'nprogress'; @import 'nprogress-bootstrap'; -/** +/* * Font icons */ @import "font-awesome"; -/** +/* * Page specific styles (issues, projects etc): */ @import "pages/**/*"; -/** +/* * Code highlight */ @import "highlight/**/*"; -/** +/* * Styles for JS behaviors. */ @import "behaviors.scss"; -- cgit v1.2.1 From 69c04498ef0a49186a667fd44383b9b43690a91e Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 12 Oct 2015 15:45:46 +0200 Subject: Small bug fixes --- app/models/ci/build.rb | 16 +++++++++++---- app/models/commit_status.rb | 23 +++++++++++++++------- .../commit_statuses/_commit_status.html.haml | 16 +++++++-------- doc/api/commits.md | 1 - lib/api/commit_statuses.rb | 5 +++-- 5 files changed, 39 insertions(+), 22 deletions(-) diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 41ce522b2ff..cb6a1015210 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -212,15 +212,23 @@ module Ci "#{dir_to_trace}/#{id}.log" end - def description - name - end - def target_url Gitlab::Application.routes.url_helpers. namespace_project_build_url(gl_project.namespace, gl_project, self) end + def cancel_url + if active? + cancel_namespace_project_build_path(gl_project.namespace, gl_project, self, return_to: request.original_url) + end + end + + def retry_url + if commands.present? + cancel_namespace_project_build_path(gl_project.namespace, gl_project, self, return_to: request.original_url) + end + end + private def yaml_variables diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index a4896a76316..b6234c896e3 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -11,14 +11,14 @@ class CommitStatus < ActiveRecord::Base alias_attribute :author, :user - scope :running, ->() { where(status: 'running') } - scope :pending, ->() { where(status: 'pending') } - scope :success, ->() { where(status: 'success') } - scope :failed, ->() { where(status: 'failed') } - scope :running_or_pending, ->() { where(status:[:running, :pending]) } - scope :latest, ->() { where(id: unscope(:select).select('max(id)').group(:name, :ref)).order(stage_idx: :asc) } + scope :running, -> { where(status: 'running') } + scope :pending, -> { where(status: 'pending') } + scope :success, -> { where(status: 'success') } + scope :failed, -> { where(status: 'failed') } + scope :running_or_pending, -> { where(status:[:running, :pending]) } + scope :latest, -> { where(id: unscope(:select).select('max(id)').group(:name, :ref)).order(stage_idx: :asc) } scope :for_ref, ->(ref) { where(ref: [ref, nil]) } - scope :running_or_pending, ->() { where(status: [:running, :pending]) } + scope :running_or_pending, -> { where(status: [:running, :pending]) } state_machine :status, initial: :pending do event :run do @@ -55,6 +55,7 @@ class CommitStatus < ActiveRecord::Base delegate :sha, :short_sha, :gl_project, to: :commit, prefix: false + # TODO: this should be removed with all references def before_sha Gitlab::Git::BLANK_SHA end @@ -78,4 +79,12 @@ class CommitStatus < ActiveRecord::Base Time.now - started_at end end + + def cancel_url + nil + end + + def retry_url + nil + end end diff --git a/app/views/projects/commit_statuses/_commit_status.html.haml b/app/views/projects/commit_statuses/_commit_status.html.haml index f79929c70bf..14b814bb0d6 100644 --- a/app/views/projects/commit_statuses/_commit_status.html.haml +++ b/app/views/projects/commit_statuses/_commit_status.html.haml @@ -9,7 +9,7 @@ - else %strong Build ##{commit_status.id} - - if defined?(ref) + - if defined?(ref) && ref %td = commit_status.ref @@ -17,7 +17,7 @@ = commit_status.stage %td - = commit_status.description + = commit_status.name .pull-right - if commit_status.tags.any? - commit_status.tags.each do |tag| @@ -36,17 +36,17 @@ - if commit_status.finished_at %span #{time_ago_in_words commit_status.finished_at} ago - - if defined?(coverage) + - if defined?(coverage) && coverage %td.coverage - if commit_status.try(:coverage) #{commit_status.coverage}% %td - - if defined?(controls) && current_user && can?(current_user, :manage_builds, gl_project) + - if defined?(controls) && controls && current_user && can?(current_user, :manage_builds, gl_project) .pull-right - - if commit_status.active? - = link_to cancel_namespace_project_build_path(gl_project.namespace, gl_project, commit_status, return_to: request.original_url), title: 'Cancel commit_status' do + - if commit_status.cancel_url + = link_to commit_status.cancel_url, title: 'Cancel' do %i.fa.fa-remove.cred - - elsif commit_status.commands.present? - = link_to retry_namespace_project_build_path(gl_project.namespace, gl_project, commit_status, return_to: request.original_url), method: :post, title: 'Retry commit_status' do + - elsif commit_status.retry_url + = link_to commit_status.retry_url, method: :post, title: 'Retry' do %i.fa.fa-repeat diff --git a/doc/api/commits.md b/doc/api/commits.md index 78144dd42ef..9f72adc6ed9 100644 --- a/doc/api/commits.md +++ b/doc/api/commits.md @@ -203,7 +203,6 @@ Parameters: ## Post the status to commit Adds or updates a status of a commit. -Optionally you can post comments on a specific line of a commit. Therefor both `path`, `line_new` and `line_old` are required. ``` POST /projects/:id/statuses/:sha diff --git a/lib/api/commit_statuses.rb b/lib/api/commit_statuses.rb index ca750320e40..2a005d6a9f7 100644 --- a/lib/api/commit_statuses.rb +++ b/lib/api/commit_statuses.rb @@ -5,7 +5,6 @@ module API class CommitStatus < Grape::API resource :projects do before { authenticate! } - before { authorize! :read_commit_statuses, user_project } # Get a commit's statuses # @@ -19,13 +18,14 @@ module API # Examples: # GET /projects/:id/repository/commits/:sha/statuses get ':id/repository/commits/:sha/statuses' do + authorize! :read_commit_statuses, user_project sha = params[:sha] ci_commit = user_project.ci_commit(sha) not_found! 'Commit' unless ci_commit statuses = ci_commit.statuses statuses = statuses.latest unless parse_boolean(params[:all]) statuses = statuses.where(ref: params[:ref]) if params[:ref].present? - statuses = statuses.where(name: params[:stage]) if params[:stage].present? + statuses = statuses.where(stage: params[:stage]) if params[:stage].present? statuses = statuses.where(name: params[:name]) if params[:name].present? present paginate(statuses), with: Entities::CommitStatus end @@ -43,6 +43,7 @@ module API # Examples: # POST /projects/:id/statuses/:sha post ':id/statuses/:sha' do + authorize! :create_commit_statuses, user_project required_attributes! [:state] attrs = attributes_for_keys [:ref, :target_url, :description, :context, :name] commit = @project.commit(params[:sha]) -- cgit v1.2.1 From 789fe7b4899fb97c48ad363c5ecb1969d78d1536 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 12 Oct 2015 16:32:58 +0200 Subject: Update rendering --- app/models/ci/commit.rb | 66 +++++++++++---------- app/models/commit_status.rb | 5 +- app/views/projects/builds/show.html.haml | 6 +- app/views/projects/commit/ci.html.haml | 67 ++++++++-------------- .../commit_statuses/_commit_status.html.haml | 5 +- lib/api/commit_statuses.rb | 2 +- 6 files changed, 64 insertions(+), 87 deletions(-) diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb index 623ff619c49..201b6f62b86 100644 --- a/app/models/ci/commit.rb +++ b/app/models/ci/commit.rb @@ -106,50 +106,47 @@ module Ci end def refs - statuses.pluck(:ref).compact.uniq + statuses.order(:ref).pluck(:ref).uniq end - def statuses_for_ref(ref = nil) - if ref - statuses.for_ref(ref) - else - statuses - end + def latest_statuses + @latest_statuses ||= statuses.latest.to_a end - def builds_without_retry(ref = nil) - if ref - builds.for_ref(ref).latest - else - builds.latest - end + def builds_without_retry + @builds_without_retry ||= builds.latest.to_a + end + + def builds_without_retry_for_ref(ref) + builds_without_retry.select { |build| build.ref == ref } end def retried @retried ||= (statuses.order(id: :desc) - statuses.latest) end - def status(ref = nil) + def status if yaml_errors.present? return 'failed' end - latest_statuses = statuses.latest.to_a - latest_statuses.reject! { |status| status.try(&:allow_failure?) } - latest_statuses.select! { |status| status.ref.nil? || status.ref == ref } if ref - - if latest_statuses.none? - return 'skipped' - elsif latest_statuses.all?(&:success?) - 'success' - elsif latest_statuses.all?(&:pending?) - 'pending' - elsif latest_statuses.any?(&:running?) || latest_statuses.any?(&:pending?) - 'running' - elsif latest_statuses.all?(&:canceled?) - 'canceled' - else - 'failed' + @status ||= begin + latest = latest_statuses + latest.reject! { |status| status.try(&:allow_failure?) } + + if latest.none? + 'skipped' + elsif latest.all?(&:success?) + 'success' + elsif latest.all?(&:pending?) + 'pending' + elsif latest.any?(&:running?) || latest.any?(&:pending?) + 'running' + elsif latest.all?(&:canceled?) + 'canceled' + else + 'failed' + end end end @@ -173,8 +170,9 @@ module Ci status == 'canceled' end - def duration(ref = nil) - statuses_for_ref(ref).latest.select(&:duration).sum(&:duration).to_i + def duration + duration_array = latest_statuses.map(&:duration).compact + duration_array.reduce(:+).to_i end def finished_at @@ -190,8 +188,8 @@ module Ci end end - def matrix?(ref) - builds_without_retry(ref).pluck(:id).size > 1 + def matrix_for_ref?(ref) + builds_without_retry_for_ref(ref).size > 1 end def config_processor diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index b6234c896e3..b4d91b1b0c3 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -16,8 +16,9 @@ class CommitStatus < ActiveRecord::Base scope :success, -> { where(status: 'success') } scope :failed, -> { where(status: 'failed') } scope :running_or_pending, -> { where(status:[:running, :pending]) } - scope :latest, -> { where(id: unscope(:select).select('max(id)').group(:name, :ref)).order(stage_idx: :asc) } - scope :for_ref, ->(ref) { where(ref: [ref, nil]) } + scope :latest, -> { where(id: unscope(:select).select('max(id)').group(:name, :ref)) } + scope :ordered, -> { order(:ref, :stage_idx, :name) } + scope :for_ref, ->(ref) { where(ref: ref) } scope :running_or_pending, -> { where(status: [:running, :pending]) } state_machine :status, initial: :pending do diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml index 66e668f3771..b561078e8c7 100644 --- a/app/views/projects/builds/show.html.haml +++ b/app/views/projects/builds/show.html.haml @@ -7,9 +7,9 @@ %code #{@build.ref} #up-build-trace - - if @commit.matrix?(@build.ref) + - if @commit.matrix_for_ref?(@build.ref) %ul.center-top-menu.build-top-menu - - @commit.builds_without_retry(@build.ref).each do |build| + - @commit.builds_without_retry_for_ref(@build.ref).each do |build| %li{class: ('active' if build == @build) } = link_to namespace_project_build_path(@project.namespace, @project, build) do = ci_icon_for_status(build.status) @@ -20,7 +20,7 @@ = build.id - - unless @commit.builds_without_retry(@build.ref).include?(@build) + - unless @commit.builds_without_retry_for_ref(@build.ref).include?(@build) %li.active %a Build ##{@build.id} diff --git a/app/views/projects/commit/ci.html.haml b/app/views/projects/commit/ci.html.haml index 7f106631cac..585f012fe04 100644 --- a/app/views/projects/commit/ci.html.haml +++ b/app/views/projects/commit/ci.html.haml @@ -20,49 +20,28 @@ .bs-callout.bs-callout-warning \.gitlab-ci.yml not found in this commit -- if @ci_commit.refs.blank? - .gray-content-block.second-block - Latest builds - - if @ci_commit.duration > 0 - %small.pull-right - %i.fa.fa-time - #{time_interval_in_words @ci_commit.duration} - - %table.table.builds - %thead - %tr - %th Status - %th Build ID - %th Stage - %th Name - %th Duration - %th Finished at - - if @ci_project && @ci_project.coverage_enabled? - %th Coverage - %th - = render partial: "projects/commit_statuses/commit_status", collection: @ci_commit.statuses.latest, coverage: @ci_project.try(:coverage_enabled?), controls: true - -- @ci_commit.refs.sort.each do |ref| - .gray-content-block.second-block - Builds for #{ref} - - if @ci_commit.duration(ref) > 0 - %small.pull-right - %i.fa.fa-time - #{time_interval_in_words @ci_commit.duration(ref)} - - %table.table.builds - %thead - %tr - %th Status - %th Build ID - %th Stage - %th Name - %th Duration - %th Finished at - - if @ci_project && @ci_project.coverage_enabled? - %th Coverage - %th - = render partial: "projects/commit_statuses/commit_status", collection: @ci_commit.statuses.for_ref(ref).latest, coverage: @ci_project.try(:coverage_enabled?), controls: true +.gray-content-block.second-block + Latest + - if @ci_commit.duration > 0 + %small.pull-right + %i.fa.fa-time + #{time_interval_in_words @ci_commit.duration} + +%table.table.builds + %thead + %tr + %th Status + %th Build ID + %th Ref + %th Stage + %th Name + %th Duration + %th Finished at + - if @ci_project && @ci_project.coverage_enabled? + %th Coverage + %th + - @ci_commit.refs.each do |ref| + = render partial: "projects/commit_statuses/commit_status", collection: @ci_commit.statuses.for_ref(ref).latest.ordered, coverage: @ci_project.try(:coverage_enabled?), controls: true - if @ci_commit.retried.any? .gray-content-block.second-block @@ -81,4 +60,4 @@ - if @ci_project && @ci_project.coverage_enabled? %th Coverage %th - = render partial: "projects/commit_statuses/commit_status", collection: @ci_commit.retried, coverage: @ci_project.try(:coverage_enabled?), ref: true + = render partial: "projects/commit_statuses/commit_status", collection: @ci_commit.retried, coverage: @ci_project.try(:coverage_enabled?) diff --git a/app/views/projects/commit_statuses/_commit_status.html.haml b/app/views/projects/commit_statuses/_commit_status.html.haml index 14b814bb0d6..e3a17faf0bd 100644 --- a/app/views/projects/commit_statuses/_commit_status.html.haml +++ b/app/views/projects/commit_statuses/_commit_status.html.haml @@ -9,9 +9,8 @@ - else %strong Build ##{commit_status.id} - - if defined?(ref) && ref - %td - = commit_status.ref + %td + = commit_status.ref %td = commit_status.stage diff --git a/lib/api/commit_statuses.rb b/lib/api/commit_statuses.rb index 2a005d6a9f7..50ca89079e0 100644 --- a/lib/api/commit_statuses.rb +++ b/lib/api/commit_statuses.rb @@ -53,7 +53,7 @@ module API name = params[:name] || params[:context] status = GenericCommitStatus.running_or_pending.find_by(commit: ci_commit, name: name, ref: params[:ref]) - status = GenericCommitStatus.new(commit: ci_commit, user: current_user) unless status + status ||= GenericCommitStatus.new(commit: ci_commit, user: current_user) status.update(attrs) case params[:state].to_s -- cgit v1.2.1 From 2e9c1608e56a20b93608ddcd569c6a45d3a229eb Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 12 Oct 2015 16:35:58 +0200 Subject: Fix commit skipping --- app/services/ci/create_commit_service.rb | 10 +++++----- spec/models/ci/project_services/mail_service_spec.rb | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/services/ci/create_commit_service.rb b/app/services/ci/create_commit_service.rb index 0ae35387579..79b0291fabc 100644 --- a/app/services/ci/create_commit_service.rb +++ b/app/services/ci/create_commit_service.rb @@ -17,11 +17,11 @@ module Ci tag = origin_ref.start_with?('refs/tags/') commit = project.gl_project.ensure_ci_commit(sha) - return false if commit.skip_ci? - - commit.update_committed! - commit.create_builds(ref, tag, user) - + unless commit.skip_ci? + commit.update_committed! + commit.create_builds(ref, tag, user) + end + commit end end diff --git a/spec/models/ci/project_services/mail_service_spec.rb b/spec/models/ci/project_services/mail_service_spec.rb index 2ce5c2b4707..d9b3d34ff15 100644 --- a/spec/models/ci/project_services/mail_service_spec.rb +++ b/spec/models/ci/project_services/mail_service_spec.rb @@ -35,7 +35,7 @@ describe Ci::MailService do let(:project) { FactoryGirl.create(:ci_project, email_add_pusher: true) } let(:gl_project) { FactoryGirl.create(:empty_project, gitlab_ci_project: project) } let(:commit) { FactoryGirl.create(:ci_commit, gl_project: gl_project) } - let(:build) { FactoryGirl.create(:ci_build, status: :failed, commit: commit, user: user) } + let(:build) { FactoryGirl.create(:ci_build, status: 'failed', commit: commit, user: user) } before do allow(mail).to receive_messages( @@ -167,7 +167,7 @@ describe Ci::MailService do end let(:gl_project) { FactoryGirl.create(:empty_project, gitlab_ci_project: project) } let(:commit) { FactoryGirl.create(:ci_commit, gl_project: gl_project) } - let(:build) { FactoryGirl.create(:ci_build, status: :failed, commit: commit, user: user) } + let(:build) { FactoryGirl.create(:ci_build, status: 'failed', commit: commit, user: user) } before do allow(mail).to receive_messages( -- cgit v1.2.1 From 5cd504ed331dd23d17709285237945fb867978a8 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 12 Oct 2015 16:39:08 +0200 Subject: Rename builds_without_retry to latest_builds --- app/models/ci/commit.rb | 14 +++++++------- app/models/project_services/ci/hip_chat_service.rb | 2 +- app/models/project_services/ci/mail_service.rb | 2 +- app/models/project_services/ci/slack_message.rb | 2 +- app/models/project_services/ci/slack_service.rb | 2 +- app/services/ci/create_commit_service.rb | 2 +- app/views/projects/builds/show.html.haml | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb index 201b6f62b86..296890c5e7c 100644 --- a/app/models/ci/commit.rb +++ b/app/models/ci/commit.rb @@ -48,7 +48,7 @@ module Ci end def retry - builds_without_retry.each do |build| + latest_builds.each do |build| Ci::Build.retry(build) end end @@ -113,12 +113,12 @@ module Ci @latest_statuses ||= statuses.latest.to_a end - def builds_without_retry - @builds_without_retry ||= builds.latest.to_a + def latest_builds + @latest_builds ||= builds.latest.to_a end - def builds_without_retry_for_ref(ref) - builds_without_retry.select { |build| build.ref == ref } + def latest_builds_for_ref(ref) + latest_builds.select { |build| build.ref == ref } end def retried @@ -181,7 +181,7 @@ module Ci def coverage if project.coverage_enabled? - coverage_array = builds_without_retry.map(&:coverage).compact + coverage_array = latest_builds.map(&:coverage).compact if coverage_array.size >= 1 '%.2f' % (coverage_array.reduce(:+) / coverage_array.size) end @@ -189,7 +189,7 @@ module Ci end def matrix_for_ref?(ref) - builds_without_retry_for_ref(ref).size > 1 + latest_builds_for_ref(ref).size > 1 end def config_processor diff --git a/app/models/project_services/ci/hip_chat_service.rb b/app/models/project_services/ci/hip_chat_service.rb index 0e6e97394bc..f17993d9f3b 100644 --- a/app/models/project_services/ci/hip_chat_service.rb +++ b/app/models/project_services/ci/hip_chat_service.rb @@ -49,7 +49,7 @@ module Ci commit = build.commit return unless commit - return unless commit.builds_without_retry.include? build + return unless commit.latest_builds.include? build case commit.status.to_sym when :failed diff --git a/app/models/project_services/ci/mail_service.rb b/app/models/project_services/ci/mail_service.rb index 11a2743f969..fd193301001 100644 --- a/app/models/project_services/ci/mail_service.rb +++ b/app/models/project_services/ci/mail_service.rb @@ -48,7 +48,7 @@ module Ci # it doesn't make sense to send emails for retried builds commit = build.commit return unless commit - return unless commit.builds_without_retry.include?(build) + return unless commit.latest_builds.include?(build) case build.status.to_sym when :failed diff --git a/app/models/project_services/ci/slack_message.rb b/app/models/project_services/ci/slack_message.rb index 5ac8907ecd0..dc050a3fc59 100644 --- a/app/models/project_services/ci/slack_message.rb +++ b/app/models/project_services/ci/slack_message.rb @@ -23,7 +23,7 @@ module Ci def attachments fields = [] - commit.builds_without_retry.each do |build| + commit.latest_builds.each do |build| next if build.allow_failure? next unless build.failed? fields << { diff --git a/app/models/project_services/ci/slack_service.rb b/app/models/project_services/ci/slack_service.rb index 76db573dc17..ee8e4988826 100644 --- a/app/models/project_services/ci/slack_service.rb +++ b/app/models/project_services/ci/slack_service.rb @@ -48,7 +48,7 @@ module Ci commit = build.commit return unless commit - return unless commit.builds_without_retry.include?(build) + return unless commit.latest_builds.include?(build) case commit.status.to_sym when :failed diff --git a/app/services/ci/create_commit_service.rb b/app/services/ci/create_commit_service.rb index 79b0291fabc..479a2d6defc 100644 --- a/app/services/ci/create_commit_service.rb +++ b/app/services/ci/create_commit_service.rb @@ -21,7 +21,7 @@ module Ci commit.update_committed! commit.create_builds(ref, tag, user) end - + commit end end diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml index b561078e8c7..9c3ae622b72 100644 --- a/app/views/projects/builds/show.html.haml +++ b/app/views/projects/builds/show.html.haml @@ -9,7 +9,7 @@ #up-build-trace - if @commit.matrix_for_ref?(@build.ref) %ul.center-top-menu.build-top-menu - - @commit.builds_without_retry_for_ref(@build.ref).each do |build| + - @commit.latest_builds_for_ref(@build.ref).each do |build| %li{class: ('active' if build == @build) } = link_to namespace_project_build_path(@project.namespace, @project, build) do = ci_icon_for_status(build.status) @@ -20,7 +20,7 @@ = build.id - - unless @commit.builds_without_retry_for_ref(@build.ref).include?(@build) + - unless @commit.latest_builds_for_ref(@build.ref).include?(@build) %li.active %a Build ##{@build.id} -- cgit v1.2.1 From c61dc1315077ad4e175a3c76991872c0e7b1d2ab Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 12 Oct 2015 16:41:36 +0200 Subject: Fix some changes --- lib/api/entities.rb | 2 +- spec/models/commit_status_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/api/entities.rb b/lib/api/entities.rb index bfb242bb6fd..519072d0157 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -65,7 +65,7 @@ module API expose :issues_enabled, :merge_requests_enabled, :wiki_enabled, :snippets_enabled, :created_at, :last_activity_at expose :creator_id expose :namespace - expose :forked_from_project, using: Entities::ForkedFromProject, if: lambda { |project, options| project.forked? } + expose :forked_from_project, using: Entities::ForkedFromProject, if: lambda{ | project, options | project.forked? } expose :avatar_url expose :star_count, :forks_count end diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb index cbefa7798de..c96a606fdaa 100644 --- a/spec/models/commit_status_spec.rb +++ b/spec/models/commit_status_spec.rb @@ -142,7 +142,7 @@ describe CommitStatus do end it 'return statuses with equal and nil ref set' do - is_expected.to eq([@commit1, @commit3]) + is_expected.to eq([@commit1]) end end -- cgit v1.2.1 From 1af4fcfa123370ab6dcf38a424c54029d7734032 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 12 Oct 2015 19:00:21 +0000 Subject: Fix typos in application.scss --- app/assets/stylesheets/application.scss | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 65f775ca3f3..7b060ce4853 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -13,9 +13,9 @@ /* * Welcome to GitLab css! - * If you need to add or modify UI component that is commont for many pages - * like table or typography then make changes in framework/ directory. - * If you need to add uniq style that should affect only one page - use pages/ + * If you need to add or modify UI component that is common for many pages + * like a table or typography then make changes in the framework/ directory. + * If you need to add unique style that should affect only one page - use pages/ * directory. */ @@ -48,4 +48,4 @@ /* * Styles for JS behaviors. */ -@import "behaviors.scss"; +@import "behaviors.scss"; \ No newline at end of file -- cgit v1.2.1 From daca1c6511c3a09d5f0c33a8c4d29487e668afc2 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 12 Oct 2015 21:35:52 +0200 Subject: Fix broken tests --- app/models/ci/commit.rb | 4 ++-- lib/api/commit_statuses.rb | 2 +- spec/models/ci/commit_spec.rb | 9 +++++---- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb index 296890c5e7c..f6fc4645947 100644 --- a/app/models/ci/commit.rb +++ b/app/models/ci/commit.rb @@ -82,7 +82,7 @@ module Ci end def stage - running_or_pending = statuses.latest.running_or_pending + running_or_pending = statuses.latest.running_or_pending.ordered running_or_pending.first.try(:stage) end @@ -189,7 +189,7 @@ module Ci end def matrix_for_ref?(ref) - latest_builds_for_ref(ref).size > 1 + builds_without_retry_for_ref(ref).size > 1 end def config_processor diff --git a/lib/api/commit_statuses.rb b/lib/api/commit_statuses.rb index 50ca89079e0..2c0596c9dfb 100644 --- a/lib/api/commit_statuses.rb +++ b/lib/api/commit_statuses.rb @@ -43,7 +43,7 @@ module API # Examples: # POST /projects/:id/statuses/:sha post ':id/statuses/:sha' do - authorize! :create_commit_statuses, user_project + authorize! :create_commit_status, user_project required_attributes! [:state] attrs = attributes_for_keys [:ref, :target_url, :description, :context, :name] commit = @project.commit(params[:sha]) diff --git a/spec/models/ci/commit_spec.rb b/spec/models/ci/commit_spec.rb index 371add4ee59..330971174fb 100644 --- a/spec/models/ci/commit_spec.rb +++ b/spec/models/ci/commit_spec.rb @@ -125,7 +125,7 @@ describe Ci::Commit do end it 'returns all refs' do - is_expected.to contain_exactly('master', 'develop') + is_expected.to contain_exactly('master', 'develop', nil) end end @@ -225,9 +225,10 @@ describe Ci::Commit do it 'rebuilds commit' do expect(commit.status).to eq('skipped') expect(create_builds(trigger_request)).to be_truthy - commit.builds.reload - expect(commit.builds.size).to eq(2) - expect(commit.status).to eq('pending') + + # since everything in Ci::Commit is cached we need to fetch a new object + new_commit = Ci::Commit.find_by_id(commit.id) + expect(new_commit.status).to eq('pending') end end end -- cgit v1.2.1 From 766da5fa7bdded8a333a758d7b172533ade5a934 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 12 Oct 2015 22:34:59 +0200 Subject: Fix broken matrix_for_ref? Signed-off-by: Kamil Trzcinski --- app/models/ci/commit.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb index f6fc4645947..68864edfbbf 100644 --- a/app/models/ci/commit.rb +++ b/app/models/ci/commit.rb @@ -189,7 +189,7 @@ module Ci end def matrix_for_ref?(ref) - builds_without_retry_for_ref(ref).size > 1 + latest_builds_for_ref(ref).size > 1 end def config_processor -- cgit v1.2.1 From 4bf69b0bd9a27e675c98eee998f24c0122030731 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 12 Oct 2015 23:59:21 +0200 Subject: Fix feature tests --- app/views/projects/commit/ci.html.haml | 2 +- features/steps/project/commits/commits.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/projects/commit/ci.html.haml b/app/views/projects/commit/ci.html.haml index 585f012fe04..4a1ef378a30 100644 --- a/app/views/projects/commit/ci.html.haml +++ b/app/views/projects/commit/ci.html.haml @@ -21,7 +21,7 @@ \.gitlab-ci.yml not found in this commit .gray-content-block.second-block - Latest + Latest builds - if @ci_commit.duration > 0 %small.pull-right %i.fa.fa-time diff --git a/features/steps/project/commits/commits.rb b/features/steps/project/commits/commits.rb index ae5f90004e6..a3cb83880e3 100644 --- a/features/steps/project/commits/commits.rb +++ b/features/steps/project/commits/commits.rb @@ -118,6 +118,6 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps step 'I see builds list' do expect(page).to have_content "build: pending" - expect(page).to have_content "Builds for master" + expect(page).to have_content "Latest builds" end end -- cgit v1.2.1 From 7816488a8967d4c87e84a35027499c1a5cb5406e Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Mon, 12 Oct 2015 23:02:27 -0700 Subject: Add "New Page" button to Wiki Pages tab Closes #2998 --- CHANGELOG | 1 + app/views/projects/wikis/pages.html.haml | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index a3d796bea66..d86f28bdc9a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -45,6 +45,7 @@ v 8.1.0 (unreleased) - Fix position of hamburger in header for smaller screens (Han Loong Liauw) - Fix bug where Emojis in Markdown would truncate remaining text (Sakata Sinji) - Persist filters when sorting on admin user page (Jerry Lukins) + - Add "New Page" button to Wiki Pages tab (Stan Hu) v 8.0.4 - Fix Message-ID header to be RFC 2111-compliant to prevent e-mails being dropped (Stan Hu) diff --git a/app/views/projects/wikis/pages.html.haml b/app/views/projects/wikis/pages.html.haml index 03e6a522b25..d179a1abec1 100644 --- a/app/views/projects/wikis/pages.html.haml +++ b/app/views/projects/wikis/pages.html.haml @@ -3,6 +3,7 @@ = render 'nav' .gray-content-block + = render 'main_links' %h3.page-title All Pages %ul.content-list -- cgit v1.2.1 From cb9b53958a4b49f4c1ab796d430674a64f1ccb9f Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Tue, 13 Oct 2015 11:12:39 +0300 Subject: update changelog --- CHANGELOG | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index a3d796bea66..8f0bbb12d7b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -45,6 +45,8 @@ v 8.1.0 (unreleased) - Fix position of hamburger in header for smaller screens (Han Loong Liauw) - Fix bug where Emojis in Markdown would truncate remaining text (Sakata Sinji) - Persist filters when sorting on admin user page (Jerry Lukins) + - Add spellcheck=false to certain input fields + - Invalidate stored service password if the endpoint URL is changed v 8.0.4 - Fix Message-ID header to be RFC 2111-compliant to prevent e-mails being dropped (Stan Hu) -- cgit v1.2.1 From 0e34154d214c0e470b7783b5086a70b4fe4cb08f Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Fri, 9 Oct 2015 19:35:09 +0300 Subject: Project names are not fully shown if group name is too big, even on group page view --- CHANGELOG | 1 + app/views/groups/_projects.html.haml | 2 +- app/views/shared/projects/_list.html.haml | 3 ++- app/views/shared/projects/_project.html.haml | 3 ++- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 8f0bbb12d7b..063b85d0eb7 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -47,6 +47,7 @@ v 8.1.0 (unreleased) - Persist filters when sorting on admin user page (Jerry Lukins) - Add spellcheck=false to certain input fields - Invalidate stored service password if the endpoint URL is changed + - Project names are not fully shown if group name is too big, even on group page view v 8.0.4 - Fix Message-ID header to be RFC 2111-compliant to prevent e-mails being dropped (Stan Hu) diff --git a/app/views/groups/_projects.html.haml b/app/views/groups/_projects.html.haml index 76da3276e47..133f3e2d5a8 100644 --- a/app/views/groups/_projects.html.haml +++ b/app/views/groups/_projects.html.haml @@ -7,4 +7,4 @@ = link_to new_project_path(namespace_id: @group.id), class: 'btn btn-green' do New project - = render 'shared/projects/list', projects: @projects, projects_limit: 20, stars: false + = render 'shared/projects/list', projects: @projects, projects_limit: 20, stars: false, skip_namespace: true diff --git a/app/views/shared/projects/_list.html.haml b/app/views/shared/projects/_list.html.haml index 16e1d8421de..357cfd6a370 100644 --- a/app/views/shared/projects/_list.html.haml +++ b/app/views/shared/projects/_list.html.haml @@ -2,11 +2,12 @@ - avatar = true unless local_assigns[:avatar] == false - stars = true unless local_assigns[:stars] == false - ci = false unless local_assigns[:ci] == true +- skip_namespace = false unless local_assigns[:skip_namespace] == true %ul.projects-list - projects.each_with_index do |project, i| - css_class = (i >= projects_limit) ? 'hide' : nil - = render "shared/projects/project", project: project, + = render "shared/projects/project", project: project, skip_namespace: skip_namespace, avatar: avatar, stars: stars, css_class: css_class, ci: ci - if projects.size > projects_limit diff --git a/app/views/shared/projects/_project.html.haml b/app/views/shared/projects/_project.html.haml index e67e5a8a638..aee839b44e7 100644 --- a/app/views/shared/projects/_project.html.haml +++ b/app/views/shared/projects/_project.html.haml @@ -1,6 +1,7 @@ - avatar = true unless local_assigns[:avatar] == false - stars = true unless local_assigns[:stars] == false - ci = false unless local_assigns[:ci] == true +- skip_namespace = false unless local_assigns[:skip_namespace] == true - css_class = '' unless local_assigns[:css_class] - css_class += " no-description" unless project.description.present? %li.project-row{ class: css_class } @@ -11,7 +12,7 @@ = project_icon(project, alt: '', class: 'avatar project-avatar s46') %span.project-full-name %span.namespace-name - - if project.namespace + - if project.namespace && !skip_namespace = project.namespace.human_name \/ %span.project-name.filter-title -- cgit v1.2.1 From e4a9447451bfccbea6943bb5546b03c81321eb77 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 13 Oct 2015 10:55:06 +0200 Subject: Rename bootstrap css file and refactor typography css Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/framework.scss | 5 +- app/assets/stylesheets/framework/gl_bootstrap.scss | 273 --------------------- app/assets/stylesheets/framework/gl_variables.scss | 158 ------------ app/assets/stylesheets/framework/mixins.scss | 141 ----------- app/assets/stylesheets/framework/tables.scss | 16 ++ app/assets/stylesheets/framework/tw_bootstrap.scss | 253 +++++++++++++++++++ .../framework/tw_bootstrap_variables.scss | 158 ++++++++++++ app/assets/stylesheets/framework/typography.scss | 145 ++++++++++- 8 files changed, 573 insertions(+), 576 deletions(-) delete mode 100644 app/assets/stylesheets/framework/gl_bootstrap.scss delete mode 100644 app/assets/stylesheets/framework/gl_variables.scss create mode 100644 app/assets/stylesheets/framework/tw_bootstrap.scss create mode 100644 app/assets/stylesheets/framework/tw_bootstrap_variables.scss diff --git a/app/assets/stylesheets/framework.scss b/app/assets/stylesheets/framework.scss index c5e23c1c328..1ec9d2fd84f 100644 --- a/app/assets/stylesheets/framework.scss +++ b/app/assets/stylesheets/framework.scss @@ -2,8 +2,9 @@ @import "framework/variables"; @import "framework/mixins"; @import "framework/layout"; -@import 'framework/gl_variables'; -@import 'framework/gl_bootstrap'; +@import 'framework/tw_bootstrap_variables'; +@import 'framework/tw_bootstrap'; + @import "framework/avatar.scss"; @import "framework/blocks.scss"; @import "framework/buttons.scss"; diff --git a/app/assets/stylesheets/framework/gl_bootstrap.scss b/app/assets/stylesheets/framework/gl_bootstrap.scss deleted file mode 100644 index eb8d23d6453..00000000000 --- a/app/assets/stylesheets/framework/gl_bootstrap.scss +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Twitter bootstrap with GitLab customizations/additions - * - */ - -// Core variables and mixins -@import "bootstrap/variables"; -@import "bootstrap/mixins"; - -// Reset -@import "bootstrap/normalize"; -@import "bootstrap/print"; - -// Core CSS -@import "bootstrap/scaffolding"; -@import "bootstrap/type"; -@import "bootstrap/code"; -@import "bootstrap/grid"; -@import "bootstrap/tables"; -@import "bootstrap/forms"; -@import "bootstrap/buttons"; - -// Components -@import "bootstrap/component-animations"; -@import "bootstrap/dropdowns"; -@import "bootstrap/button-groups"; -@import "bootstrap/input-groups"; -@import "bootstrap/navs"; -@import "bootstrap/navbar"; -@import "bootstrap/breadcrumbs"; -@import "bootstrap/pagination"; -@import "bootstrap/pager"; -@import "bootstrap/labels"; -@import "bootstrap/badges"; -@import "bootstrap/jumbotron"; -@import "bootstrap/thumbnails"; -@import "bootstrap/alerts"; -@import "bootstrap/progress-bars"; -@import "bootstrap/list-group"; -@import "bootstrap/wells"; -@import "bootstrap/close"; -@import "bootstrap/panels"; - -// Components w/ JavaScript -@import "bootstrap/modals"; -@import "bootstrap/tooltip"; -@import "bootstrap/popovers"; -@import "bootstrap/carousel"; - -// Utility classes -.clearfix { - @include clearfix(); -} -.center-block { - @include center-block(); -} -.pull-right { - float: right !important; -} -.pull-left { - float: left !important; -} -.hide { - display: none; -} -.show { - display: block !important; -} -.invisible { - visibility: hidden; -} -.text-hide { - @include text-hide(); -} -.hidden { - display: none !important; - visibility: hidden !important; -} -.affix { - position: fixed; -} - -@import "bootstrap/responsive-utilities"; - -// Labels -.label { - padding: 2px 4px; - font-size: 13px; - font-style: normal; - font-weight: normal; - display: inline-block; - - &.label-gray { - background-color: #f8fafc; - color: $gl-gray; - text-shadow: none; - } - - &.label-inverse { - background-color: #333333; - } -} - -// Nav tabs -.nav.nav-tabs { - margin-bottom: 15px; - - li { - > a { - margin-right: 5px; - line-height: 20px; - border-color: #EEE; - color: #888; - border-bottom: 1px solid #ddd; - .badge { - background-color: #eee; - color: #888; - text-shadow: 0 1px 1px #fff; - } - i.fa { - line-height: 14px; - } - } - &.active { - > a { - border-color: #CCC; - border-bottom: 1px solid #fff; - color: #333; - font-weight: bold; - } - } - } -} - -.nav-tabs > li > a, -.nav-pills > li > a { - color: #666; -} - -.nav-pills > .active > a > span > .badge { - background-color: #fff; - color: $gl-primary; -} - - -/** - * fix to keep tooltips position in top navigation bar - * - */ -.navbar .nav > li { - position: relative; - white-space: nowrap; -} - -/** - * Add some extra stuff to panels - * - */ - -.container-blank .panel .panel-heading { - font-size: 17px; - line-height: 38px; -} - -.panel { - box-shadow: none; - - .panel-heading { - .panel-head-actions { - position: relative; - top: -5px; - float: right; - } - } - - .panel-body { - form { - margin: 0; - } - - .form-actions { - margin: -15px; - margin-top: 18px; - } - } - - .panel-footer { - .pagination { - margin: 0; - } - - .btn { - min-width: 124px; - } - } - - &.panel-small { - .panel-heading { - padding: 6px 15px; - font-size: 13px; - font-weight: normal; - a { - color: #777; - } - } - } -} - -.panel-succes .panel-heading, -.panel-info .panel-heading, -.panel-danger .panel-heading, -.panel-warning .panel-heading, -.panel-primary .panel-heading, -.alert { - a:not(.btn) { - @extend .alert-link; - color: #fff; - text-decoration: underline; - } -} - -.alert-help { - background-color: $background-color; - border: 1px solid $border-color; - color: $gl-gray; -} - -// Typography ================================================================= - -.text-primary, -.text-primary:hover { - color: $brand-primary; -} - -.text-success, -.text-success:hover { - color: $brand-success; -} - -.text-danger, -.text-danger:hover { - color: $brand-danger; -} - -.text-warning, -.text-warning:hover { - color: $brand-warning; -} - -.text-info, -.text-info:hover { - color: $brand-info; -} - -// Tables ===================================================================== - -table.table { - .dropdown-menu a { - text-decoration: none; - } - - .success, - .warning, - .danger, - .info { - color: #fff; - - a:not(.btn) { - text-decoration: underline; - color: #fff; - } - } -} diff --git a/app/assets/stylesheets/framework/gl_variables.scss b/app/assets/stylesheets/framework/gl_variables.scss deleted file mode 100644 index 18632da4f2a..00000000000 --- a/app/assets/stylesheets/framework/gl_variables.scss +++ /dev/null @@ -1,158 +0,0 @@ -// Override Bootstrap variables here (defaults from bootstrap-sass v3.3.3): -// For all variables see https://github.com/twbs/bootstrap-sass/blob/master/templates/project/_bootstrap-variables.sass -// -// Variables -// -------------------------------------------------- - - -//== Colors -// -//## Gray and brand colors for use across Bootstrap. - -// $gray-base: #000 -// $gray-darker: lighten($gray-base, 13.5%) // #222 -// $gray-dark: lighten($gray-base, 20%) // #333 -// $gray: lighten($gray-base, 33.5%) // #555 -// $gray-light: lighten($gray-base, 46.7%) // #777 -// $gray-lighter: lighten($gray-base, 93.5%) // #eee - -$brand-primary: $gl-primary; -$brand-success: $gl-success; -$brand-info: $gl-info; -$brand-warning: $gl-warning; -$brand-danger: $gl-danger; - -$border-radius-base: 2px !default; -$border-radius-large: 2px !default; -$border-radius-small: 2px !default; - - -//== Scaffolding -// -$text-color: $gl-text-color; -$link-color: $gl-link-color; - - -//== Typography -// -//## Font, line-height, and color for body text, headings, and more. - -$font-family-sans-serif: $regular_font; -$font-family-monospace: $monospace_font; -$font-size-base: $gl-font-size; - - -//== Components -// -//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start). - -$padding-base-vertical: 9px; -$padding-base-horizontal: $gl-padding; -$component-active-color: #fff; -$component-active-bg: $brand-info; - -//== Forms -// -//## - -$input-color: $text-color; -$input-border: #e7e9ed; -$input-border-focus: #7F8FA4; -$legend-color: $text-color; - - -//== Pagination -// -//## - -$pagination-color: $gl-gray; -$pagination-bg: $background-color; -$pagination-border: transparent; - -$pagination-hover-color: #fff; -$pagination-hover-bg: $brand-info; -$pagination-hover-border: transparent; - -$pagination-active-color: #fff; -$pagination-active-bg: $brand-info; -$pagination-active-border: transparent; - -$pagination-disabled-color: #fff; -$pagination-disabled-bg: lighten($brand-info, 15%); -$pagination-disabled-border: transparent; - - -//== Form states and alerts -// -//## Define colors for form feedback states and, by default, alerts. - -$state-success-text: #fff; -$state-success-bg: $brand-success; -$state-success-border: $brand-success; - -$state-info-text: #fff; -$state-info-bg: $brand-info; -$state-info-border: $brand-info; - -$state-warning-text: #fff; -$state-warning-bg: $brand-warning; -$state-warning-border: $brand-warning; - -$state-danger-text: #fff; -$state-danger-bg: $brand-danger; -$state-danger-border: $brand-danger; - - -//== Alerts -// -//## Define alert colors, border radius, and padding. - -$alert-border-radius: 0; - - -//== Panels -// -//## - -$panel-border-radius: 2px; -$panel-default-text: $text-color; -$panel-default-border: $border-color; -$panel-default-heading-bg: $background-color; -$panel-footer-bg: $background-color; -$panel-inner-border: $border-color; - -//== Wells -// -//## - -$well-bg: #F9F9F9; -$well-border: #EEE; - -//== Code -// -//## - -$code-color: #c7254e; -$code-bg: #f9f2f4; - -$kbd-color: #fff; -$kbd-bg: #333; - -//== Buttons -// -//## -$btn-default-color: $gl-text-color; -$btn-default-bg: #fff; -$btn-default-border: #e7e9ed; - -//== Nav -// -//## -$nav-link-padding: 13px $gl-padding; - -//== Code -// -//## -$pre-bg: #f8fafc !default; -$pre-color: $gl-gray !default; -$pre-border-color: #e7e9ed; diff --git a/app/assets/stylesheets/framework/mixins.scss b/app/assets/stylesheets/framework/mixins.scss index c74a6d39824..089e6958eeb 100644 --- a/app/assets/stylesheets/framework/mixins.scss +++ b/app/assets/stylesheets/framework/mixins.scss @@ -54,147 +54,6 @@ @include box-shadow(0 0 0 3px #f1f1f1); } -@mixin md-typography { - color: $md-text-color; - - a { - color: $md-link-color; - } - - img { - max-width: 100%; - } - - *:first-child { - margin-top: 0; - } - - code { - font-family: $monospace_font; - white-space: pre; - word-wrap: normal; - padding: 1px 2px; - } - - kbd { - display: inline-block; - padding: 3px 5px; - font-size: 11px; - line-height: 10px; - color: #555; - vertical-align: middle; - background-color: #FCFCFC; - border-width: 1px; - border-style: solid; - border-color: #CCC #CCC #BBB; - border-image: none; - border-radius: 3px; - box-shadow: 0px -1px 0px #BBB inset; - } - - h1 { - font-size: 1.3em; - font-weight: 600; - margin: 24px 0 12px 0; - padding: 0 0 10px 0; - border-bottom: 1px solid #e7e9ed; - color: #313236; - } - - h2 { - font-size: 1.2em; - font-weight: 600; - margin: 24px 0 12px 0; - color: #313236; - } - - h3 { - margin: 24px 0 12px 0; - font-size: 1.25em; - } - - h4 { - margin: 24px 0 12px 0; - font-size: 1.1em; - } - - h5 { - margin: 24px 0 12px 0; - font-size: 1em; - } - - h6 { - margin: 24px 0 12px 0; - font-size: 0.90em; - } - - blockquote { - padding: 8px 21px; - margin: 12px 0 12px; - border-left: 3px solid #e7e9ed; - } - - blockquote p { - color: #7f8fa4 !important; - font-size: 15px; - line-height: 1.5; - } - - p { - color:#5c5d5e; - margin:6px 0 0 0; - } - - table { - @extend .table; - @extend .table-bordered; - margin: 12px 0 12px 0; - color: #5c5d5e; - th { - background: #f8fafc; - } - } - - pre { - margin: 12px 0 12px 0 !important; - background-color: #f8fafc !important; - font-size: 13px !important; - color: #5b6169 !important; - line-height: 1.6em !important; - @include border-radius(2px); - } - - p > code { - font-weight: inherit; - } - - - ul { - color: #5c5d5e; - } - - li { - line-height: 1.6em; - } - - a[href*="/uploads/"], a[href*="storage.googleapis.com/google-code-attachments/"] { - &:before { - margin-right: 4px; - - font: normal normal normal 14px/1 FontAwesome; - font-size: inherit; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - content: "\f0c6"; - } - - &:hover:before { - text-decoration: none; - } - } -} - - @mixin str-truncated($max_width: 82%) { display: inline-block; overflow: hidden; diff --git a/app/assets/stylesheets/framework/tables.scss b/app/assets/stylesheets/framework/tables.scss index a66e45577de..76163b3a05e 100644 --- a/app/assets/stylesheets/framework/tables.scss +++ b/app/assets/stylesheets/framework/tables.scss @@ -1,5 +1,21 @@ table { &.table { + .dropdown-menu a { + text-decoration: none; + } + + .success, + .warning, + .danger, + .info { + color: #fff; + + a:not(.btn) { + text-decoration: underline; + color: #fff; + } + } + tr { td, th { padding: 8px 10px; diff --git a/app/assets/stylesheets/framework/tw_bootstrap.scss b/app/assets/stylesheets/framework/tw_bootstrap.scss new file mode 100644 index 00000000000..722b44d2d10 --- /dev/null +++ b/app/assets/stylesheets/framework/tw_bootstrap.scss @@ -0,0 +1,253 @@ +/* + * Twitter bootstrap with GitLab customizations/additions + * + */ + +// Core variables and mixins +@import "bootstrap/variables"; +@import "bootstrap/mixins"; + +// Reset +@import "bootstrap/normalize"; +@import "bootstrap/print"; + +// Core CSS +@import "bootstrap/scaffolding"; +@import "bootstrap/type"; +@import "bootstrap/code"; +@import "bootstrap/grid"; +@import "bootstrap/tables"; +@import "bootstrap/forms"; +@import "bootstrap/buttons"; + +// Components +@import "bootstrap/component-animations"; +@import "bootstrap/dropdowns"; +@import "bootstrap/button-groups"; +@import "bootstrap/input-groups"; +@import "bootstrap/navs"; +@import "bootstrap/navbar"; +@import "bootstrap/breadcrumbs"; +@import "bootstrap/pagination"; +@import "bootstrap/pager"; +@import "bootstrap/labels"; +@import "bootstrap/badges"; +@import "bootstrap/jumbotron"; +@import "bootstrap/thumbnails"; +@import "bootstrap/alerts"; +@import "bootstrap/progress-bars"; +@import "bootstrap/list-group"; +@import "bootstrap/wells"; +@import "bootstrap/close"; +@import "bootstrap/panels"; + +// Components w/ JavaScript +@import "bootstrap/modals"; +@import "bootstrap/tooltip"; +@import "bootstrap/popovers"; +@import "bootstrap/carousel"; + +// Utility classes +.clearfix { + @include clearfix(); +} +.center-block { + @include center-block(); +} +.pull-right { + float: right !important; +} +.pull-left { + float: left !important; +} +.hide { + display: none; +} +.show { + display: block !important; +} +.invisible { + visibility: hidden; +} +.text-hide { + @include text-hide(); +} +.hidden { + display: none !important; + visibility: hidden !important; +} +.affix { + position: fixed; +} + +@import "bootstrap/responsive-utilities"; + +// Labels +.label { + padding: 2px 4px; + font-size: 13px; + font-style: normal; + font-weight: normal; + display: inline-block; + + &.label-gray { + background-color: #f8fafc; + color: $gl-gray; + text-shadow: none; + } + + &.label-inverse { + background-color: #333333; + } +} + +// Nav tabs +.nav.nav-tabs { + margin-bottom: 15px; + + li { + > a { + margin-right: 5px; + line-height: 20px; + border-color: #EEE; + color: #888; + border-bottom: 1px solid #ddd; + .badge { + background-color: #eee; + color: #888; + text-shadow: 0 1px 1px #fff; + } + i.fa { + line-height: 14px; + } + } + &.active { + > a { + border-color: #CCC; + border-bottom: 1px solid #fff; + color: #333; + font-weight: bold; + } + } + } +} + +.nav-tabs > li > a, +.nav-pills > li > a { + color: #666; +} + +.nav-pills > .active > a > span > .badge { + background-color: #fff; + color: $gl-primary; +} + + +/** + * fix to keep tooltips position in top navigation bar + * + */ +.navbar .nav > li { + position: relative; + white-space: nowrap; +} + +/** + * Add some extra stuff to panels + * + */ + +.container-blank .panel .panel-heading { + font-size: 17px; + line-height: 38px; +} + +.panel { + box-shadow: none; + + .panel-heading { + .panel-head-actions { + position: relative; + top: -5px; + float: right; + } + } + + .panel-body { + form { + margin: 0; + } + + .form-actions { + margin: -15px; + margin-top: 18px; + } + } + + .panel-footer { + .pagination { + margin: 0; + } + + .btn { + min-width: 124px; + } + } + + &.panel-small { + .panel-heading { + padding: 6px 15px; + font-size: 13px; + font-weight: normal; + a { + color: #777; + } + } + } +} + +.panel-succes .panel-heading, +.panel-info .panel-heading, +.panel-danger .panel-heading, +.panel-warning .panel-heading, +.panel-primary .panel-heading, +.alert { + a:not(.btn) { + @extend .alert-link; + color: #fff; + text-decoration: underline; + } +} + +.alert-help { + background-color: $background-color; + border: 1px solid $border-color; + color: $gl-gray; +} + +// Typography ================================================================= + +.text-primary, +.text-primary:hover { + color: $brand-primary; +} + +.text-success, +.text-success:hover { + color: $brand-success; +} + +.text-danger, +.text-danger:hover { + color: $brand-danger; +} + +.text-warning, +.text-warning:hover { + color: $brand-warning; +} + +.text-info, +.text-info:hover { + color: $brand-info; +} diff --git a/app/assets/stylesheets/framework/tw_bootstrap_variables.scss b/app/assets/stylesheets/framework/tw_bootstrap_variables.scss new file mode 100644 index 00000000000..18632da4f2a --- /dev/null +++ b/app/assets/stylesheets/framework/tw_bootstrap_variables.scss @@ -0,0 +1,158 @@ +// Override Bootstrap variables here (defaults from bootstrap-sass v3.3.3): +// For all variables see https://github.com/twbs/bootstrap-sass/blob/master/templates/project/_bootstrap-variables.sass +// +// Variables +// -------------------------------------------------- + + +//== Colors +// +//## Gray and brand colors for use across Bootstrap. + +// $gray-base: #000 +// $gray-darker: lighten($gray-base, 13.5%) // #222 +// $gray-dark: lighten($gray-base, 20%) // #333 +// $gray: lighten($gray-base, 33.5%) // #555 +// $gray-light: lighten($gray-base, 46.7%) // #777 +// $gray-lighter: lighten($gray-base, 93.5%) // #eee + +$brand-primary: $gl-primary; +$brand-success: $gl-success; +$brand-info: $gl-info; +$brand-warning: $gl-warning; +$brand-danger: $gl-danger; + +$border-radius-base: 2px !default; +$border-radius-large: 2px !default; +$border-radius-small: 2px !default; + + +//== Scaffolding +// +$text-color: $gl-text-color; +$link-color: $gl-link-color; + + +//== Typography +// +//## Font, line-height, and color for body text, headings, and more. + +$font-family-sans-serif: $regular_font; +$font-family-monospace: $monospace_font; +$font-size-base: $gl-font-size; + + +//== Components +// +//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start). + +$padding-base-vertical: 9px; +$padding-base-horizontal: $gl-padding; +$component-active-color: #fff; +$component-active-bg: $brand-info; + +//== Forms +// +//## + +$input-color: $text-color; +$input-border: #e7e9ed; +$input-border-focus: #7F8FA4; +$legend-color: $text-color; + + +//== Pagination +// +//## + +$pagination-color: $gl-gray; +$pagination-bg: $background-color; +$pagination-border: transparent; + +$pagination-hover-color: #fff; +$pagination-hover-bg: $brand-info; +$pagination-hover-border: transparent; + +$pagination-active-color: #fff; +$pagination-active-bg: $brand-info; +$pagination-active-border: transparent; + +$pagination-disabled-color: #fff; +$pagination-disabled-bg: lighten($brand-info, 15%); +$pagination-disabled-border: transparent; + + +//== Form states and alerts +// +//## Define colors for form feedback states and, by default, alerts. + +$state-success-text: #fff; +$state-success-bg: $brand-success; +$state-success-border: $brand-success; + +$state-info-text: #fff; +$state-info-bg: $brand-info; +$state-info-border: $brand-info; + +$state-warning-text: #fff; +$state-warning-bg: $brand-warning; +$state-warning-border: $brand-warning; + +$state-danger-text: #fff; +$state-danger-bg: $brand-danger; +$state-danger-border: $brand-danger; + + +//== Alerts +// +//## Define alert colors, border radius, and padding. + +$alert-border-radius: 0; + + +//== Panels +// +//## + +$panel-border-radius: 2px; +$panel-default-text: $text-color; +$panel-default-border: $border-color; +$panel-default-heading-bg: $background-color; +$panel-footer-bg: $background-color; +$panel-inner-border: $border-color; + +//== Wells +// +//## + +$well-bg: #F9F9F9; +$well-border: #EEE; + +//== Code +// +//## + +$code-color: #c7254e; +$code-bg: #f9f2f4; + +$kbd-color: #fff; +$kbd-bg: #333; + +//== Buttons +// +//## +$btn-default-color: $gl-text-color; +$btn-default-bg: #fff; +$btn-default-border: #e7e9ed; + +//== Nav +// +//## +$nav-link-padding: 13px $gl-padding; + +//== Code +// +//## +$pre-bg: #f8fafc !default; +$pre-color: $gl-gray !default; +$pre-border-color: #e7e9ed; diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss index 6a3cb49baae..bf36f96cc97 100644 --- a/app/assets/stylesheets/framework/typography.scss +++ b/app/assets/stylesheets/framework/typography.scss @@ -1,3 +1,144 @@ +@mixin md-typography { + color: $md-text-color; + + a { + color: $md-link-color; + } + + img { + max-width: 100%; + } + + *:first-child { + margin-top: 0; + } + + code { + font-family: $monospace_font; + white-space: pre; + word-wrap: normal; + padding: 1px 2px; + } + + kbd { + display: inline-block; + padding: 3px 5px; + font-size: 11px; + line-height: 10px; + color: #555; + vertical-align: middle; + background-color: #FCFCFC; + border-width: 1px; + border-style: solid; + border-color: #CCC #CCC #BBB; + border-image: none; + border-radius: 3px; + box-shadow: 0px -1px 0px #BBB inset; + } + + h1 { + font-size: 1.3em; + font-weight: 600; + margin: 24px 0 12px 0; + padding: 0 0 10px 0; + border-bottom: 1px solid #e7e9ed; + color: #313236; + } + + h2 { + font-size: 1.2em; + font-weight: 600; + margin: 24px 0 12px 0; + color: #313236; + } + + h3 { + margin: 24px 0 12px 0; + font-size: 1.25em; + } + + h4 { + margin: 24px 0 12px 0; + font-size: 1.1em; + } + + h5 { + margin: 24px 0 12px 0; + font-size: 1em; + } + + h6 { + margin: 24px 0 12px 0; + font-size: 0.90em; + } + + blockquote { + padding: 8px 21px; + margin: 12px 0 12px; + border-left: 3px solid #e7e9ed; + } + + blockquote p { + color: #7f8fa4 !important; + font-size: 15px; + line-height: 1.5; + } + + p { + color:#5c5d5e; + margin:6px 0 0 0; + } + + table { + @extend .table; + @extend .table-bordered; + margin: 12px 0 12px 0; + color: #5c5d5e; + th { + background: #f8fafc; + } + } + + pre { + margin: 12px 0 12px 0 !important; + background-color: #f8fafc !important; + font-size: 13px !important; + color: #5b6169 !important; + line-height: 1.6em !important; + @include border-radius(2px); + } + + p > code { + font-weight: inherit; + } + + + ul { + color: #5c5d5e; + } + + li { + line-height: 1.6em; + } + + a[href*="/uploads/"], a[href*="storage.googleapis.com/google-code-attachments/"] { + &:before { + margin-right: 4px; + + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + content: "\f0c6"; + } + + &:hover:before { + text-decoration: none; + } + } +} + + /** * Headers * @@ -6,7 +147,7 @@ body { text-rendering:optimizeLegibility; -webkit-text-shadow: rgba(255,255,255,0.01) 0 0 1px; } - + .page-title { margin-top: 0px; line-height: 1.3; @@ -127,4 +268,4 @@ textarea.js-gfm-input { .strikethrough { text-decoration: line-through; -} \ No newline at end of file +} -- cgit v1.2.1 From 029edcc391d492c30f0598e70dba3433189806c7 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 13 Oct 2015 11:02:44 +0200 Subject: Fix padding for controls in list Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/framework/lists.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss index 3bfed8de772..fdfbb886926 100644 --- a/app/assets/stylesheets/framework/lists.scss +++ b/app/assets/stylesheets/framework/lists.scss @@ -117,7 +117,7 @@ ul.content-list { } .controls { - padding-top: 10px; + padding-top: 5px; float: right; } } -- cgit v1.2.1 From f1e3894973abd96a318b5f3f56bfce110c620c39 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 13 Oct 2015 11:23:10 +0200 Subject: Remove unused twbs components Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/framework/tw_bootstrap.scss | 2 -- app/assets/stylesheets/pages/note_form.scss | 1 - 2 files changed, 3 deletions(-) diff --git a/app/assets/stylesheets/framework/tw_bootstrap.scss b/app/assets/stylesheets/framework/tw_bootstrap.scss index 722b44d2d10..99d028d1228 100644 --- a/app/assets/stylesheets/framework/tw_bootstrap.scss +++ b/app/assets/stylesheets/framework/tw_bootstrap.scss @@ -32,8 +32,6 @@ @import "bootstrap/pager"; @import "bootstrap/labels"; @import "bootstrap/badges"; -@import "bootstrap/jumbotron"; -@import "bootstrap/thumbnails"; @import "bootstrap/alerts"; @import "bootstrap/progress-bars"; @import "bootstrap/list-group"; diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss index dcd1aed7196..4392f08942b 100644 --- a/app/assets/stylesheets/pages/note_form.scss +++ b/app/assets/stylesheets/pages/note_form.scss @@ -65,7 +65,6 @@ .note-image-attach { @extend .col-md-4; - @extend .thumbnail; margin-left: 45px; float: none; } -- cgit v1.2.1 From ab604c73ef986d03d5c5c04075663d87ef390479 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 13 Oct 2015 11:33:46 +0200 Subject: Temporary return sm and xs button sizes Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/framework/buttons.scss | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss index 11acbe3adfa..e5f0c0ad9ef 100644 --- a/app/assets/stylesheets/framework/buttons.scss +++ b/app/assets/stylesheets/framework/buttons.scss @@ -6,7 +6,7 @@ font-size: 13px; font-weight: 600; line-height: 18px; - padding: 11px 16px; + padding: 11px $gl-padding; letter-spacing: .4px; &:focus, @@ -71,6 +71,14 @@ @include btn-default; @include btn-white; + &.btn-sm { + padding: 5px 10px; + } + + &.btn-xs { + padding: 1px 5px; + } + &.btn-success, &.btn-new, &.btn-create, -- cgit v1.2.1 From e7cc554cc181cbb850f89af26e64a9ab56116f28 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Tue, 13 Oct 2015 11:50:37 +0200 Subject: Fix retry and cancel URLs --- app/models/ci/build.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index cb6a1015210..f8c731a7bf7 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -219,13 +219,15 @@ module Ci def cancel_url if active? - cancel_namespace_project_build_path(gl_project.namespace, gl_project, self, return_to: request.original_url) + Gitlab::Application.routes.url_helpers. + cancel_namespace_project_build_path(gl_project.namespace, gl_project, self, return_to: request.original_url) end end def retry_url if commands.present? - cancel_namespace_project_build_path(gl_project.namespace, gl_project, self, return_to: request.original_url) + Gitlab::Application.routes.url_helpers. + cancel_namespace_project_build_path(gl_project.namespace, gl_project, self, return_to: request.original_url) end end -- cgit v1.2.1 From 4ad61519f9f9cdc82b1ee6bd1ed92905692c7e7f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 13 Oct 2015 13:02:27 +0200 Subject: Fix control buttons in lists Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/framework/lists.scss | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss index fdfbb886926..c5764c36597 100644 --- a/app/assets/stylesheets/framework/lists.scss +++ b/app/assets/stylesheets/framework/lists.scss @@ -117,8 +117,12 @@ ul.content-list { } .controls { - padding-top: 5px; + padding-top: 4px; float: right; + + .btn { + padding: 10px 14px; + } } } } -- cgit v1.2.1 From 219451241a92ff9e81dcb77914e6d659ea2f7376 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 13 Oct 2015 13:03:27 +0200 Subject: Fix UI issue on project page with no ssh key message Signed-off-by: Dmitriy Zaporozhets --- app/views/layouts/_page.html.haml | 3 ++- app/views/projects/show.html.haml | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml index 2468687b56d..1a883e20e89 100644 --- a/app/views/layouts/_page.html.haml +++ b/app/views/layouts/_page.html.haml @@ -6,7 +6,7 @@ = brand_header_logo .gitlab-text-container %h3 GitLab - + - if defined?(sidebar) && sidebar = render "layouts/nav/#{sidebar}" - elsif current_user @@ -23,6 +23,7 @@ = current_user.username .content-wrapper = render "layouts/flash" + = yield :flash_message %div{ class: container_class } .content .clearfix diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index efa119edd5a..e95d987d74c 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -2,9 +2,10 @@ - if current_user = auto_discovery_link_tag(:atom, namespace_project_path(@project.namespace, @project, format: :atom, private_token: current_user.private_token), title: "#{@project.name} activity") -- if current_user && can?(current_user, :download_code, @project) - = render 'shared/no_ssh' - = render 'shared/no_password' += content_for :flash_message do + - if current_user && can?(current_user, :download_code, @project) + = render 'shared/no_ssh' + = render 'shared/no_password' - if prefer_readme? = render 'projects/last_push' -- cgit v1.2.1 From e75655950d27eff75dba0aadd2f853f84034bb3a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 13 Oct 2015 13:37:15 +0200 Subject: Several fixes for UI on mobile Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/framework/mobile.scss | 14 +++++++++++--- app/assets/stylesheets/pages/projects.scss | 1 + 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/app/assets/stylesheets/framework/mobile.scss b/app/assets/stylesheets/framework/mobile.scss index 36ae126f865..cea47fba192 100644 --- a/app/assets/stylesheets/framework/mobile.scss +++ b/app/assets/stylesheets/framework/mobile.scss @@ -23,7 +23,7 @@ margin-right: 0; } - .issues-filters, + .issues-details-filters, .dash-projects-filters, .check-all-holder { display: none; @@ -83,6 +83,7 @@ .center-top-menu { height: 45px; + margin-bottom: 30px; li a { font-size: 14px; @@ -90,9 +91,11 @@ } } - .projects-search-form { - margin: 0 -5px !important; + .activity-filter-block { + display: none; + } + .projects-search-form { .btn { display: none; } @@ -100,6 +103,11 @@ } @media (max-width: $screen-sm-max) { + .page-with-sidebar .content-wrapper { + padding: 0; + padding-top: 1px; + } + .issues-filters { .milestone-filter, .labels-filter { display: none; diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 0031ab5151b..9d42c0f28e7 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -63,6 +63,7 @@ } p { + padding: 0 $gl-padding; color: #5c5d5e; } } -- cgit v1.2.1 From 2f68fb9cc3622eb90c955b6936e91ea766f262b6 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 13 Oct 2015 14:38:38 +0200 Subject: Small css cleanup Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/framework/common.scss | 4 ---- app/assets/stylesheets/pages/projects.scss | 5 ----- app/views/dashboard/_activities.html.haml | 7 +++---- app/views/groups/show.html.haml | 8 +++----- app/views/projects/_activity.html.haml | 7 +++---- app/views/projects/buttons/_notifications.html.haml | 2 +- app/views/projects/new.html.haml | 4 ++-- 7 files changed, 12 insertions(+), 25 deletions(-) diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss index 03919f15f1f..e1a1793be9c 100644 --- a/app/assets/stylesheets/framework/common.scss +++ b/app/assets/stylesheets/framework/common.scss @@ -398,7 +398,3 @@ table { .space-right { margin-right: 10px; } - -.in-line { - display: inline-block; -} diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 9d42c0f28e7..f7a22849003 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -511,8 +511,3 @@ pre.light-well { margin-top: -1px; } } - -.inline-form { - display: inline-block; -} - diff --git a/app/views/dashboard/_activities.html.haml b/app/views/dashboard/_activities.html.haml index 19d919f9b6a..f98fd9f06ba 100644 --- a/app/views/dashboard/_activities.html.haml +++ b/app/views/dashboard/_activities.html.haml @@ -3,10 +3,9 @@ .gray-content-block - if current_user - %ul.nav.nav-pills.event_filter.pull-right - %li.pull-right - = link_to dashboard_projects_path(:atom, { private_token: current_user.private_token }), class: 'rss-btn' do - %i.fa.fa-rss + .pull-right + = link_to dashboard_projects_path(:atom, { private_token: current_user.private_token }), class: 'btn rss-btn' do + %i.fa.fa-rss = render 'shared/event_filter' .content_list diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml index a9ba9d2ba10..dc8e81323a6 100644 --- a/app/views/groups/show.html.haml +++ b/app/views/groups/show.html.haml @@ -25,11 +25,9 @@ .hidden-xs - if current_user = render "events/event_last_push", event: @last_push - - %ul.nav.nav-pills.event_filter.pull-right - %li - = link_to group_path(@group, { format: :atom, private_token: current_user.private_token }), title: "Feed", class: 'rss-btn' do - %i.fa.fa-rss + .pull-right + = link_to group_path(@group, { format: :atom, private_token: current_user.private_token }), title: "Feed", class: 'btn rss-btn' do + %i.fa.fa-rss = render 'shared/event_filter' %hr diff --git a/app/views/projects/_activity.html.haml b/app/views/projects/_activity.html.haml index 1261f6254d7..c2683bc6219 100644 --- a/app/views/projects/_activity.html.haml +++ b/app/views/projects/_activity.html.haml @@ -1,10 +1,9 @@ = render 'projects/last_push' .gray-content-block.activity-filter-block - if current_user - %ul.nav.nav-pills.event_filter.pull-right - %li - = link_to namespace_project_path(@project.namespace, @project, format: :atom, private_token: current_user.private_token), title: "Feed", class: 'rss-btn' do - %i.fa.fa-rss + .pull-right + = link_to namespace_project_path(@project.namespace, @project, format: :atom, private_token: current_user.private_token), title: "Feed", class: 'btn rss-btn' do + %i.fa.fa-rss = render 'shared/event_filter' .content_list{:"data-href" => activity_project_path(@project)} diff --git a/app/views/projects/buttons/_notifications.html.haml b/app/views/projects/buttons/_notifications.html.haml index 4b69a6d7a6f..3bc2daeec4e 100644 --- a/app/views/projects/buttons/_notifications.html.haml +++ b/app/views/projects/buttons/_notifications.html.haml @@ -1,6 +1,6 @@ - return unless @membership -= form_tag profile_notifications_path, method: :put, remote: true, class: 'inline-form', id: 'notification-form' do += form_tag profile_notifications_path, method: :put, remote: true, class: 'inline', id: 'notification-form' do = hidden_field_tag :notification_type, 'project' = hidden_field_tag :notification_id, @membership.id = hidden_field_tag :notification_level diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml index 1b093c8f514..daab2326bc7 100644 --- a/app/views/projects/new.html.haml +++ b/app/views/projects/new.html.haml @@ -111,10 +111,10 @@ - if current_user.can_create_group? .pull-right - .light.in-line + .light.inline .space-right Need a group for several dependent projects? - = link_to new_group_path, class: "btn btn-xs" do + = link_to new_group_path, class: "btn" do Create a group .save-project-loader.hide -- cgit v1.2.1 From a0a488ed13e2a07e0dd42e8795c50ea762917f20 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 13 Oct 2015 16:41:48 +0200 Subject: Apply new design to files page Signed-off-by: Dmitriy Zaporozhets --- CHANGELOG | 1 + app/assets/javascripts/line_highlighter.js.coffee | 6 +- app/assets/stylesheets/framework/tables.scss | 2 +- .../framework/tw_bootstrap_variables.scss | 2 + app/assets/stylesheets/framework/variables.scss | 1 + app/assets/stylesheets/pages/tree.scss | 34 +++---- app/views/projects/blob/_blob.html.haml | 2 +- .../repositories/_download_archive.html.haml | 4 +- app/views/projects/tree/_readme.html.haml | 13 +-- app/views/projects/tree/_tree.html.haml | 106 +++++++++++---------- .../fixtures/line_highlighter.html.haml | 2 +- spec/javascripts/line_highlighter_spec.js.coffee | 2 +- 12 files changed, 87 insertions(+), 88 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 8f0bbb12d7b..8b3df158a04 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -47,6 +47,7 @@ v 8.1.0 (unreleased) - Persist filters when sorting on admin user page (Jerry Lukins) - Add spellcheck=false to certain input fields - Invalidate stored service password if the endpoint URL is changed + - Apply new design for Files page v 8.0.4 - Fix Message-ID header to be RFC 2111-compliant to prevent e-mails being dropped (Stan Hu) diff --git a/app/assets/javascripts/line_highlighter.js.coffee b/app/assets/javascripts/line_highlighter.js.coffee index e604e6025c2..2254a3f91ae 100644 --- a/app/assets/javascripts/line_highlighter.js.coffee +++ b/app/assets/javascripts/line_highlighter.js.coffee @@ -6,7 +6,7 @@ # # ### Example Markup # -#
+#
#
#
# 1 @@ -53,7 +53,7 @@ class @LineHighlighter $.scrollTo("#L#{range[0]}", offset: -150) bindEvents: -> - $('#tree-content-holder').on 'mousedown', 'a[data-line-number]', @clickHandler + $('#blob-content-holder').on 'mousedown', 'a[data-line-number]', @clickHandler # While it may seem odd to bind to the mousedown event and then throw away # the click event, there is a method to our madness. @@ -62,7 +62,7 @@ class @LineHighlighter # active state even when the event is cancelled, resulting in an ugly border # around the link and/or a persisted underline text decoration. - $('#tree-content-holder').on 'click', 'a[data-line-number]', (event) -> + $('#blob-content-holder').on 'click', 'a[data-line-number]', (event) -> event.preventDefault() clickHandler: (event) => diff --git a/app/assets/stylesheets/framework/tables.scss b/app/assets/stylesheets/framework/tables.scss index 76163b3a05e..789b34020c1 100644 --- a/app/assets/stylesheets/framework/tables.scss +++ b/app/assets/stylesheets/framework/tables.scss @@ -28,7 +28,7 @@ table { border-bottom: 1px solid $border-color !important; } td { - border-color: #F1F1F1 !important; + border-color: $table-border-color !important; border-bottom: 1px solid; } } diff --git a/app/assets/stylesheets/framework/tw_bootstrap_variables.scss b/app/assets/stylesheets/framework/tw_bootstrap_variables.scss index 18632da4f2a..63868a34e2a 100644 --- a/app/assets/stylesheets/framework/tw_bootstrap_variables.scss +++ b/app/assets/stylesheets/framework/tw_bootstrap_variables.scss @@ -156,3 +156,5 @@ $nav-link-padding: 13px $gl-padding; $pre-bg: #f8fafc !default; $pre-color: $gl-gray !default; $pre-border-color: #e7e9ed; + +$table-bg-accent: $background-color; diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index eb9a2966389..91954683c3e 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -16,6 +16,7 @@ $avatar_radius: 50%; $code_font_size: 13px; $code_line_height: 1.5; $border-color: #dce0e6; +$table-border-color: #eef0f2; $background-color: #F7F8FA; $header-height: 58px; $fixed-layout-width: 1200px; diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss index 271cc547e2b..dadd86e88cc 100644 --- a/app/assets/stylesheets/pages/tree.scss +++ b/app/assets/stylesheets/pages/tree.scss @@ -1,7 +1,7 @@ .tree-holder { - .tree-content-holder { - float: left; - width: 100%; + .tree-table-holder { + margin-left: -$gl-padding; + margin-right: -$gl-padding; } .tree_progress { @@ -13,10 +13,15 @@ } .tree-table { - @extend .table; - @include border-radius(0); + margin-bottom: 0; tr { + > td, > th { + padding: 10px $gl-padding; + line-height: 32px; + border-color: $table-border-color !important; + } + &:hover { td { background: $hover; @@ -27,9 +32,9 @@ } &.selected { td { - background: $background-color; - border-top: 1px solid #EEE; - border-bottom: 1px solid #EEE; + background: $gray-dark; + border-top: 1px solid $border-gray-dark; + border-bottom: 1px solid $border-gray-dark; } } } @@ -85,19 +90,6 @@ margin-right: 15px; } -.readme-holder { - margin: 0 auto; - - .readme-file-title { - font-size: 14px; - font-weight: bold; - margin-bottom: 20px; - color: #777; - border-bottom: 1px solid #DDD; - padding: 10px 0; - } -} - .blob-commit-info { list-style: none; margin: 0; diff --git a/app/views/projects/blob/_blob.html.haml b/app/views/projects/blob/_blob.html.haml index b4c7d8b9b71..a1ae1397584 100644 --- a/app/views/projects/blob/_blob.html.haml +++ b/app/views/projects/blob/_blob.html.haml @@ -19,7 +19,7 @@ - blob_commit = @repository.last_commit_for_path(@commit.id, blob.path) = render blob_commit, project: @project -%div#tree-content-holder.tree-content-holder +%div#blob-content-holder.blob-content-holder %article.file-holder .file-title = blob_icon blob.mode, blob.name diff --git a/app/views/projects/repositories/_download_archive.html.haml b/app/views/projects/repositories/_download_archive.html.haml index b9486a9b492..07c24950ee2 100644 --- a/app/views/projects/repositories/_download_archive.html.haml +++ b/app/views/projects/repositories/_download_archive.html.haml @@ -3,10 +3,10 @@ - split_button = split_button || false - if split_button == true %span.btn-group{class: btn_class} - = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'zip'), class: 'btn col-xs-10', rel: 'nofollow' do + = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'zip'), class: 'btn btn-success col-xs-10', rel: 'nofollow' do %i.fa.fa-download %span Download zip - %a.col-xs-2.btn.dropdown-toggle{ 'data-toggle' => 'dropdown' } + %a.col-xs-2.btn.btn-success.dropdown-toggle{ 'data-toggle' => 'dropdown' } %span.caret %span.sr-only Select Archive Format diff --git a/app/views/projects/tree/_readme.html.haml b/app/views/projects/tree/_readme.html.haml index f082d711865..7e9af19c8ba 100644 --- a/app/views/projects/tree/_readme.html.haml +++ b/app/views/projects/tree/_readme.html.haml @@ -1,7 +1,8 @@ -%article.readme-holder#README - = link_to '#README' do - %h4.readme-file-title - %i.fa.fa-file - = readme.name - .wiki +%article.file-holder.readme-holder#README + .file-title + = link_to '#README' do + %strong + %i.fa.fa-file + = readme.name + .file-content.wiki = render_readme(readme) diff --git a/app/views/projects/tree/_tree.html.haml b/app/views/projects/tree/_tree.html.haml index 457f8a4a585..7ff48e32e60 100644 --- a/app/views/projects/tree/_tree.html.haml +++ b/app/views/projects/tree/_tree.html.haml @@ -1,59 +1,61 @@ -%ul.breadcrumb.repo-breadcrumb - %li - = link_to namespace_project_tree_path(@project.namespace, @project, @ref) do - = @project.path - - tree_breadcrumbs(tree, 6) do |title, path| +.gray-content-block + %ul.breadcrumb.repo-breadcrumb %li - - if path - = link_to truncate(title, length: 40), namespace_project_tree_path(@project.namespace, @project, path) - - else - = link_to title, '#' - - if allowed_tree_edit? - %li - %span.dropdown - %a.dropdown-toggle.btn.btn-xs.add-to-tree{href: '#', "data-toggle" => "dropdown"} - = icon('plus') - %ul.dropdown-menu - %li - = link_to namespace_project_new_blob_path(@project.namespace, @project, @id), title: 'Create file', id: 'new-file-link' do - = icon('pencil fw') - Create file - %li - = link_to '#modal-upload-blob', { 'data-target' => '#modal-upload-blob', 'data-toggle' => 'modal'} do - = icon('file fw') - Upload file - %li.divider - %li - = link_to '#modal-create-new-dir', { 'data-target' => '#modal-create-new-dir', 'data-toggle' => 'modal'} do - = icon('folder fw') - New directory + = link_to namespace_project_tree_path(@project.namespace, @project, @ref) do + = @project.path + - tree_breadcrumbs(tree, 6) do |title, path| + %li + - if path + = link_to truncate(title, length: 40), namespace_project_tree_path(@project.namespace, @project, path) + - else + = link_to title, '#' + - if allowed_tree_edit? + %li + %span.dropdown + %a.dropdown-toggle.btn.add-to-tree{href: '#', "data-toggle" => "dropdown"} + = icon('plus') + %ul.dropdown-menu + %li + = link_to namespace_project_new_blob_path(@project.namespace, @project, @id), title: 'Create file', id: 'new-file-link' do + = icon('pencil fw') + Create file + %li + = link_to '#modal-upload-blob', { 'data-target' => '#modal-upload-blob', 'data-toggle' => 'modal'} do + = icon('file fw') + Upload file + %li.divider + %li + = link_to '#modal-create-new-dir', { 'data-target' => '#modal-create-new-dir', 'data-toggle' => 'modal'} do + = icon('folder fw') + New directory -%div#tree-content-holder.tree-content-holder.prepend-top-20 - %table#tree-slider{class: "table_#{@hex_path} tree-table" } - %thead - %tr - %th Name - %th Last Update - %th.hidden-xs - .pull-left Last Commit - .last-commit.hidden-sm.pull-left -   - %i.fa.fa-angle-right -   - %small.light - = link_to @commit.short_id, namespace_project_commit_path(@project.namespace, @project, @commit) - – - = truncate(@commit.title, length: 50) - = link_to 'History', namespace_project_commits_path(@project.namespace, @project, @id), class: 'pull-right' +%div#tree-content-holder.tree-content-holder + .tree-table-holder + %table.table#tree-slider{class: "table_#{@hex_path} tree-table table-striped" } + %thead + %tr + %th Name + %th Last Update + %th.hidden-xs + .pull-left Last Commit + .last-commit.hidden-sm.pull-left +   + %i.fa.fa-angle-right +   + %small.light + = link_to @commit.short_id, namespace_project_commit_path(@project.namespace, @project, @commit) + – + = truncate(@commit.title, length: 50) + = link_to 'History', namespace_project_commits_path(@project.namespace, @project, @id), class: 'pull-right' - - if @path.present? - %tr.tree-item - %td.tree-item-file-name - = link_to "..", namespace_project_tree_path(@project.namespace, @project, up_dir_path), class: 'prepend-left-10' - %td - %td.hidden-xs + - if @path.present? + %tr.tree-item + %td.tree-item-file-name + = link_to "..", namespace_project_tree_path(@project.namespace, @project, up_dir_path), class: 'prepend-left-10' + %td + %td.hidden-xs - = render_tree(tree) + = render_tree(tree) - if tree.readme = render "projects/tree/readme", readme: tree.readme diff --git a/spec/javascripts/fixtures/line_highlighter.html.haml b/spec/javascripts/fixtures/line_highlighter.html.haml index da1ebcdb23c..514877340e4 100644 --- a/spec/javascripts/fixtures/line_highlighter.html.haml +++ b/spec/javascripts/fixtures/line_highlighter.html.haml @@ -1,4 +1,4 @@ -#tree-content-holder +#blob-content-holder .file-content .line-numbers - 1.upto(25) do |i| diff --git a/spec/javascripts/line_highlighter_spec.js.coffee b/spec/javascripts/line_highlighter_spec.js.coffee index 57453c716a5..a073f21e7bc 100644 --- a/spec/javascripts/line_highlighter_spec.js.coffee +++ b/spec/javascripts/line_highlighter_spec.js.coffee @@ -39,7 +39,7 @@ describe 'LineHighlighter', -> expect(spy).toHaveBeenPrevented() it 'handles garbage input from the hash', -> - func = -> new LineHighlighter('#tree-content-holder') + func = -> new LineHighlighter('#blob-content-holder') expect(func).not.toThrow() describe '#clickHandler', -> -- cgit v1.2.1 From a092d27025cbaf4abe8a1198a25c5becfc07c9b1 Mon Sep 17 00:00:00 2001 From: sue445 Date: Wed, 14 Oct 2015 00:30:48 +0900 Subject: [ci skip] Fix wrong comment According to `attributes_for_keys` and API doc, `POST /projects/:id/merge_requests` is received `target_project_id` (NOT `target_project`) --- lib/api/merge_requests.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb index 63ea2f05438..f3a59fadf24 100644 --- a/lib/api/merge_requests.rb +++ b/lib/api/merge_requests.rb @@ -99,7 +99,7 @@ module API # id (required) - The ID of a project - this will be the source of the merge request # source_branch (required) - The source branch # target_branch (required) - The target branch - # target_project - The target project of the merge request defaults to the :id of the project + # target_project_id - The target project of the merge request defaults to the :id of the project # assignee_id - Assignee user ID # title (required) - Title of MR # description - Description of MR -- cgit v1.2.1 From 2297a7ba1f5d004c877a7cb82510d7d635f90ec0 Mon Sep 17 00:00:00 2001 From: sue445 Date: Wed, 14 Oct 2015 00:40:37 +0900 Subject: [ci skip] Add missing parameters in API doc --- doc/api/merge_requests.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md index bb551fc67f7..ffa7f2cdf14 100644 --- a/doc/api/merge_requests.md +++ b/doc/api/merge_requests.md @@ -188,6 +188,7 @@ Parameters: - `title` (required) - Title of MR - `description` (optional) - Description of MR - `target_project_id` (optional) - The target project (numeric id) +- `labels` (optional) - Labels for MR as a comma-separated list ```json { @@ -239,6 +240,7 @@ Parameters: - `title` - Title of MR - `description` - Description of MR - `state_event` - New state (close|reopen|merge) +- `labels` (optional) - Labels for MR as a comma-separated list ```json { -- cgit v1.2.1 From 135ec3242d803fc46087b59d10016e55207f6743 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 13 Oct 2015 18:27:25 +0200 Subject: Reduce font size of commit references to not stand out as much --- app/assets/stylesheets/generic/gfm.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/app/assets/stylesheets/generic/gfm.scss b/app/assets/stylesheets/generic/gfm.scss index bd9200ace23..5ae0520fd7b 100644 --- a/app/assets/stylesheets/generic/gfm.scss +++ b/app/assets/stylesheets/generic/gfm.scss @@ -22,4 +22,5 @@ .gfm-commit, .gfm-commit_range { font-family: $monospace_font; + font-size: 90%; } -- cgit v1.2.1