diff options
Diffstat (limited to 'app')
33 files changed, 127 insertions, 61 deletions
diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_dropdown_mixin.js b/app/assets/javascripts/create_cluster/gke_cluster/components/gke_dropdown_mixin.js index 5a3407693e5..5a3407693e5 100644 --- a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_dropdown_mixin.js +++ b/app/assets/javascripts/create_cluster/gke_cluster/components/gke_dropdown_mixin.js diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_machine_type_dropdown.vue b/app/assets/javascripts/create_cluster/gke_cluster/components/gke_machine_type_dropdown.vue index 83811ab489a..83811ab489a 100644 --- a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_machine_type_dropdown.vue +++ b/app/assets/javascripts/create_cluster/gke_cluster/components/gke_machine_type_dropdown.vue diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown.vue b/app/assets/javascripts/create_cluster/gke_cluster/components/gke_project_id_dropdown.vue index a2eb79af4f9..a2eb79af4f9 100644 --- a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown.vue +++ b/app/assets/javascripts/create_cluster/gke_cluster/components/gke_project_id_dropdown.vue diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_zone_dropdown.vue b/app/assets/javascripts/create_cluster/gke_cluster/components/gke_zone_dropdown.vue index fd5d5f86401..fd5d5f86401 100644 --- a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_zone_dropdown.vue +++ b/app/assets/javascripts/create_cluster/gke_cluster/components/gke_zone_dropdown.vue diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/constants.js b/app/assets/javascripts/create_cluster/gke_cluster/constants.js index 2a1c0819916..2a1c0819916 100644 --- a/app/assets/javascripts/projects/gke_cluster_dropdowns/constants.js +++ b/app/assets/javascripts/create_cluster/gke_cluster/constants.js diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/index.js b/app/assets/javascripts/create_cluster/gke_cluster/index.js index 729b9404b64..729b9404b64 100644 --- a/app/assets/javascripts/projects/gke_cluster_dropdowns/index.js +++ b/app/assets/javascripts/create_cluster/gke_cluster/index.js diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/store/actions.js b/app/assets/javascripts/create_cluster/gke_cluster/store/actions.js index f05ad7773a2..f05ad7773a2 100644 --- a/app/assets/javascripts/projects/gke_cluster_dropdowns/store/actions.js +++ b/app/assets/javascripts/create_cluster/gke_cluster/store/actions.js diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/store/getters.js b/app/assets/javascripts/create_cluster/gke_cluster/store/getters.js index f9e2e2f74fb..f9e2e2f74fb 100644 --- a/app/assets/javascripts/projects/gke_cluster_dropdowns/store/getters.js +++ b/app/assets/javascripts/create_cluster/gke_cluster/store/getters.js diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/store/index.js b/app/assets/javascripts/create_cluster/gke_cluster/store/index.js index 5f72060633e..5f72060633e 100644 --- a/app/assets/javascripts/projects/gke_cluster_dropdowns/store/index.js +++ b/app/assets/javascripts/create_cluster/gke_cluster/store/index.js diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/store/mutation_types.js b/app/assets/javascripts/create_cluster/gke_cluster/store/mutation_types.js index 45a91efc2d9..45a91efc2d9 100644 --- a/app/assets/javascripts/projects/gke_cluster_dropdowns/store/mutation_types.js +++ b/app/assets/javascripts/create_cluster/gke_cluster/store/mutation_types.js diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/store/mutations.js b/app/assets/javascripts/create_cluster/gke_cluster/store/mutations.js index 88a2c1b630d..88a2c1b630d 100644 --- a/app/assets/javascripts/projects/gke_cluster_dropdowns/store/mutations.js +++ b/app/assets/javascripts/create_cluster/gke_cluster/store/mutations.js diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/store/state.js b/app/assets/javascripts/create_cluster/gke_cluster/store/state.js index 9f3c473d4bc..9f3c473d4bc 100644 --- a/app/assets/javascripts/projects/gke_cluster_dropdowns/store/state.js +++ b/app/assets/javascripts/create_cluster/gke_cluster/store/state.js diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js index 39f2097c174..0ddf40b0405 100644 --- a/app/assets/javascripts/main.js +++ b/app/assets/javascripts/main.js @@ -35,6 +35,7 @@ import initPerformanceBar from './performance_bar'; import initSearchAutocomplete from './search_autocomplete'; import GlFieldErrors from './gl_field_errors'; import initUserPopovers from './user_popovers'; +import { initUserTracking } from './tracking'; import { __ } from './locale'; import 'ee_else_ce/main_ee'; @@ -94,6 +95,7 @@ function deferredInitialisation() { initLogoAnimation(); initUsagePingConsent(); initUserPopovers(); + initUserTracking(); if (document.querySelector('.search')) initSearchAutocomplete(); diff --git a/app/assets/javascripts/pages/admin/clusters/index.js b/app/assets/javascripts/pages/admin/clusters/index.js index d0c9ae66c6a..43992938d07 100644 --- a/app/assets/javascripts/pages/admin/clusters/index.js +++ b/app/assets/javascripts/pages/admin/clusters/index.js @@ -1,5 +1,5 @@ import PersistentUserCallout from '~/persistent_user_callout'; -import initGkeDropdowns from '~/projects/gke_cluster_dropdowns'; +import initGkeDropdowns from '~/create_cluster/gke_cluster'; function initGcpSignupCallout() { const callout = document.querySelector('.gcp-signup-offer'); diff --git a/app/assets/javascripts/pages/groups/index.js b/app/assets/javascripts/pages/groups/index.js index 451be6497de..a33d242908b 100644 --- a/app/assets/javascripts/pages/groups/index.js +++ b/app/assets/javascripts/pages/groups/index.js @@ -1,5 +1,5 @@ import PersistentUserCallout from '~/persistent_user_callout'; -import initGkeDropdowns from '~/projects/gke_cluster_dropdowns'; +import initGkeDropdowns from '~/create_cluster/gke_cluster'; function initGcpSignupCallout() { const callout = document.querySelector('.gcp-signup-offer'); diff --git a/app/assets/javascripts/pages/projects/index.js b/app/assets/javascripts/pages/projects/index.js index 55c377ebec0..196798a9076 100644 --- a/app/assets/javascripts/pages/projects/index.js +++ b/app/assets/javascripts/pages/projects/index.js @@ -1,4 +1,4 @@ -import initGkeDropdowns from '~/projects/gke_cluster_dropdowns'; +import initGkeDropdowns from '~/create_cluster/gke_cluster'; import initGkeNamespace from '~/projects/gke_cluster_namespace'; import PersistentUserCallout from '../../persistent_user_callout'; import Project from './project'; diff --git a/app/assets/javascripts/tracking.js b/app/assets/javascripts/tracking.js index a852f937eec..03281b5ef49 100644 --- a/app/assets/javascripts/tracking.js +++ b/app/assets/javascripts/tracking.js @@ -1,5 +1,23 @@ import $ from 'jquery'; +const DEFAULT_SNOWPLOW_OPTIONS = { + namespace: 'gl', + hostname: window.location.hostname, + cookieDomain: window.location.hostname, + appId: '', + userFingerprint: false, + respectDoNotTrack: true, + forceSecureTracker: true, + eventMethod: 'post', + contexts: { webPage: true }, + // Page tracking tracks a single event when the page loads. + pageTrackingEnabled: false, + // Activity tracking tracks when a user is still interacting with the page. + // Events like scrolling and mouse movements are used to determine if the + // user has the tab active and is still actively engaging. + activityTrackingEnabled: false, +}; + const extractData = (el, opts = {}) => { const { trackEvent, trackLabel = '', trackProperty = '' } = el.dataset; let trackValue = el.dataset.trackValue || el.value || ''; @@ -71,3 +89,13 @@ export default class Tracking { }; } } + +export function initUserTracking() { + if (!Tracking.enabled()) return; + + const opts = Object.assign({}, DEFAULT_SNOWPLOW_OPTIONS, window.snowplowOptions); + window.snowplow('newTracker', opts.namespace, opts.hostname, opts); + + if (opts.activityTrackingEnabled) window.snowplow('enableActivityTracking', 30, 30); + if (opts.pageTrackingEnabled) window.snowplow('trackPageView'); // must be after enableActivityTracking +} diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss index 77a2fd6b876..defa1a6c0d5 100644 --- a/app/assets/stylesheets/pages/diff.scss +++ b/app/assets/stylesheets/pages/diff.scss @@ -2,8 +2,14 @@ .diff-file { margin-bottom: $gl-padding; + &.conflict { + border-top: 1px solid $border-color; + } + .file-title, .file-title-flex-parent { + border-top-left-radius: $border-radius-default; + border-top-right-radius: $border-radius-default; cursor: pointer; @media (min-width: map-get($grid-breakpoints, md)) { @@ -67,6 +73,28 @@ } } + @media (min-width: map-get($grid-breakpoints, md)) { + &.conflict .file-title, + &.conflict .file-title-flex-parent { + top: $header-height; + } + + .with-performance-bar &.conflict .file-title, + .with-performance-bar &.conflict .file-title-flex-parent { + top: $header-height + $performance-bar-height; + } + + .with-system-header &.conflict .file-title, + .with-system-header &.conflict .file-title-flex-parent { + top: $header-height + $system-header-height; + } + + .with-system-header.with-performance-bar &.conflict .file-title, + .with-system-header.with-performance-bar &.conflict .file-title-flex-parent { + top: $header-height + $performance-bar-height + $system-header-height; + } + } + .diff-content { background: $white-light; color: $gl-text-color; diff --git a/app/assets/stylesheets/pages/todos.scss b/app/assets/stylesheets/pages/todos.scss index 7b64c67ae34..ece0ac04baf 100644 --- a/app/assets/stylesheets/pages/todos.scss +++ b/app/assets/stylesheets/pages/todos.scss @@ -72,12 +72,7 @@ @include transition(opacity); .todo-title { - display: flex; - > .title-item { - flex: 0 0 auto; - margin: 0 2px; - &:first-child { margin-left: 0; } @@ -105,8 +100,12 @@ font-size: 14px; } - .action-name { - font-weight: $gl-font-weight-normal; + .todo-label, + .todo-project { + a { + color: $blue-600; + font-weight: $gl-font-weight-normal; + } } .todo-body { @@ -170,7 +169,7 @@ } } -@include media-breakpoint-down(xs) { +@include media-breakpoint-down(sm) { .todo { .avatar { display: none; @@ -179,7 +178,6 @@ .todo-item { .todo-title { - flex-flow: row wrap; margin-bottom: 10px; .todo-label { diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb index 38142bc68cb..f5333bb332e 100644 --- a/app/helpers/todos_helper.rb +++ b/app/helpers/todos_helper.rb @@ -33,7 +33,23 @@ module TodosHelper todo.target_reference end - link_to text, todo_target_path(todo), class: 'has-tooltip', title: todo.target.title + link_to text, todo_target_path(todo) + end + + def todo_target_title(todo) + if todo.target + "\"#{todo.target.title}\"" + else + "" + end + end + + def todo_parent_path(todo) + if todo.parent.is_a?(Group) + link_to todo.parent.name, group_path(todo.parent) + else + link_to_project(todo.project) + end end def todo_target_type_name(todo) diff --git a/app/models/commit.rb b/app/models/commit.rb index 0889ce7e287..1470b50f396 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -35,6 +35,7 @@ class Commit MIN_SHA_LENGTH = Gitlab::Git::Commit::MIN_SHA_LENGTH COMMIT_SHA_PATTERN = /\h{#{MIN_SHA_LENGTH},40}/.freeze + EXACT_COMMIT_SHA_PATTERN = /\A#{COMMIT_SHA_PATTERN}\z/.freeze # Used by GFM to match and present link extensions on node texts and hrefs. LINK_EXTENSION_PATTERN = /(patch)/.freeze @@ -90,7 +91,7 @@ class Commit end def valid_hash?(key) - !!(/\A#{COMMIT_SHA_PATTERN}\z/ =~ key) + !!(EXACT_COMMIT_SHA_PATTERN =~ key) end def lazy(project, oid) @@ -139,6 +140,10 @@ class Commit '@' end + def self.reference_valid?(reference) + !!(reference =~ EXACT_COMMIT_SHA_PATTERN) + end + # Pattern used to extract commit references from text # # This pattern supports cross-project references. diff --git a/app/models/todo.rb b/app/models/todo.rb index 240c91da5b6..1ec04189482 100644 --- a/app/models/todo.rb +++ b/app/models/todo.rb @@ -186,9 +186,9 @@ class Todo < ApplicationRecord def target_reference if for_commit? - target.reference_link_text(full: true) + target.reference_link_text else - target.to_reference(full: true) + target.to_reference end end diff --git a/app/services/base_count_service.rb b/app/services/base_count_service.rb index ad1647842b8..cfad2dd9265 100644 --- a/app/services/base_count_service.rb +++ b/app/services/base_count_service.rb @@ -35,7 +35,7 @@ class BaseCountService end def cache_key - raise NotImplementedError, 'cache_key must be implemented and return a String' + raise NotImplementedError, 'cache_key must be implemented and return a String, Array, or Hash' end # subclasses can override to add any specific options, such as diff --git a/app/views/admin/application_settings/_ip_limits.html.haml b/app/views/admin/application_settings/_ip_limits.html.haml index 67a04fcf698..9512c1837bf 100644 --- a/app/views/admin/application_settings/_ip_limits.html.haml +++ b/app/views/admin/application_settings/_ip_limits.html.haml @@ -4,7 +4,7 @@ %fieldset .form-group .form-check - = f.check_box :throttle_unauthenticated_enabled, class: 'form-check-input' + = f.check_box :throttle_unauthenticated_enabled, class: 'form-check-input', data: { qa_selector: 'throttle_unauthenticated_checkbox' } = f.label :throttle_unauthenticated_enabled, class: 'form-check-label' do Enable unauthenticated request rate limit %span.form-text.text-muted @@ -17,7 +17,7 @@ = f.number_field :throttle_unauthenticated_period_in_seconds, class: 'form-control' .form-group .form-check - = f.check_box :throttle_authenticated_api_enabled, class: 'form-check-input' + = f.check_box :throttle_authenticated_api_enabled, class: 'form-check-input', data: { qa_selector: 'throttle_authenticated_api_checkbox' } = f.label :throttle_authenticated_api_enabled, class: 'form-check-label' do Enable authenticated API request rate limit %span.form-text.text-muted @@ -30,7 +30,7 @@ = f.number_field :throttle_authenticated_api_period_in_seconds, class: 'form-control' .form-group .form-check - = f.check_box :throttle_authenticated_web_enabled, class: 'form-check-input' + = f.check_box :throttle_authenticated_web_enabled, class: 'form-check-input', data: { qa_selector: 'throttle_authenticated_web_checkbox' } = f.label :throttle_authenticated_web_enabled, class: 'form-check-label' do Enable authenticated web request rate limit %span.form-text.text-muted @@ -42,4 +42,4 @@ = f.label :throttle_authenticated_web_period_in_seconds, 'Rate limit period in seconds', class: 'label-bold' = f.number_field :throttle_authenticated_web_period_in_seconds, class: 'form-control' - = f.submit 'Save changes', class: "btn btn-success" + = f.submit 'Save changes', class: "btn btn-success", data: { qa_selector: 'save_changes_button' } diff --git a/app/views/admin/application_settings/network.html.haml b/app/views/admin/application_settings/network.html.haml index 26fd745f45f..3a4d901ca1d 100644 --- a/app/views/admin/application_settings/network.html.haml +++ b/app/views/admin/application_settings/network.html.haml @@ -13,7 +13,7 @@ .settings-content = render 'performance' -%section.settings.as-ip-limits.no-animate#js-ip-limits-settings{ class: ('expanded' if expanded_by_default?) } +%section.settings.as-ip-limits.no-animate#js-ip-limits-settings{ class: ('expanded' if expanded_by_default?), data: { qa_selector: 'ip_limits_section' } } .settings-header %h4 = _('User and IP Rate Limits') diff --git a/app/views/dashboard/todos/_todo.html.haml b/app/views/dashboard/todos/_todo.html.haml index 8cdfc7369a0..fdb71d3a221 100644 --- a/app/views/dashboard/todos/_todo.html.haml +++ b/app/views/dashboard/todos/_todo.html.haml @@ -2,41 +2,49 @@ .todo-avatar = author_avatar(todo, size: 40) - .todo-item.todo-block - .todo-title.title + .todo-item.todo-block.align-self-center + .todo-title - unless todo.build_failed? || todo.unmergeable? = todo_target_state_pill(todo) - .title-item.author-name + %span.title-item.author-name.bold - if todo.author = link_to_author(todo, self_added: todo.self_added?) - else (removed) - .title-item.action-name + %span.title-item.action-name = todo_action_name(todo) - .title-item.todo-label + %span.title-item.todo-label.todo-target-link - if todo.target = todo_target_link(todo) - else - (removed) + = _("(removed)") + + %span.title-item.todo-target-title + = todo_target_title(todo) + + %span.title-item.todo-project.todo-label + at + = todo_parent_path(todo) - if todo.self_assigned? - .title-item.action-name + %span.title-item.action-name to yourself - .title-item + %span.title-item · - .title-item + %span.title-item.todo-timestamp #{time_ago_with_tooltip(todo.created_at)} = todo_due_date(todo) - .todo-body - .todo-note.break-word - .md - = first_line_in_markdown(todo, :body, 150, project: todo.project) + - if todo.note.present? + .todo-body + .todo-note.break-word + .md + = first_line_in_markdown(todo, :body, 150, project: todo.project) - if todo.pending? .todo-actions diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml index 0c8f86c2822..6d06bb246cb 100644 --- a/app/views/groups/edit.html.haml +++ b/app/views/groups/edit.html.haml @@ -14,7 +14,7 @@ .settings-content = render 'groups/settings/general' -%section.settings.gs-permissions.no-animate#js-permissions-settings{ class: ('expanded' if expanded) } +%section.settings.gs-permissions.no-animate#js-permissions-settings{ class: ('expanded' if expanded), data: { qa_selector: 'permission_lfs_2fa_section' } } .settings-header %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only{ role: 'button' } = _('Permissions, LFS, 2FA') diff --git a/app/views/groups/settings/_permissions.html.haml b/app/views/groups/settings/_permissions.html.haml index 94a938021f9..c55730ccd31 100644 --- a/app/views/groups/settings/_permissions.html.haml +++ b/app/views/groups/settings/_permissions.html.haml @@ -31,4 +31,4 @@ = render 'groups/settings/two_factor_auth', f: f = render_if_exists 'groups/member_lock_setting', f: f, group: @group - = f.submit _('Save changes'), class: 'btn btn-success prepend-top-default js-dirty-submit' + = f.submit _('Save changes'), class: 'btn btn-success prepend-top-default js-dirty-submit', data: { qa_selector: 'save_permissions_changes_button' } diff --git a/app/views/layouts/_snowplow.html.haml b/app/views/layouts/_snowplow.html.haml index 5f5c5e984c5..d7ff5ad1094 100644 --- a/app/views/layouts/_snowplow.html.haml +++ b/app/views/layouts/_snowplow.html.haml @@ -7,23 +7,4 @@ };p[i].q=p[i].q||[];n=l.createElement(o);g=l.getElementsByTagName(o)[0];n.async=1; n.src=w;g.parentNode.insertBefore(n,g)}}(window,document,"script","#{asset_url('snowplow/sp.js')}","snowplow")); - window.snowplow('newTracker', '#{Gitlab::SnowplowTracker::NAMESPACE}', '#{Gitlab::CurrentSettings.snowplow_collector_hostname}', { - appId: '#{Gitlab::CurrentSettings.snowplow_site_id}', - cookieDomain: '#{Gitlab::CurrentSettings.snowplow_cookie_domain}', - userFingerprint: false, - respectDoNotTrack: true, - forceSecureTracker: true, - post: true, - contexts: { webPage: true }, - stateStorageStrategy: "localStorage" - }); - - window.snowplow('enableActivityTracking', 30, 30); - window.snowplow('trackPageView'); - -- return unless Feature.enabled?(:additional_snowplow_tracking, @group) - -= javascript_tag nonce: true do - :plain - window.snowplow('enableFormTracking'); - window.snowplow('enableLinkClickTracking'); + window.snowplowOptions = #{Gitlab::Tracking.snowplow_options(@group).to_json} diff --git a/app/views/layouts/nav/sidebar/_admin.html.haml b/app/views/layouts/nav/sidebar/_admin.html.haml index cb39c830170..9e92ced9f89 100644 --- a/app/views/layouts/nav/sidebar/_admin.html.haml +++ b/app/views/layouts/nav/sidebar/_admin.html.haml @@ -261,7 +261,7 @@ %span = _('Metrics and profiling') = nav_link(path: 'application_settings#network') do - = link_to network_admin_application_settings_path, title: _('Network') do + = link_to network_admin_application_settings_path, title: _('Network'), data: { qa_selector: 'admin_settings_network_item' } do %span = _('Network') - if template_exists?('admin/application_settings/geo') diff --git a/app/views/layouts/nav/sidebar/_group.html.haml b/app/views/layouts/nav/sidebar/_group.html.haml index 48c9f19f89f..c1f4b3adfec 100644 --- a/app/views/layouts/nav/sidebar/_group.html.haml +++ b/app/views/layouts/nav/sidebar/_group.html.haml @@ -147,7 +147,7 @@ = _('Settings') %li.divider.fly-out-top-item = nav_link(path: 'groups#edit') do - = link_to edit_group_path(@group), title: _('General') do + = link_to edit_group_path(@group), title: _('General'), data: { qa_selector: 'general_settings_link' } do %span = _('General') diff --git a/app/views/layouts/nav/sidebar/_project.html.haml b/app/views/layouts/nav/sidebar/_project.html.haml index 02ecf816e90..48fea2bbecf 100644 --- a/app/views/layouts/nav/sidebar/_project.html.haml +++ b/app/views/layouts/nav/sidebar/_project.html.haml @@ -115,7 +115,7 @@ = _('List') = nav_link(controller: :boards) do - = link_to project_boards_path(@project), title: boards_link_text do + = link_to project_boards_path(@project), title: boards_link_text, data: { qa_selector: "issue_boards_link" } do %span = boards_link_text diff --git a/app/views/shared/boards/_show.html.haml b/app/views/shared/boards/_show.html.haml index 4f0be117035..93fc839a371 100644 --- a/app/views/shared/boards/_show.html.haml +++ b/app/views/shared/boards/_show.html.haml @@ -4,7 +4,7 @@ - @no_container = true - @content_class = "issue-boards-content js-focus-mode-board" - breadcrumb_title _("Issue Boards") -- page_title _("Boards") +- page_title("#{board.name}", _("Boards")) - content_for :page_specific_javascripts do |